]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/commitdiff
Merge remote-tracking branches 'spi/topic/fsl-dspi', 'spi/topic/mpc512x', 'spi/topic...
authorMark Brown <broonie@kernel.org>
Wed, 4 Nov 2015 11:02:10 +0000 (11:02 +0000)
committerMark Brown <broonie@kernel.org>
Wed, 4 Nov 2015 11:02:10 +0000 (11:02 +0000)
1701 files changed:
.mailmap
Documentation/Changes
Documentation/arm/OMAP/README [new file with mode: 0644]
Documentation/device-mapper/snapshot.txt
Documentation/devicetree/bindings/arm/gic-v3.txt
Documentation/devicetree/bindings/arm/idle-states.txt
Documentation/devicetree/bindings/gpio/gpio.txt
Documentation/devicetree/bindings/iio/accel/bma180.txt
Documentation/devicetree/bindings/input/cypress,cyapa.txt
Documentation/devicetree/bindings/interrupt-controller/qca,ath79-misc-intc.txt
Documentation/devicetree/bindings/net/cpsw.txt
Documentation/devicetree/bindings/net/smsc-lan87xx.txt [new file with mode: 0644]
Documentation/devicetree/bindings/pci/pci-rcar-gen2.txt
Documentation/devicetree/bindings/regulator/pbias-regulator.txt
Documentation/devicetree/bindings/spi/brcm,bcm2835-aux-spi.txt [new file with mode: 0644]
Documentation/devicetree/bindings/spi/sh-msiof.txt
Documentation/devicetree/bindings/spi/spi-mt65xx.txt
Documentation/devicetree/bindings/thermal/thermal.txt
Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
Documentation/devicetree/bindings/usb/renesas_usbhs.txt
Documentation/devicetree/bindings/vendor-prefixes.txt
Documentation/gpio/board.txt
Documentation/gpio/consumer.txt
Documentation/hwmon/nct6775
Documentation/input/multi-touch-protocol.txt
Documentation/networking/vrf.txt [new file with mode: 0644]
Documentation/power/pci.txt
Documentation/ptp/testptp.c
Documentation/static-keys.txt
Documentation/sysctl/net.txt
Documentation/thermal/power_allocator.txt
MAINTAINERS
Makefile
arch/alpha/include/asm/io.h
arch/alpha/include/asm/word-at-a-time.h
arch/alpha/kernel/irq.c
arch/alpha/kernel/pci.c
arch/alpha/lib/udelay.c
arch/arc/include/asm/Kbuild
arch/arc/kernel/mcip.c
arch/arm/Kconfig
arch/arm/Makefile
arch/arm/boot/dts/Makefile
arch/arm/boot/dts/am335x-phycore-som.dtsi
arch/arm/boot/dts/am57xx-beagle-x15.dts
arch/arm/boot/dts/armada-385-db-ap.dts
arch/arm/boot/dts/berlin2q.dtsi
arch/arm/boot/dts/dm8148-evm.dts
arch/arm/boot/dts/dm8148-t410.dts
arch/arm/boot/dts/dm814x.dtsi
arch/arm/boot/dts/dra7.dtsi
arch/arm/boot/dts/emev2-kzm9d.dts
arch/arm/boot/dts/exynos4412.dtsi
arch/arm/boot/dts/exynos5250-smdk5250.dts
arch/arm/boot/dts/exynos5420-peach-pit.dts
arch/arm/boot/dts/exynos5420.dtsi
arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi
arch/arm/boot/dts/exynos5800-peach-pi.dts
arch/arm/boot/dts/imx53-qsrb.dts
arch/arm/boot/dts/imx53.dtsi
arch/arm/boot/dts/imx6qdl-rex.dtsi
arch/arm/boot/dts/imx7d.dtsi
arch/arm/boot/dts/logicpd-torpedo-37xx-devkit.dts
arch/arm/boot/dts/meson.dtsi
arch/arm/boot/dts/omap2430.dtsi
arch/arm/boot/dts/omap3-beagle.dts
arch/arm/boot/dts/omap3-evm-37xx.dts
arch/arm/boot/dts/omap3-igep.dtsi
arch/arm/boot/dts/omap3-igep0020-common.dtsi
arch/arm/boot/dts/omap3.dtsi
arch/arm/boot/dts/omap4.dtsi
arch/arm/boot/dts/omap5-uevm.dts
arch/arm/boot/dts/omap5.dtsi
arch/arm/boot/dts/r8a7790.dtsi
arch/arm/boot/dts/r8a7791.dtsi
arch/arm/boot/dts/rk3288-veyron.dtsi
arch/arm/boot/dts/ste-hrefv60plus.dtsi
arch/arm/boot/dts/ste-snowball.dts
arch/arm/boot/dts/stih407.dtsi
arch/arm/boot/dts/stih410.dtsi
arch/arm/boot/dts/sun7i-a20.dtsi
arch/arm/boot/dts/tegra114.dtsi
arch/arm/boot/dts/tegra124.dtsi
arch/arm/boot/dts/tegra20.dtsi
arch/arm/boot/dts/tegra30.dtsi
arch/arm/boot/dts/uniphier-ph1-ld6b-ref.dts
arch/arm/common/it8152.c
arch/arm/common/locomo.c
arch/arm/common/sa1111.c
arch/arm/configs/omap2plus_defconfig
arch/arm/include/asm/assembler.h
arch/arm/include/asm/bug.h
arch/arm/include/asm/domain.h
arch/arm/include/asm/hardware/it8152.h
arch/arm/include/asm/hw_irq.h
arch/arm/include/asm/kvm_host.h
arch/arm/include/asm/mach/irq.h
arch/arm/include/asm/thread_info.h
arch/arm/include/asm/unistd.h
arch/arm/include/uapi/asm/unistd.h
arch/arm/kernel/calls.S
arch/arm/kernel/irq.c
arch/arm/kernel/kgdb.c
arch/arm/kernel/process.c
arch/arm/kernel/signal.c
arch/arm/kvm/Kconfig
arch/arm/kvm/arm.c
arch/arm/kvm/interrupts_head.S
arch/arm/kvm/mmu.c
arch/arm/kvm/psci.c
arch/arm/mach-dove/irq.c
arch/arm/mach-exynos/mcpm-exynos.c
arch/arm/mach-exynos/pm_domains.c
arch/arm/mach-exynos/regs-pmu.h
arch/arm/mach-footbridge/isa-irq.c
arch/arm/mach-gemini/gpio.c
arch/arm/mach-imx/3ds_debugboard.c
arch/arm/mach-imx/mach-mx31ads.c
arch/arm/mach-iop13xx/msi.c
arch/arm/mach-lpc32xx/irq.c
arch/arm/mach-netx/generic.c
arch/arm/mach-omap1/fpga.c
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/board-generic.c
arch/arm/mach-omap2/id.c
arch/arm/mach-omap2/io.c
arch/arm/mach-omap2/omap_device.c
arch/arm/mach-omap2/pdata-quirks.c
arch/arm/mach-omap2/pm.h
arch/arm/mach-omap2/prm_common.c
arch/arm/mach-omap2/soc.h
arch/arm/mach-omap2/timer.c
arch/arm/mach-omap2/vc.c
arch/arm/mach-pxa/balloon3.c
arch/arm/mach-pxa/cm-x2xx-pci.c
arch/arm/mach-pxa/include/mach/addr-map.h
arch/arm/mach-pxa/lpd270.c
arch/arm/mach-pxa/pcm990-baseboard.c
arch/arm/mach-pxa/pxa3xx.c
arch/arm/mach-pxa/viper.c
arch/arm/mach-pxa/zeus.c
arch/arm/mach-rpc/ecard.c
arch/arm/mach-s3c24xx/bast-irq.c
arch/arm/mach-s3c64xx/common.c
arch/arm/mach-sa1100/neponset.c
arch/arm/mm/alignment.c
arch/arm/mm/dma-mapping.c
arch/arm/net/bpf_jit_32.c
arch/arm/nwfpe/entry.S
arch/arm/plat-orion/common.c
arch/arm/plat-orion/gpio.c
arch/arm/plat-pxa/ssp.c
arch/arm/vdso/vdsomunge.c
arch/arm/xen/hypercall.S
arch/arm64/Kconfig
arch/arm64/Makefile
arch/arm64/boot/dts/arm/juno-motherboard.dtsi
arch/arm64/boot/dts/mediatek/mt8173.dtsi
arch/arm64/boot/dts/rockchip/rk3368.dtsi
arch/arm64/include/asm/hardirq.h
arch/arm64/include/asm/kvm_arm.h
arch/arm64/include/asm/kvm_asm.h
arch/arm64/include/asm/kvm_host.h
arch/arm64/include/asm/pgtable.h
arch/arm64/include/asm/unistd.h
arch/arm64/include/asm/unistd32.h
arch/arm64/include/uapi/asm/signal.h
arch/arm64/kernel/armv8_deprecated.c
arch/arm64/kernel/debug-monitors.c
arch/arm64/kernel/efi-stub.c
arch/arm64/kernel/efi.c
arch/arm64/kernel/entry-ftrace.S
arch/arm64/kernel/head.S
arch/arm64/kernel/hw_breakpoint.c
arch/arm64/kernel/insn.c
arch/arm64/kernel/module.c
arch/arm64/kernel/setup.c
arch/arm64/kernel/signal32.c
arch/arm64/kernel/stacktrace.c
arch/arm64/kernel/suspend.c
arch/arm64/kvm/Kconfig
arch/arm64/kvm/hyp.S
arch/arm64/kvm/sys_regs.c
arch/arm64/mm/dma-mapping.c
arch/arm64/mm/fault.c
arch/avr32/include/asm/Kbuild
arch/avr32/mach-at32ap/extint.c
arch/avr32/mach-at32ap/pio.c
arch/blackfin/include/asm/Kbuild
arch/blackfin/include/asm/irq_handler.h
arch/blackfin/kernel/irqchip.c
arch/blackfin/mach-bf537/ints-priority.c
arch/blackfin/mach-common/ints-priority.c
arch/c6x/include/asm/Kbuild
arch/c6x/platforms/megamod-pic.c
arch/cris/include/asm/Kbuild
arch/frv/include/asm/Kbuild
arch/frv/mb93090-mb00/pci-vdk.c
arch/h8300/include/asm/Kbuild
arch/hexagon/include/asm/Kbuild
arch/ia64/include/asm/Kbuild
arch/ia64/include/asm/unistd.h
arch/ia64/include/uapi/asm/unistd.h
arch/ia64/kernel/entry.S
arch/ia64/pci/pci.c
arch/m32r/include/asm/Kbuild
arch/m68k/amiga/amiints.c
arch/m68k/coldfire/intc-5272.c
arch/m68k/configs/amiga_defconfig
arch/m68k/configs/apollo_defconfig
arch/m68k/configs/atari_defconfig
arch/m68k/configs/bvme6000_defconfig
arch/m68k/configs/hp300_defconfig
arch/m68k/configs/mac_defconfig
arch/m68k/configs/multi_defconfig
arch/m68k/configs/mvme147_defconfig
arch/m68k/configs/mvme16x_defconfig
arch/m68k/configs/q40_defconfig
arch/m68k/configs/sun3_defconfig
arch/m68k/configs/sun3x_defconfig
arch/m68k/include/asm/irq.h
arch/m68k/include/asm/linkage.h
arch/m68k/include/asm/mac_via.h
arch/m68k/include/asm/unistd.h
arch/m68k/include/uapi/asm/unistd.h
arch/m68k/kernel/syscalltable.S
arch/m68k/mac/baboon.c
arch/m68k/mac/oss.c
arch/m68k/mac/psc.c
arch/m68k/mac/via.c
arch/metag/include/asm/Kbuild
arch/metag/kernel/irq.c
arch/microblaze/include/asm/Kbuild
arch/microblaze/pci/pci-common.c
arch/mips/alchemy/common/irq.c
arch/mips/alchemy/devboards/bcsr.c
arch/mips/ath25/ar2315.c
arch/mips/ath25/ar5312.c
arch/mips/ath79/irq.c
arch/mips/bcm63xx/dev-spi.c
arch/mips/cavium-octeon/octeon-irq.c
arch/mips/cavium-octeon/setup.c
arch/mips/include/asm/Kbuild
arch/mips/include/asm/cpu-features.h
arch/mips/include/asm/cpu.h
arch/mips/include/asm/io.h
arch/mips/include/asm/kvm_host.h
arch/mips/include/asm/maar.h
arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h
arch/mips/include/asm/mips-cm.h
arch/mips/include/asm/mipsregs.h
arch/mips/include/asm/netlogic/common.h
arch/mips/include/uapi/asm/swab.h
arch/mips/include/uapi/asm/unistd.h
arch/mips/jz4740/board-qi_lb60.c
arch/mips/jz4740/gpio.c
arch/mips/kernel/cps-vec.S
arch/mips/kernel/cpu-probe.c
arch/mips/kernel/octeon_switch.S
arch/mips/kernel/r2300_switch.S
arch/mips/kernel/scall32-o32.S
arch/mips/kernel/scall64-64.S
arch/mips/kernel/scall64-n32.S
arch/mips/kernel/scall64-o32.S
arch/mips/kernel/setup.c
arch/mips/kernel/smp.c
arch/mips/kvm/mips.c
arch/mips/loongson64/common/env.c
arch/mips/mm/dma-default.c
arch/mips/mm/init.c
arch/mips/net/bpf_jit_asm.S
arch/mips/netlogic/common/smp.c
arch/mips/pci/pci-ar2315.c
arch/mips/pci/pci-ar71xx.c
arch/mips/pci/pci-ar724x.c
arch/mips/pci/pci-rt3883.c
arch/mips/pci/pci.c
arch/mips/ralink/irq.c
arch/mn10300/include/asm/Kbuild
arch/mn10300/unit-asb2305/pci.c
arch/nios2/include/asm/Kbuild
arch/powerpc/boot/Makefile
arch/powerpc/configs/ppc64_defconfig
arch/powerpc/configs/pseries_defconfig
arch/powerpc/include/asm/cache.h
arch/powerpc/include/asm/kvm_host.h
arch/powerpc/include/asm/machdep.h
arch/powerpc/include/asm/ppc-opcode.h
arch/powerpc/include/asm/qe_ic.h
arch/powerpc/include/asm/reg.h
arch/powerpc/include/asm/systbl.h
arch/powerpc/include/asm/tsi108_pci.h
arch/powerpc/include/asm/unistd.h
arch/powerpc/include/asm/word-at-a-time.h
arch/powerpc/include/uapi/asm/unistd.h
arch/powerpc/kernel/dma.c
arch/powerpc/kernel/irq.c
arch/powerpc/kernel/pci-common.c
arch/powerpc/kernel/rtas.c
arch/powerpc/kernel/setup_32.c
arch/powerpc/kvm/book3s.c
arch/powerpc/kvm/book3s_hv.c
arch/powerpc/kvm/book3s_hv_rmhandlers.S
arch/powerpc/kvm/booke.c
arch/powerpc/lib/copy_32.S
arch/powerpc/mm/hash_native_64.c
arch/powerpc/mm/hugepage-hash64.c
arch/powerpc/platforms/512x/mpc5121_ads_cpld.c
arch/powerpc/platforms/52xx/media5200.c
arch/powerpc/platforms/52xx/mpc52xx_gpt.c
arch/powerpc/platforms/52xx/mpc52xx_pic.c
arch/powerpc/platforms/82xx/pq2ads-pci-pic.c
arch/powerpc/platforms/85xx/common.c
arch/powerpc/platforms/85xx/mpc85xx_cds.c
arch/powerpc/platforms/85xx/mpc85xx_ds.c
arch/powerpc/platforms/85xx/socrates_fpga_pic.c
arch/powerpc/platforms/86xx/pic.c
arch/powerpc/platforms/8xx/m8xx_setup.c
arch/powerpc/platforms/cell/axon_msi.c
arch/powerpc/platforms/cell/interrupt.c
arch/powerpc/platforms/cell/spider-pic.c
arch/powerpc/platforms/chrp/setup.c
arch/powerpc/platforms/embedded6xx/hlwd-pic.c
arch/powerpc/platforms/embedded6xx/mvme5100.c
arch/powerpc/platforms/pasemi/msi.c
arch/powerpc/platforms/powernv/opal.c
arch/powerpc/platforms/powernv/pci-ioda.c
arch/powerpc/platforms/powernv/pci.c
arch/powerpc/platforms/powernv/smp.c
arch/powerpc/platforms/ps3/os-area.c
arch/powerpc/platforms/pseries/dlpar.c
arch/powerpc/platforms/pseries/setup.c
arch/powerpc/sysdev/cpm2_pic.c
arch/powerpc/sysdev/fsl_msi.c
arch/powerpc/sysdev/ge/ge_pic.c
arch/powerpc/sysdev/ge/ge_pic.h
arch/powerpc/sysdev/ipic.c
arch/powerpc/sysdev/mpc8xx_pic.c
arch/powerpc/sysdev/mpic.c
arch/powerpc/sysdev/mpic_u3msi.c
arch/powerpc/sysdev/ppc4xx_msi.c
arch/powerpc/sysdev/qe_lib/qe_ic.c
arch/powerpc/sysdev/tsi108_pci.c
arch/powerpc/sysdev/uic.c
arch/powerpc/sysdev/xics/ics-opal.c
arch/powerpc/sysdev/xics/ics-rtas.c
arch/powerpc/sysdev/xilinx_intc.c
arch/s390/boot/compressed/Makefile
arch/s390/configs/default_defconfig
arch/s390/configs/gcov_defconfig
arch/s390/configs/performance_defconfig
arch/s390/configs/zfcpdump_defconfig
arch/s390/include/asm/Kbuild
arch/s390/include/asm/kvm_host.h
arch/s390/include/asm/numa.h
arch/s390/include/asm/topology.h
arch/s390/include/asm/unistd.h
arch/s390/include/uapi/asm/unistd.h
arch/s390/kernel/asm-offsets.c
arch/s390/kernel/compat_signal.c
arch/s390/kernel/compat_wrapper.c
arch/s390/kernel/entry.S
arch/s390/kernel/perf_cpum_cf.c
arch/s390/kernel/swsusp.S
arch/s390/kernel/syscalls.S
arch/s390/kernel/vtime.c
arch/s390/kvm/kvm-s390.c
arch/s390/numa/mode_emu.c
arch/s390/numa/numa.c
arch/score/include/asm/Kbuild
arch/sh/boards/mach-se/7343/irq.c
arch/sh/boards/mach-se/7722/irq.c
arch/sh/boards/mach-se/7724/irq.c
arch/sh/boards/mach-x3proto/gpio.c
arch/sh/cchips/hd6446x/hd64461.c
arch/sh/include/asm/page.h
arch/sparc/crypto/aes_glue.c
arch/sparc/crypto/camellia_glue.c
arch/sparc/crypto/des_glue.c
arch/sparc/kernel/leon_kernel.c
arch/sparc/kernel/leon_pci_grpci1.c
arch/sparc/kernel/leon_pci_grpci2.c
arch/tile/gxio/mpipe.c
arch/tile/include/asm/word-at-a-time.h
arch/tile/kernel/pci_gx.c
arch/tile/kernel/usb.c
arch/um/Makefile
arch/um/include/asm/Kbuild
arch/um/kernel/trap.c
arch/um/os-Linux/helper.c
arch/unicore32/include/asm/Kbuild
arch/unicore32/kernel/irq.c
arch/x86/Kconfig
arch/x86/boot/compressed/eboot.c
arch/x86/crypto/camellia_aesni_avx_glue.c
arch/x86/entry/entry_64.S
arch/x86/include/asm/cpufeature.h
arch/x86/include/asm/efi.h
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/msr-index.h
arch/x86/include/asm/paravirt_types.h
arch/x86/include/asm/pvclock-abi.h
arch/x86/include/asm/qspinlock.h
arch/x86/include/asm/string_64.h
arch/x86/include/asm/xen/hypercall.h
arch/x86/include/uapi/asm/bitsperlong.h
arch/x86/kernel/alternative.c
arch/x86/kernel/apic/apic.c
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/apic/vector.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/cpu/mshyperv.c
arch/x86/kernel/cpu/perf_event.h
arch/x86/kernel/cpu/perf_event_intel.c
arch/x86/kernel/cpu/perf_event_intel_bts.c
arch/x86/kernel/cpu/perf_event_msr.c
arch/x86/kernel/cpu/scattered.c
arch/x86/kernel/crash.c
arch/x86/kernel/irq_32.c
arch/x86/kernel/irq_64.c
arch/x86/kernel/ldt.c
arch/x86/kernel/paravirt.c
arch/x86/kernel/pci-dma.c
arch/x86/kernel/process.c
arch/x86/kernel/process_32.c
arch/x86/kernel/process_64.c
arch/x86/kernel/setup.c
arch/x86/kernel/smpboot.c
arch/x86/kernel/tsc.c
arch/x86/kernel/vm86_32.c
arch/x86/kvm/emulate.c
arch/x86/kvm/mmu.c
arch/x86/kvm/svm.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/lguest/boot.c
arch/x86/mm/init_64.c
arch/x86/mm/srat.c
arch/x86/pci/common.c
arch/x86/platform/efi/efi.c
arch/x86/um/ldt.c
arch/x86/xen/enlighten.c
arch/x86/xen/p2m.c
arch/x86/xen/setup.c
arch/xtensa/include/asm/Kbuild
arch/xtensa/kernel/pci.c
block/bio-integrity.c
block/blk-cgroup.c
block/blk-core.c
block/blk-integrity.c
block/blk-lib.c
block/blk-map.c
block/blk-merge.c
block/blk-mq-cpumap.c
block/blk-mq-sysfs.c
block/blk-mq-tag.c
block/blk-mq-tag.h
block/blk-mq.c
block/blk-mq.h
block/blk-sysfs.c
block/bounce.c
crypto/ablkcipher.c
crypto/ahash.c
crypto/algapi.c
crypto/api.c
crypto/asymmetric_keys/x509_public_key.c
crypto/crypto_user.c
crypto/testmgr.c
drivers/acpi/acpica/acglobal.h
drivers/acpi/acpica/actables.h
drivers/acpi/acpica/evxfevnt.c
drivers/acpi/acpica/tbfadt.c
drivers/acpi/acpica/tbutils.c
drivers/acpi/bus.c
drivers/acpi/ec.c
drivers/acpi/int340x_thermal.c
drivers/acpi/pci_irq.c
drivers/acpi/pci_link.c
drivers/atm/he.c
drivers/atm/solos-pci.c
drivers/base/cacheinfo.c
drivers/base/dma-contiguous.c
drivers/base/platform-msi.c
drivers/base/power/domain_governor.c
drivers/base/power/opp.c
drivers/base/regmap/regmap-debugfs.c
drivers/block/loop.c
drivers/block/nbd.c
drivers/block/null_blk.c
drivers/block/nvme-core.c
drivers/block/rbd.c
drivers/block/virtio_blk.c
drivers/block/xen-blkback/xenbus.c
drivers/block/xen-blkfront.c
drivers/block/zram/zcomp.c
drivers/bus/Kconfig
drivers/bus/arm-ccn.c
drivers/char/hw_random/xgene-rng.c
drivers/clk/clk.c
drivers/clk/clkdev.c
drivers/clk/h8300/clk-h8s2678.c
drivers/clk/hisilicon/Kconfig
drivers/clk/hisilicon/Makefile
drivers/clk/mvebu/clk-cpu.c
drivers/clk/rockchip/clk-rk3188.c
drivers/clk/rockchip/clk-rk3368.c
drivers/clk/samsung/clk-cpu.c
drivers/clk/st/clkgen-fsyn.c
drivers/clk/st/clkgen-pll.c
drivers/clk/tegra/clk-dfll.c
drivers/clk/ti/clk-3xxx.c
drivers/clk/ti/clk-7xx.c
drivers/clk/ti/clkt_dflt.c
drivers/clocksource/arm_global_timer.c
drivers/clocksource/fsl_ftm_timer.c
drivers/clocksource/rockchip_timer.c
drivers/clocksource/samsung_pwm_timer.c
drivers/clocksource/sh_mtu2.c
drivers/clocksource/time-pistachio.c
drivers/clocksource/timer-digicolor.c
drivers/clocksource/timer-keystone.c
drivers/clocksource/timer-prima2.c
drivers/clocksource/vf_pit_timer.c
drivers/cpufreq/acpi-cpufreq.c
drivers/cpufreq/cpufreq.c
drivers/cpufreq/intel_pstate.c
drivers/crypto/Kconfig
drivers/crypto/marvell/cesa.h
drivers/crypto/marvell/cipher.c
drivers/crypto/marvell/hash.c
drivers/crypto/qat/qat_common/adf_aer.c
drivers/crypto/sunxi-ss/sun4i-ss-cipher.c
drivers/devfreq/devfreq.c
drivers/devfreq/event/exynos-ppmu.c
drivers/devfreq/governor_simpleondemand.c
drivers/devfreq/tegra-devfreq.c
drivers/dma/at_xdmac.c
drivers/dma/dmaengine.c
drivers/dma/dw/core.c
drivers/dma/idma64.c
drivers/dma/ipu/ipu_irq.c
drivers/dma/pxa_dma.c
drivers/dma/sun4i-dma.c
drivers/dma/xgene-dma.c
drivers/dma/zx296702_dma.c
drivers/extcon/extcon.c
drivers/firmware/Kconfig
drivers/firmware/Makefile
drivers/firmware/efi/libstub/arm-stub.c
drivers/firmware/efi/libstub/efistub.h
drivers/firmware/qcom_scm-64.c [new file with mode: 0644]
drivers/gpio/Kconfig
drivers/gpio/gpio-altera.c
drivers/gpio/gpio-bcm-kona.c
drivers/gpio/gpio-brcmstb.c
drivers/gpio/gpio-davinci.c
drivers/gpio/gpio-dwapb.c
drivers/gpio/gpio-ep93xx.c
drivers/gpio/gpio-intel-mid.c
drivers/gpio/gpio-lynxpoint.c
drivers/gpio/gpio-mpc8xxx.c
drivers/gpio/gpio-msic.c
drivers/gpio/gpio-msm-v2.c
drivers/gpio/gpio-mvebu.c
drivers/gpio/gpio-mxc.c
drivers/gpio/gpio-mxs.c
drivers/gpio/gpio-omap.c
drivers/gpio/gpio-pl061.c
drivers/gpio/gpio-pxa.c
drivers/gpio/gpio-sa1100.c
drivers/gpio/gpio-sx150x.c
drivers/gpio/gpio-tegra.c
drivers/gpio/gpio-timberdale.c
drivers/gpio/gpio-tz1090.c
drivers/gpio/gpio-vf610.c
drivers/gpio/gpio-zx.c
drivers/gpio/gpio-zynq.c
drivers/gpio/gpiolib.c
drivers/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c
drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ih.c
drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c
drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c
drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
drivers/gpu/drm/amd/amdgpu/amdgpu_test.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
drivers/gpu/drm/amd/amdgpu/atombios_encoders.c
drivers/gpu/drm/amd/amdgpu/ci_dpm.c
drivers/gpu/drm/amd/amdgpu/cik.c
drivers/gpu/drm/amd/amdgpu/cz_dpm.c
drivers/gpu/drm/amd/amdgpu/cz_smc.c
drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
drivers/gpu/drm/amd/amdgpu/fiji_smc.c
drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
drivers/gpu/drm/amd/amdgpu/iceland_smc.c
drivers/gpu/drm/amd/amdgpu/kv_dpm.c
drivers/gpu/drm/amd/amdgpu/tonga_smc.c
drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c
drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c
drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
drivers/gpu/drm/amd/amdgpu/vi.c
drivers/gpu/drm/amd/include/cgs_linux.h
drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h [new file with mode: 0644]
drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
drivers/gpu/drm/amd/scheduler/gpu_scheduler.h
drivers/gpu/drm/amd/scheduler/sched_fence.c
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_dp_mst_topology.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/drm_ioctl.c
drivers/gpu/drm/drm_probe_helper.c
drivers/gpu/drm/drm_sysfs.c
drivers/gpu/drm/exynos/exynos7_drm_decon.c
drivers/gpu/drm/exynos/exynos_dp_core.c
drivers/gpu/drm/exynos/exynos_drm_core.c
drivers/gpu/drm/exynos/exynos_drm_crtc.c
drivers/gpu/drm/exynos/exynos_drm_drv.c
drivers/gpu/drm/exynos/exynos_drm_drv.h
drivers/gpu/drm/exynos/exynos_drm_fimc.c
drivers/gpu/drm/exynos/exynos_drm_fimd.c
drivers/gpu/drm/exynos/exynos_drm_g2d.c
drivers/gpu/drm/exynos/exynos_drm_gem.c
drivers/gpu/drm/exynos/exynos_drm_gem.h
drivers/gpu/drm/exynos/exynos_drm_rotator.c
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
drivers/gpu/drm/i915/i915_gem_shrinker.c
drivers/gpu/drm/i915/i915_gem_userptr.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/intel_audio.c
drivers/gpu/drm/i915/intel_bios.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp_mst.c
drivers/gpu/drm/i915/intel_hotplug.c
drivers/gpu/drm/i915/intel_lrc.c
drivers/gpu/drm/i915/intel_lrc.h
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/i915/intel_runtime_pm.c
drivers/gpu/drm/mgag200/mgag200_fb.c
drivers/gpu/drm/mgag200/mgag200_main.c
drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nouveau_fbcon.c
drivers/gpu/drm/nouveau/nouveau_gem.c
drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c
drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h
drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c
drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c
drivers/gpu/drm/nouveau/nvkm/subdev/pci/agp.c
drivers/gpu/drm/qxl/qxl_display.c
drivers/gpu/drm/qxl/qxl_fb.c
drivers/gpu/drm/qxl/qxl_release.c
drivers/gpu/drm/radeon/atombios_encoders.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_dp_mst.c
drivers/gpu/drm/radeon/radeon_encoders.c
drivers/gpu/drm/radeon/radeon_fb.c
drivers/gpu/drm/radeon/radeon_kms.c
drivers/gpu/drm/radeon/radeon_legacy_encoders.c
drivers/gpu/drm/radeon/radeon_mode.h
drivers/gpu/drm/radeon/radeon_pm.c
drivers/gpu/drm/radeon/si_dpm.c
drivers/gpu/drm/ttm/ttm_bo.c
drivers/gpu/drm/virtio/virtgpu_debugfs.c
drivers/gpu/drm/virtio/virtgpu_fence.c
drivers/gpu/drm/vmwgfx/Kconfig
drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
drivers/gpu/ipu-v3/ipu-common.c
drivers/hv/channel_mgmt.c
drivers/hwmon/Kconfig
drivers/hwmon/abx500.c
drivers/hwmon/gpio-fan.c
drivers/hwmon/nct6775.c
drivers/hwmon/pwm-fan.c
drivers/i2c/busses/i2c-designware-platdrv.c
drivers/i2c/busses/i2c-mv64xxx.c
drivers/i2c/busses/i2c-pnx.c
drivers/i2c/busses/i2c-rcar.c
drivers/i2c/busses/i2c-s3c2410.c
drivers/i2c/i2c-core.c
drivers/idle/intel_idle.c
drivers/iio/accel/st_accel_core.c
drivers/iio/adc/twl4030-madc.c
drivers/infiniband/Kconfig
drivers/infiniband/core/cache.c
drivers/infiniband/core/cm.c
drivers/infiniband/core/cma.c
drivers/infiniband/core/roce_gid_mgmt.c
drivers/infiniband/core/ucma.c
drivers/infiniband/hw/Makefile
drivers/infiniband/hw/ehca/Kconfig [deleted file]
drivers/infiniband/hw/ehca/Makefile [deleted file]
drivers/infiniband/hw/ehca/ehca_av.c [deleted file]
drivers/infiniband/hw/ehca/ehca_classes.h [deleted file]
drivers/infiniband/hw/ehca/ehca_classes_pSeries.h [deleted file]
drivers/infiniband/hw/ehca/ehca_cq.c [deleted file]
drivers/infiniband/hw/ehca/ehca_eq.c [deleted file]
drivers/infiniband/hw/ehca/ehca_hca.c [deleted file]
drivers/infiniband/hw/ehca/ehca_irq.c [deleted file]
drivers/infiniband/hw/ehca/ehca_irq.h [deleted file]
drivers/infiniband/hw/ehca/ehca_iverbs.h [deleted file]
drivers/infiniband/hw/ehca/ehca_main.c [deleted file]
drivers/infiniband/hw/ehca/ehca_mcast.c [deleted file]
drivers/infiniband/hw/ehca/ehca_mrmw.c [deleted file]
drivers/infiniband/hw/ehca/ehca_mrmw.h [deleted file]
drivers/infiniband/hw/ehca/ehca_pd.c [deleted file]
drivers/infiniband/hw/ehca/ehca_qes.h [deleted file]
drivers/infiniband/hw/ehca/ehca_qp.c [deleted file]
drivers/infiniband/hw/ehca/ehca_reqs.c [deleted file]
drivers/infiniband/hw/ehca/ehca_sqp.c [deleted file]
drivers/infiniband/hw/ehca/ehca_tools.h [deleted file]
drivers/infiniband/hw/ehca/ehca_uverbs.c [deleted file]
drivers/infiniband/hw/ehca/hcp_if.c [deleted file]
drivers/infiniband/hw/ehca/hcp_if.h [deleted file]
drivers/infiniband/hw/ehca/hcp_phyp.c [deleted file]
drivers/infiniband/hw/ehca/hcp_phyp.h [deleted file]
drivers/infiniband/hw/ehca/hipz_fns.h [deleted file]
drivers/infiniband/hw/ehca/hipz_fns_core.h [deleted file]
drivers/infiniband/hw/ehca/hipz_hw.h [deleted file]
drivers/infiniband/hw/ehca/ipz_pt_fn.c [deleted file]
drivers/infiniband/hw/ehca/ipz_pt_fn.h [deleted file]
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/mlx5/mlx5_ib.h
drivers/infiniband/hw/mlx5/qp.c
drivers/infiniband/hw/usnic/usnic.h
drivers/infiniband/hw/usnic/usnic_abi.h
drivers/infiniband/hw/usnic/usnic_common_pkt_hdr.h
drivers/infiniband/hw/usnic/usnic_common_util.h
drivers/infiniband/hw/usnic/usnic_debugfs.c
drivers/infiniband/hw/usnic/usnic_debugfs.h
drivers/infiniband/hw/usnic/usnic_fwd.c
drivers/infiniband/hw/usnic/usnic_fwd.h
drivers/infiniband/hw/usnic/usnic_ib.h
drivers/infiniband/hw/usnic/usnic_ib_main.c
drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c
drivers/infiniband/hw/usnic/usnic_ib_qp_grp.h
drivers/infiniband/hw/usnic/usnic_ib_sysfs.c
drivers/infiniband/hw/usnic/usnic_ib_sysfs.h
drivers/infiniband/hw/usnic/usnic_ib_verbs.c
drivers/infiniband/hw/usnic/usnic_ib_verbs.h
drivers/infiniband/hw/usnic/usnic_log.h
drivers/infiniband/hw/usnic/usnic_transport.c
drivers/infiniband/hw/usnic/usnic_transport.h
drivers/infiniband/hw/usnic/usnic_uiom.c
drivers/infiniband/hw/usnic/usnic_uiom.h
drivers/infiniband/hw/usnic/usnic_uiom_interval_tree.c
drivers/infiniband/hw/usnic/usnic_uiom_interval_tree.h
drivers/infiniband/hw/usnic/usnic_vnic.c
drivers/infiniband/hw/usnic/usnic_vnic.h
drivers/infiniband/ulp/ipoib/ipoib.h
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/infiniband/ulp/ipoib/ipoib_multicast.c
drivers/infiniband/ulp/iser/iscsi_iser.c
drivers/infiniband/ulp/iser/iscsi_iser.h
drivers/infiniband/ulp/iser/iser_memory.c
drivers/infiniband/ulp/iser/iser_verbs.c
drivers/infiniband/ulp/isert/ib_isert.c
drivers/infiniband/ulp/isert/ib_isert.h
drivers/input/joystick/Kconfig
drivers/input/joystick/walkera0701.c
drivers/input/keyboard/omap4-keypad.c
drivers/input/misc/pm8941-pwrkey.c
drivers/input/misc/uinput.c
drivers/input/mouse/alps.c
drivers/input/mouse/cyapa_gen6.c
drivers/input/mouse/elan_i2c.h
drivers/input/mouse/elan_i2c_core.c
drivers/input/mouse/elan_i2c_i2c.c
drivers/input/mouse/elan_i2c_smbus.c
drivers/input/mouse/synaptics.c
drivers/input/serio/libps2.c
drivers/input/serio/parkbd.c
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/ads7846.c
drivers/input/touchscreen/imx6ul_tsc.c
drivers/input/touchscreen/lpc32xx_ts.c
drivers/input/touchscreen/mms114.c
drivers/iommu/Kconfig
drivers/iommu/amd_iommu.c
drivers/iommu/amd_iommu_init.c
drivers/iommu/amd_iommu_types.h
drivers/iommu/amd_iommu_v2.c
drivers/iommu/arm-smmu-v3.c
drivers/iommu/intel-iommu.c
drivers/iommu/io-pgtable-arm.c
drivers/iommu/iova.c
drivers/irqchip/exynos-combiner.c
drivers/irqchip/irq-armada-370-xp.c
drivers/irqchip/irq-atmel-aic5.c
drivers/irqchip/irq-bcm2835.c
drivers/irqchip/irq-bcm7038-l1.c
drivers/irqchip/irq-bcm7120-l2.c
drivers/irqchip/irq-brcmstb-l2.c
drivers/irqchip/irq-clps711x.c
drivers/irqchip/irq-dw-apb-ictl.c
drivers/irqchip/irq-gic-v2m.c
drivers/irqchip/irq-gic-v3-its-pci-msi.c
drivers/irqchip/irq-gic-v3-its.c
drivers/irqchip/irq-gic-v3.c
drivers/irqchip/irq-gic.c
drivers/irqchip/irq-hip04.c
drivers/irqchip/irq-i8259.c
drivers/irqchip/irq-imgpdc.c
drivers/irqchip/irq-keystone.c
drivers/irqchip/irq-metag-ext.c
drivers/irqchip/irq-metag.c
drivers/irqchip/irq-mips-gic.c
drivers/irqchip/irq-mmp.c
drivers/irqchip/irq-mxs.c
drivers/irqchip/irq-orion.c
drivers/irqchip/irq-renesas-intc-irqpin.c
drivers/irqchip/irq-renesas-irqc.c
drivers/irqchip/irq-s3c24xx.c
drivers/irqchip/irq-sun4i.c
drivers/irqchip/irq-sunxi-nmi.c
drivers/irqchip/irq-tb10x.c
drivers/irqchip/irq-tegra.c
drivers/irqchip/irq-versatile-fpga.c
drivers/irqchip/irq-vic.c
drivers/irqchip/irq-vt8500.c
drivers/irqchip/spear-shirq.c
drivers/isdn/hisax/isdnl2.c
drivers/isdn/mISDN/layer2.c
drivers/leds/Kconfig
drivers/leds/leds-aat1290.c
drivers/leds/leds-bcm6328.c
drivers/leds/leds-bcm6358.c
drivers/leds/leds-ktd2692.c
drivers/leds/leds-max77693.c
drivers/leds/leds-ns2.c
drivers/mcb/mcb-pci.c
drivers/md/bitmap.c
drivers/md/dm-cache-metadata.c
drivers/md/dm-cache-policy-cleaner.c
drivers/md/dm-crypt.c
drivers/md/dm-exception-store.c
drivers/md/dm-exception-store.h
drivers/md/dm-raid.c
drivers/md/dm-snap-persistent.c
drivers/md/dm-snap-transient.c
drivers/md/dm-snap.c
drivers/md/dm-thin.c
drivers/md/dm.c
drivers/md/md.c
drivers/md/multipath.c
drivers/md/persistent-data/dm-btree-remove.c
drivers/md/persistent-data/dm-btree.c
drivers/md/raid0.c
drivers/md/raid1.c
drivers/md/raid10.c
drivers/md/raid5.c
drivers/media/dvb-frontends/horus3a.h
drivers/media/dvb-frontends/lnbh25.h
drivers/media/dvb-frontends/m88ds3103.c
drivers/media/dvb-frontends/si2168.c
drivers/media/pci/netup_unidvb/netup_unidvb_spi.c
drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c
drivers/media/rc/ir-hix5hd2.c
drivers/media/tuners/si2157.c
drivers/media/usb/dvb-usb-v2/rtl28xxu.c
drivers/media/usb/dvb-usb-v2/rtl28xxu.h
drivers/media/v4l2-core/Kconfig
drivers/memory/Kconfig
drivers/memory/omap-gpmc.c
drivers/mfd/asic3.c
drivers/mfd/ezx-pcap.c
drivers/mfd/htc-egpio.c
drivers/mfd/intel-lpss.h
drivers/mfd/jz4740-adc.c
drivers/mfd/max77843.c
drivers/mfd/pm8921-core.c
drivers/mfd/t7l66xb.c
drivers/mfd/tc6393xb.c
drivers/mfd/ucb1x00-core.c
drivers/misc/cxl/Makefile
drivers/misc/cxl/api.c
drivers/misc/cxl/context.c
drivers/misc/cxl/cxl.h
drivers/misc/cxl/file.c
drivers/misc/cxl/irq.c
drivers/misc/cxl/native.c
drivers/misc/cxl/pci.c
drivers/misc/cxl/sysfs.c
drivers/misc/cxl/vphb.c
drivers/misc/mei/debugfs.c
drivers/misc/mei/hbm.c
drivers/mmc/card/mmc_test.c
drivers/mmc/core/core.c
drivers/mmc/core/host.c
drivers/mmc/core/mmc.c
drivers/mmc/host/omap_hsmmc.c
drivers/mmc/host/pxamci.c
drivers/mmc/host/sdhci-of-at91.c
drivers/mmc/host/sdhci-pxav3.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/sdhci.h
drivers/mmc/host/sunxi-mmc.c
drivers/mtd/nand/mxc_nand.c
drivers/mtd/nand/sunxi_nand.c
drivers/mtd/ubi/io.c
drivers/mtd/ubi/vtbl.c
drivers/mtd/ubi/wl.c
drivers/net/arcnet/arcnet.c
drivers/net/can/sja1000/peak_pci.c
drivers/net/dsa/mv88e6xxx.c
drivers/net/ethernet/allwinner/sun4i-emac.c
drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c
drivers/net/ethernet/amd/xgbe/xgbe-dev.c
drivers/net/ethernet/amd/xgbe/xgbe-drv.c
drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
drivers/net/ethernet/arc/emac_arc.c
drivers/net/ethernet/broadcom/bcm63xx_enet.c
drivers/net/ethernet/broadcom/bcmsysport.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
drivers/net/ethernet/broadcom/genet/bcmgenet.c
drivers/net/ethernet/brocade/bna/bfa_ioc.c
drivers/net/ethernet/brocade/bna/bna_tx_rx.c
drivers/net/ethernet/brocade/bna/bna_types.h
drivers/net/ethernet/brocade/bna/bnad.c
drivers/net/ethernet/brocade/bna/bnad.h
drivers/net/ethernet/brocade/bna/bnad_ethtool.c
drivers/net/ethernet/cavium/Kconfig
drivers/net/ethernet/cavium/thunder/nic_main.c
drivers/net/ethernet/cavium/thunder/nic_reg.h
drivers/net/ethernet/cavium/thunder/nicvf_main.c
drivers/net/ethernet/cavium/thunder/thunder_bgx.c
drivers/net/ethernet/chelsio/cxgb4/t4_pci_id_tbl.h
drivers/net/ethernet/emulex/benet/be.h
drivers/net/ethernet/emulex/benet/be_cmds.c
drivers/net/ethernet/emulex/benet/be_cmds.h
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/freescale/fsl_pq_mdio.c
drivers/net/ethernet/freescale/gianfar.c
drivers/net/ethernet/freescale/gianfar_ethtool.c
drivers/net/ethernet/freescale/gianfar_ptp.c
drivers/net/ethernet/freescale/ucc_geth.c
drivers/net/ethernet/hisilicon/hip04_eth.c
drivers/net/ethernet/ibm/emac/core.h
drivers/net/ethernet/intel/i40e/i40e_adminq.c
drivers/net/ethernet/intel/i40e/i40e_ethtool.c
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/i40evf/i40e_adminq.c
drivers/net/ethernet/marvell/mv643xx_eth.c
drivers/net/ethernet/marvell/mvneta.c
drivers/net/ethernet/mellanox/mlx4/cmd.c
drivers/net/ethernet/mellanox/mlx4/en_rx.c
drivers/net/ethernet/mellanox/mlx4/en_tx.c
drivers/net/ethernet/mellanox/mlx4/eq.c
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/mellanox/mlx4/mcg.c
drivers/net/ethernet/mellanox/mlx5/core/en_flow_table.c
drivers/net/ethernet/mellanox/mlx5/core/fw.c
drivers/net/ethernet/mellanox/mlx5/core/port.c
drivers/net/ethernet/mellanox/mlxsw/core.c
drivers/net/ethernet/mellanox/mlxsw/item.h
drivers/net/ethernet/mellanox/mlxsw/pci.c
drivers/net/ethernet/mellanox/mlxsw/switchx2.c
drivers/net/ethernet/micrel/ks8851.c
drivers/net/ethernet/moxa/moxart_ether.c
drivers/net/ethernet/nvidia/forcedeth.c
drivers/net/ethernet/nxp/lpc_eth.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
drivers/net/ethernet/realtek/8139cp.c
drivers/net/ethernet/realtek/r8169.c
drivers/net/ethernet/renesas/sh_eth.c
drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
drivers/net/ethernet/sun/sunvnet.c
drivers/net/ethernet/ti/cpsw.c
drivers/net/ethernet/ti/netcp_core.c
drivers/net/ethernet/ti/netcp_ethss.c
drivers/net/ethernet/via/Kconfig
drivers/net/ethernet/via/via-rhine.c
drivers/net/ethernet/xilinx/xilinx_emaclite.c
drivers/net/fjes/fjes_hw.c
drivers/net/geneve.c
drivers/net/irda/ali-ircc.c
drivers/net/macvtap.c
drivers/net/phy/Kconfig
drivers/net/phy/Makefile
drivers/net/phy/dp83848.c [new file with mode: 0644]
drivers/net/phy/fixed_phy.c
drivers/net/phy/marvell.c
drivers/net/phy/mdio-bcm-unimac.c
drivers/net/phy/mdio-gpio.c
drivers/net/phy/mdio-mux-mmioreg.c
drivers/net/phy/mdio-mux.c
drivers/net/phy/mdio_bus.c
drivers/net/phy/micrel.c
drivers/net/phy/phy_device.c
drivers/net/phy/smsc.c
drivers/net/phy/vitesse.c
drivers/net/ppp/ppp_generic.c
drivers/net/ppp/pppoe.c
drivers/net/usb/Kconfig
drivers/net/usb/Makefile
drivers/net/usb/asix_common.c
drivers/net/usb/asix_devices.c
drivers/net/usb/ch9200.c [new file with mode: 0644]
drivers/net/usb/qmi_wwan.c
drivers/net/vrf.c
drivers/net/vxlan.c
drivers/net/wireless/ath/ath10k/hw.h
drivers/net/wireless/ath/ath6kl/init.c
drivers/net/wireless/ath/ath9k/init.c
drivers/net/wireless/b43/main.c
drivers/net/wireless/iwlwifi/dvm/lib.c
drivers/net/wireless/iwlwifi/iwl-7000.c
drivers/net/wireless/iwlwifi/mvm/d3.c
drivers/net/wireless/iwlwifi/mvm/fw.c
drivers/net/wireless/iwlwifi/mvm/mac80211.c
drivers/net/wireless/iwlwifi/mvm/mvm.h
drivers/net/wireless/iwlwifi/mvm/ops.c
drivers/net/wireless/iwlwifi/pcie/drv.c
drivers/net/wireless/rt2x00/rt2800usb.c
drivers/net/wireless/rtlwifi/pci.h
drivers/net/wireless/rtlwifi/rtl8821ae/hw.c
drivers/net/wireless/rtlwifi/rtl8821ae/sw.c
drivers/net/wireless/rtlwifi/wifi.h
drivers/net/xen-netback/xenbus.c
drivers/net/xen-netfront.c
drivers/nvdimm/btt_devs.c
drivers/nvdimm/pfn_devs.c
drivers/nvdimm/pmem.c
drivers/nvmem/core.c
drivers/nvmem/sunxi_sid.c
drivers/of/of_mdio.c
drivers/of/of_pci_irq.c
drivers/parisc/dino.c
drivers/parisc/lba_pci.c
drivers/pci/access.c
drivers/pci/bus.c
drivers/pci/host/pci-keystone.c
drivers/pci/host/pci-rcar-gen2.c
drivers/pci/host/pci-xgene-msi.c
drivers/pci/msi.c
drivers/pci/pci-driver.c
drivers/pci/pci-sysfs.c
drivers/pci/probe.c
drivers/pci/quirks.c
drivers/perf/arm_pmu.c
drivers/phy/phy-berlin-sata.c
drivers/phy/phy-qcom-ufs.c
drivers/phy/phy-rockchip-usb.c
drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c
drivers/pinctrl/core.c
drivers/pinctrl/freescale/pinctrl-imx25.c
drivers/pinctrl/intel/pinctrl-baytrail.c
drivers/pinctrl/intel/pinctrl-cherryview.c
drivers/pinctrl/intel/pinctrl-intel.c
drivers/pinctrl/mediatek/pinctrl-mtk-common.c
drivers/pinctrl/nomadik/pinctrl-nomadik.c
drivers/pinctrl/pinctrl-adi2.c
drivers/pinctrl/pinctrl-amd.c
drivers/pinctrl/pinctrl-at91.c
drivers/pinctrl/pinctrl-coh901.c
drivers/pinctrl/pinctrl-digicolor.c
drivers/pinctrl/pinctrl-pistachio.c
drivers/pinctrl/pinctrl-rockchip.c
drivers/pinctrl/pinctrl-single.c
drivers/pinctrl/pinctrl-st.c
drivers/pinctrl/pinmux.c
drivers/pinctrl/qcom/pinctrl-msm.c
drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c
drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c
drivers/pinctrl/samsung/pinctrl-exynos.c
drivers/pinctrl/samsung/pinctrl-s3c24xx.c
drivers/pinctrl/samsung/pinctrl-s3c64xx.c
drivers/pinctrl/sirf/pinctrl-atlas7.c
drivers/pinctrl/sirf/pinctrl-sirf.c
drivers/pinctrl/spear/pinctrl-plgpio.c
drivers/pinctrl/sunxi/pinctrl-sun5i-a10s.c
drivers/pinctrl/sunxi/pinctrl-sunxi.c
drivers/pinctrl/uniphier/pinctrl-ph1-sld8.c
drivers/platform/x86/asus-nb-wmi.c
drivers/platform/x86/hp-wmi.c
drivers/platform/x86/toshiba_acpi.c
drivers/platform/x86/wmi.c
drivers/power/twl4030_charger.c
drivers/regulator/anatop-regulator.c
drivers/regulator/axp20x-regulator.c
drivers/regulator/core.c
drivers/regulator/gpio-regulator.c
drivers/regulator/pbias-regulator.c
drivers/regulator/tps65218-regulator.c
drivers/regulator/vexpress.c
drivers/s390/virtio/virtio_ccw.c
drivers/scsi/3w-9xxx.c
drivers/scsi/libiscsi.c
drivers/scsi/mvsas/mv_sas.c
drivers/scsi/scsi_dh.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_priv.h
drivers/scsi/scsi_sysfs.c
drivers/sh/intc/core.c
drivers/sh/intc/internals.h
drivers/sh/intc/virq.c
drivers/sh/pm_runtime.c
drivers/soc/dove/pmu.c
drivers/spi/Kconfig
drivers/spi/Makefile
drivers/spi/spi-ath79.c
drivers/spi/spi-atmel.c
drivers/spi/spi-au1550.c
drivers/spi/spi-bcm2835.c
drivers/spi/spi-bcm2835aux.c [new file with mode: 0644]
drivers/spi/spi-bcm53xx.c
drivers/spi/spi-bcm63xx.c
drivers/spi/spi-bfin-sport.c
drivers/spi/spi-bfin5xx.c
drivers/spi/spi-bitbang.c
drivers/spi/spi-coldfire-qspi.c
drivers/spi/spi-davinci.c
drivers/spi/spi-dw-mmio.c
drivers/spi/spi-dw-pci.c
drivers/spi/spi-dw.c
drivers/spi/spi-dw.h
drivers/spi/spi-imx.c
drivers/spi/spi-meson-spifc.c
drivers/spi/spi-mpc512x-psc.c
drivers/spi/spi-mt65xx.c
drivers/spi/spi-oc-tiny.c
drivers/spi/spi-octeon.c
drivers/spi/spi-omap2-mcspi.c
drivers/spi/spi-ppc4xx.c
drivers/spi/spi-pxa2xx.c
drivers/spi/spi-s3c24xx.c
drivers/spi/spi-ti-qspi.c
drivers/spi/spi-xilinx.c
drivers/spi/spi-xtensa-xtfpga.c
drivers/spi/spi.c
drivers/spi/spidev.c
drivers/spmi/spmi-pmic-arb.c
drivers/staging/android/TODO
drivers/staging/android/ion/ion.c
drivers/staging/fbtft/fb_uc1611.c
drivers/staging/fbtft/fb_watterott.c
drivers/staging/fbtft/fbtft-core.c
drivers/staging/fbtft/flexfb.c
drivers/staging/iio/accel/sca3000_ring.c
drivers/staging/iio/adc/mxs-lradc.c
drivers/staging/lustre/README.txt
drivers/staging/lustre/lustre/llite/dir.c
drivers/staging/most/Kconfig
drivers/staging/most/hdm-dim2/Kconfig
drivers/staging/most/hdm-usb/Kconfig
drivers/staging/most/mostcore/Kconfig
drivers/staging/rdma/Kconfig
drivers/staging/rdma/Makefile
drivers/staging/rdma/ehca/Kconfig [new file with mode: 0644]
drivers/staging/rdma/ehca/Makefile [new file with mode: 0644]
drivers/staging/rdma/ehca/TODO [new file with mode: 0644]
drivers/staging/rdma/ehca/ehca_av.c [new file with mode: 0644]
drivers/staging/rdma/ehca/ehca_classes.h [new file with mode: 0644]
drivers/staging/rdma/ehca/ehca_classes_pSeries.h [new file with mode: 0644]
drivers/staging/rdma/ehca/ehca_cq.c [new file with mode: 0644]
drivers/staging/rdma/ehca/ehca_eq.c [new file with mode: 0644]
drivers/staging/rdma/ehca/ehca_hca.c [new file with mode: 0644]
drivers/staging/rdma/ehca/ehca_irq.c [new file with mode: 0644]
drivers/staging/rdma/ehca/ehca_irq.h [new file with mode: 0644]
drivers/staging/rdma/ehca/ehca_iverbs.h [new file with mode: 0644]
drivers/staging/rdma/ehca/ehca_main.c [new file with mode: 0644]
drivers/staging/rdma/ehca/ehca_mcast.c [new file with mode: 0644]
drivers/staging/rdma/ehca/ehca_mrmw.c [new file with mode: 0644]
drivers/staging/rdma/ehca/ehca_mrmw.h [new file with mode: 0644]
drivers/staging/rdma/ehca/ehca_pd.c [new file with mode: 0644]
drivers/staging/rdma/ehca/ehca_qes.h [new file with mode: 0644]
drivers/staging/rdma/ehca/ehca_qp.c [new file with mode: 0644]
drivers/staging/rdma/ehca/ehca_reqs.c [new file with mode: 0644]
drivers/staging/rdma/ehca/ehca_sqp.c [new file with mode: 0644]
drivers/staging/rdma/ehca/ehca_tools.h [new file with mode: 0644]
drivers/staging/rdma/ehca/ehca_uverbs.c [new file with mode: 0644]
drivers/staging/rdma/ehca/hcp_if.c [new file with mode: 0644]
drivers/staging/rdma/ehca/hcp_if.h [new file with mode: 0644]
drivers/staging/rdma/ehca/hcp_phyp.c [new file with mode: 0644]
drivers/staging/rdma/ehca/hcp_phyp.h [new file with mode: 0644]
drivers/staging/rdma/ehca/hipz_fns.h [new file with mode: 0644]
drivers/staging/rdma/ehca/hipz_fns_core.h [new file with mode: 0644]
drivers/staging/rdma/ehca/hipz_hw.h [new file with mode: 0644]
drivers/staging/rdma/ehca/ipz_pt_fn.c [new file with mode: 0644]
drivers/staging/rdma/ehca/ipz_pt_fn.h [new file with mode: 0644]
drivers/staging/rdma/hfi1/chip.c
drivers/staging/rdma/hfi1/device.c
drivers/staging/rdma/hfi1/device.h
drivers/staging/rdma/hfi1/diag.c
drivers/staging/rdma/hfi1/file_ops.c
drivers/staging/rdma/hfi1/mad.c
drivers/staging/rdma/hfi1/sdma.c
drivers/staging/rdma/hfi1/sdma.h
drivers/staging/rdma/hfi1/verbs.c
drivers/staging/speakup/fakekey.c
drivers/staging/unisys/visorbus/Makefile
drivers/staging/unisys/visorbus/visorbus_main.c
drivers/staging/unisys/visornic/visornic_main.c
drivers/target/iscsi/iscsi_target_parameters.c
drivers/target/target_core_device.c
drivers/target/target_core_hba.c
drivers/target/target_core_iblock.c
drivers/target/target_core_pr.c
drivers/target/target_core_tpg.c
drivers/thermal/Kconfig
drivers/thermal/cpu_cooling.c
drivers/thermal/db8500_cpufreq_cooling.c
drivers/thermal/power_allocator.c
drivers/thermal/samsung/exynos_tmu.c
drivers/thermal/thermal_core.c
drivers/thermal/ti-soc-thermal/Kconfig
drivers/thunderbolt/nhi.c
drivers/tty/n_tty.c
drivers/tty/serial/8250/8250_dma.c
drivers/tty/serial/8250/8250_port.c
drivers/tty/serial/atmel_serial.c
drivers/tty/serial/imx.c
drivers/tty/tty_buffer.c
drivers/tty/tty_io.c
drivers/usb/chipidea/ci_hdrc_imx.c
drivers/usb/chipidea/ci_hdrc_usb2.c
drivers/usb/chipidea/udc.c
drivers/usb/core/config.c
drivers/usb/core/quirks.c
drivers/usb/dwc3/dwc3-omap.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/epautoconf.c
drivers/usb/gadget/udc/amd5536udc.c
drivers/usb/gadget/udc/atmel_usba_udc.c
drivers/usb/gadget/udc/bdc/bdc_core.c
drivers/usb/gadget/udc/bdc/bdc_ep.c
drivers/usb/gadget/udc/dummy_hcd.c
drivers/usb/gadget/udc/gr_udc.c
drivers/usb/gadget/udc/mv_u3d_core.c
drivers/usb/gadget/udc/mv_udc_core.c
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/misc/chaoskey.c
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_cppi41.c
drivers/usb/musb/musb_dsps.c
drivers/usb/musb/omap2430.c
drivers/usb/musb/ux500.c
drivers/usb/phy/Kconfig
drivers/usb/phy/phy-generic.c
drivers/usb/phy/phy-isp1301.c
drivers/usb/renesas_usbhs/common.c
drivers/usb/serial/option.c
drivers/usb/serial/whiteheat.c
drivers/vhost/net.c
drivers/vhost/scsi.c
drivers/vhost/test.c
drivers/vhost/vhost.h
drivers/video/console/fbcon.c
drivers/video/fbdev/broadsheetfb.c
drivers/video/fbdev/fsl-diu-fb.c
drivers/video/fbdev/mb862xx/mb862xxfbdrv.c
drivers/video/fbdev/omap2/displays-new/connector-dvi.c
drivers/video/fbdev/omap2/displays-new/panel-sony-acx565akm.c
drivers/video/fbdev/tridentfb.c
drivers/video/of_display_timing.c
drivers/watchdog/Kconfig
drivers/watchdog/bcm2835_wdt.c
drivers/watchdog/gef_wdt.c
drivers/watchdog/mena21_wdt.c
drivers/watchdog/moxart_wdt.c
fs/block_dev.c
fs/btrfs/backref.c
fs/btrfs/btrfs_inode.h
fs/btrfs/disk-io.c
fs/btrfs/export.c
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/file.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/send.c
fs/btrfs/super.c
fs/btrfs/transaction.c
fs/btrfs/transaction.h
fs/btrfs/volumes.h
fs/cifs/cifsencrypt.c
fs/cifs/cifsfs.c
fs/cifs/cifsfs.h
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/ioctl.c
fs/cifs/smb2ops.c
fs/cifs/smb2pdu.c
fs/dax.c
fs/ext4/Kconfig
fs/ext4/readpage.c
fs/fs-writeback.c
fs/mpage.c
fs/namei.c
fs/nfs/delegation.c
fs/nfs/delegation.h
fs/nfs/direct.c
fs/nfs/filelayout/filelayout.c
fs/nfs/nfs42proc.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfs/nfs4trace.h
fs/nfs/pagelist.c
fs/nfs/pnfs.c
fs/nfs/pnfs.h
fs/nfs/read.c
fs/nfs/write.c
fs/nfsd/blocklayout.c
fs/ocfs2/dlm/dlmmaster.c
fs/ocfs2/dlm/dlmrecovery.c
fs/overlayfs/copy_up.c
fs/overlayfs/inode.c
fs/overlayfs/super.c
fs/ramfs/file-nommu.c
fs/ubifs/xattr.c
fs/userfaultfd.c
include/acpi/button.h
include/acpi/video.h
include/asm-generic/memory_model.h
include/asm-generic/qspinlock.h
include/asm-generic/word-at-a-time.h
include/drm/drm_crtc_helper.h
include/drm/drm_dp_helper.h
include/drm/drm_dp_mst_helper.h
include/kvm/arm_vgic.h
include/linux/acpi.h
include/linux/backing-dev-defs.h
include/linux/backing-dev.h
include/linux/blk-cgroup.h
include/linux/blk-mq.h
include/linux/blkdev.h
include/linux/ceph/ceph_features.h
include/linux/ceph/messenger.h
include/linux/cgroup-defs.h
include/linux/clockchips.h
include/linux/cma.h
include/linux/compiler-gcc.h
include/linux/compiler.h
include/linux/cpufreq.h
include/linux/devfreq.h
include/linux/dma-contiguous.h
include/linux/init_task.h
include/linux/iova.h
include/linux/irq.h
include/linux/irqdesc.h
include/linux/irqdomain.h
include/linux/irqhandler.h
include/linux/jump_label.h
include/linux/memcontrol.h
include/linux/mlx5/device.h
include/linux/mlx5/driver.h
include/linux/mm.h
include/linux/netdevice.h
include/linux/omap-dma.h
include/linux/phy.h
include/linux/rcupdate.h
include/linux/sched.h
include/linux/security.h
include/linux/skbuff.h
include/linux/spi/spi.h
include/linux/spi/spi_bitbang.h
include/linux/string.h
include/linux/sunrpc/xprtsock.h
include/linux/thermal.h
include/linux/tick.h
include/linux/usb/renesas_usbhs.h
include/linux/wait.h
include/net/af_unix.h
include/net/dst_metadata.h
include/net/flow.h
include/net/inet_timewait_sock.h
include/net/ip6_fib.h
include/net/ip6_tunnel.h
include/net/ip_fib.h
include/net/ip_tunnels.h
include/net/route.h
include/net/sock.h
include/rdma/opa_port_info.h
include/sound/soc.h
include/sound/wm8904.h
include/target/target_core_base.h
include/uapi/asm-generic/signal.h
include/uapi/asm-generic/unistd.h
include/uapi/linux/lwtunnel.h
include/uapi/linux/openvswitch.h
include/uapi/linux/rtnetlink.h
include/uapi/linux/userfaultfd.h
include/xen/interface/sched.h
ipc/msg.c
ipc/shm.c
ipc/util.c
kernel/cgroup.c
kernel/events/core.c
kernel/fork.c
kernel/irq/chip.c
kernel/irq/handle.c
kernel/irq/internals.h
kernel/irq/irqdesc.c
kernel/irq/irqdomain.c
kernel/irq/manage.c
kernel/irq/msi.c
kernel/irq/proc.c
kernel/irq/resend.c
kernel/kmod.c
kernel/locking/lockdep.c
kernel/locking/qspinlock.c
kernel/memremap.c
kernel/module.c
kernel/rcu/tree.c
kernel/sched/core.c
kernel/sched/deadline.c
kernel/sched/fair.c
kernel/sched/idle.c
kernel/sched/sched.h
kernel/sched/wait.c
kernel/time/clockevents.c
kernel/time/clocksource.c
kernel/time/tick-common.c
kernel/time/tick-sched.c
kernel/time/timekeeping.c
kernel/time/timer_list.c
kernel/trace/trace_stack.c
kernel/workqueue.c
lib/Kconfig
lib/Kconfig.debug
lib/fault-inject.c
lib/iommu-common.c
lib/rhashtable.c
lib/string.c
lib/string_helpers.c
mm/backing-dev.c
mm/cma.c
mm/dmapool.c
mm/filemap.c
mm/huge_memory.c
mm/hugetlb.c
mm/kasan/kasan.c
mm/memcontrol.c
mm/memory.c
mm/migrate.c
mm/mmap.c
mm/page-writeback.c
mm/readahead.c
mm/slab.c
mm/vmscan.c
mm/vmstat.c
net/atm/clip.c
net/bluetooth/hci_conn.c
net/bluetooth/hci_core.c
net/bluetooth/hci_event.c
net/bluetooth/mgmt.c
net/bluetooth/smp.c
net/bridge/br_multicast.c
net/ceph/messenger.c
net/ceph/osd_client.c
net/core/dev.c
net/core/ethtool.c
net/core/fib_rules.c
net/core/filter.c
net/core/net-sysfs.c
net/core/netpoll.c
net/core/rtnetlink.c
net/core/skbuff.c
net/core/sock.c
net/dccp/ackvec.c
net/dccp/ccid.c
net/dccp/minisocks.c
net/dsa/dsa.c
net/dsa/slave.c
net/dsa/tag_trailer.c
net/ipv4/arp.c
net/ipv4/fib_frontend.c
net/ipv4/fib_trie.c
net/ipv4/gre_offload.c
net/ipv4/icmp.c
net/ipv4/inet_connection_sock.c
net/ipv4/inet_timewait_sock.c
net/ipv4/ip_gre.c
net/ipv4/ip_tunnel_core.c
net/ipv4/netfilter/Kconfig
net/ipv4/netfilter/ipt_rpfilter.c
net/ipv4/route.c
net/ipv4/tcp_cubic.c
net/ipv4/tcp_dctcp.c
net/ipv4/tcp_minisocks.c
net/ipv4/tcp_output.c
net/ipv4/udp.c
net/ipv4/xfrm4_output.c
net/ipv4/xfrm4_policy.c
net/ipv6/addrconf.c
net/ipv6/fib6_rules.c
net/ipv6/ip6_fib.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_output.c
net/ipv6/ip6_tunnel.c
net/ipv6/netfilter/Kconfig
net/ipv6/netfilter/nf_conntrack_reasm.c
net/ipv6/route.c
net/ipv6/xfrm6_output.c
net/ipv6/xfrm6_policy.c
net/irda/irlmp.c
net/key/af_key.c
net/l2tp/l2tp_core.c
net/mac80211/cfg.c
net/mac80211/debugfs.c
net/mac80211/status.c
net/mac80211/tx.c
net/netfilter/core.c
net/netfilter/ipset/ip_set_list_set.c
net/netfilter/nf_log.c
net/netfilter/nft_compat.c
net/netlink/af_netlink.c
net/netlink/af_netlink.h
net/openvswitch/Kconfig
net/openvswitch/actions.c
net/openvswitch/conntrack.c
net/openvswitch/conntrack.h
net/openvswitch/datapath.c
net/openvswitch/datapath.h
net/openvswitch/flow.h
net/openvswitch/flow_netlink.c
net/openvswitch/flow_netlink.h
net/openvswitch/flow_table.c
net/openvswitch/flow_table.h
net/openvswitch/vport-geneve.c
net/openvswitch/vport-gre.c
net/openvswitch/vport-internal_dev.c
net/openvswitch/vport-vxlan.c
net/openvswitch/vport.c
net/openvswitch/vport.h
net/packet/af_packet.c
net/rds/tcp_recv.c
net/sched/act_mirred.c
net/sched/cls_fw.c
net/sched/sch_hhf.c
net/sctp/associola.c
net/sctp/protocol.c
net/sctp/sm_sideeffect.c
net/sunrpc/sched.c
net/sunrpc/xprt.c
net/sunrpc/xprtrdma/fmr_ops.c
net/sunrpc/xprtrdma/frwr_ops.c
net/sunrpc/xprtrdma/physical_ops.c
net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
net/sunrpc/xprtrdma/transport.c
net/sunrpc/xprtrdma/verbs.c
net/sunrpc/xprtrdma/xprt_rdma.h
net/sunrpc/xprtsock.c
net/switchdev/switchdev.c
net/sysctl_net.c
net/tipc/bcast.c
net/tipc/msg.c
net/tipc/msg.h
net/tipc/node.c
net/tipc/udp_media.c
net/unix/af_unix.c
net/vmw_vsock/af_vsock.c
net/vmw_vsock/vmci_transport.c
net/vmw_vsock/vmci_transport.h
net/xfrm/xfrm_user.c
samples/bpf/bpf_helpers.h
samples/kprobes/jprobe_example.c
samples/kprobes/kprobe_example.c
samples/kprobes/kretprobe_example.c
scripts/extract-cert.c
scripts/package/builddeb
scripts/sign-file.c
security/device_cgroup.c
security/keys/gc.c
security/keys/request_key.c
sound/arm/Kconfig
sound/hda/ext/hdac_ext_bus.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_tegra.c
sound/pci/hda/patch_cirrus.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/soc/au1x/db1200.c
sound/soc/au1x/psc-i2s.c
sound/soc/codecs/rt298.c
sound/soc/codecs/rt5645.c
sound/soc/codecs/rt5645.h
sound/soc/codecs/sgtl5000.c
sound/soc/codecs/tas2552.c
sound/soc/codecs/tlv320aic3x.c
sound/soc/codecs/wm0010.c
sound/soc/codecs/wm8960.c
sound/soc/codecs/wm8962.c
sound/soc/davinci/davinci-mcasp.c
sound/soc/dwc/designware_i2s.c
sound/soc/fsl/fsl-asoc-card.c
sound/soc/fsl/fsl_ssi.c
sound/soc/fsl/imx-ssi.c
sound/soc/intel/haswell/sst-haswell-ipc.c
sound/soc/mediatek/mtk-afe-pcm.c
sound/soc/pxa/Kconfig
sound/soc/pxa/pxa2xx-ac97.c
sound/soc/soc-dapm.c
sound/soc/soc-ops.c
sound/soc/soc-utils.c
sound/soc/spear/Kconfig
sound/soc/sti/uniperif_player.c
sound/soc/sti/uniperif_reader.c
sound/synth/emux/emux_oss.c
tools/build/Makefile.feature
tools/build/feature/Makefile
tools/build/feature/test-all.c
tools/build/feature/test-get_cpuid.c [new file with mode: 0644]
tools/build/feature/test-numa_num_possible_cpus.c [new file with mode: 0644]
tools/lib/traceevent/event-parse.c
tools/perf/Documentation/intel-pt.txt
tools/perf/builtin-script.c
tools/perf/config/Makefile
tools/perf/tests/sw-clock.c
tools/perf/tests/task-exit.c
tools/perf/ui/browsers/hists.c
tools/perf/util/Build
tools/perf/util/evlist.c
tools/perf/util/evlist.h
tools/perf/util/evsel.c
tools/perf/util/evsel.h
tools/perf/util/header.c
tools/perf/util/intel-bts.c
tools/perf/util/intel-pt.c
tools/perf/util/parse-events.c
tools/perf/util/parse-events.y
tools/perf/util/perf_regs.c
tools/perf/util/perf_regs.h
tools/perf/util/probe-event.c
tools/perf/util/session.c
tools/perf/util/stat.c
tools/perf/util/symbol-elf.c
tools/perf/util/util.c
tools/power/x86/turbostat/turbostat.c
tools/testing/selftests/Makefile
tools/testing/selftests/exec/Makefile
tools/testing/selftests/ftrace/Makefile
tools/testing/selftests/lib.mk
tools/testing/selftests/membarrier/Makefile
tools/testing/selftests/membarrier/membarrier_test.c
tools/testing/selftests/mqueue/Makefile
tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c
tools/testing/selftests/seccomp/seccomp_bpf.c
tools/testing/selftests/seccomp/test_harness.h
tools/testing/selftests/vm/Makefile
tools/testing/selftests/vm/userfaultfd.c
tools/testing/selftests/x86/entry_from_vm86.c
tools/testing/selftests/zram/zram.sh
tools/testing/selftests/zram/zram_lib.sh
tools/virtio/Makefile
tools/virtio/asm/barrier.h
tools/virtio/linux/export.h [new file with mode: 0644]
tools/virtio/linux/kernel.h
virt/kvm/arm/arch_timer.c
virt/kvm/arm/vgic-v3.c
virt/kvm/arm/vgic.c
virt/kvm/coalesced_mmio.h
virt/kvm/eventfd.c
virt/kvm/kvm_main.c

index 4b31af54ccd5864359c0810f9733f3026181a631..b1e9a97653dc64853775a97db377a8f269cc8d95 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -59,6 +59,7 @@ James Bottomley <jejb@mulgrave.(none)>
 James Bottomley <jejb@titanic.il.steeleye.com>
 James E Wilson <wilson@specifix.com>
 James Ketrenos <jketreno@io.(none)>
+<javier@osg.samsung.com> <javier.martinez@collabora.co.uk>
 Jean Tourrilhes <jt@hpl.hp.com>
 Jeff Garzik <jgarzik@pretzel.yyz.us>
 Jens Axboe <axboe@suse.de>
index 6d886300485827846541744075f7919be3d16200..f447f0516f074c700b0c78ca87fcfcf4595ea49f 100644 (file)
@@ -43,7 +43,7 @@ o  udev                   081                     # udevd --version
 o  grub                   0.93                    # grub --version || grub-install --version
 o  mcelog                 0.6                     # mcelog --version
 o  iptables               1.4.2                   # iptables -V
-o  openssl & libcrypto    1.0.1k                  # openssl version
+o  openssl & libcrypto    1.0.                  # openssl version
 
 
 Kernel compilation
diff --git a/Documentation/arm/OMAP/README b/Documentation/arm/OMAP/README
new file mode 100644 (file)
index 0000000..75645c4
--- /dev/null
@@ -0,0 +1,7 @@
+This file contains documentation for running mainline
+kernel on omaps.
+
+KERNEL         NEW DEPENDENCIES
+v4.3+          Update is needed for custom .config files to make sure
+               CONFIG_REGULATOR_PBIAS is enabled for MMC1 to work
+               properly.
index 0d5bc46dc1676869358cd6f36975905031f17f9e..ad6949bff2e392d63e7ddb82391746687ea6235e 100644 (file)
@@ -41,9 +41,13 @@ useless and be disabled, returning errors.  So it is important to monitor
 the amount of free space and expand the <COW device> before it fills up.
 
 <persistent?> is P (Persistent) or N (Not persistent - will not survive
-after reboot).
-The difference is that for transient snapshots less metadata must be
-saved on disk - they can be kept in memory by the kernel.
+after reboot).  O (Overflow) can be added as a persistent store option
+to allow userspace to advertise its support for seeing "Overflow" in the
+snapshot status.  So supported store types are "P", "PO" and "N".
+
+The difference between persistent and transient is with transient
+snapshots less metadata must be saved on disk - they can be kept in
+memory by the kernel.
 
 
 * snapshot-merge <origin> <COW device> <persistent> <chunksize>
index ddfade40ac596ca773fd4763d1e3b60b6f42209e..7803e77d85cbe9d69dfcd42405ece4de0ddfe329 100644 (file)
@@ -57,6 +57,8 @@ used to route Message Signalled Interrupts (MSI) to the CPUs.
 These nodes must have the following properties:
 - compatible : Should at least contain  "arm,gic-v3-its".
 - msi-controller : Boolean property. Identifies the node as an MSI controller
+- #msi-cells: Must be <1>. The single msi-cell is the DeviceID of the device
+  which will generate the MSI.
 - reg: Specifies the base physical address and size of the ITS
   registers.
 
@@ -83,6 +85,7 @@ Examples:
                gic-its@2c200000 {
                        compatible = "arm,gic-v3-its";
                        msi-controller;
+                       #msi-cells = <1>;
                        reg = <0x0 0x2c200000 0 0x200000>;
                };
        };
@@ -107,12 +110,14 @@ Examples:
                gic-its@2c200000 {
                        compatible = "arm,gic-v3-its";
                        msi-controller;
+                       #msi-cells = <1>;
                        reg = <0x0 0x2c200000 0 0x200000>;
                };
 
                gic-its@2c400000 {
                        compatible = "arm,gic-v3-its";
                        msi-controller;
+                       #msi-cells = <1>;
                        reg = <0x0 0x2c400000 0 0x200000>;
                };
        };
index a8274eabae2e12d75f23fd95b9df59e02be21bc2..b8e41c148a3c1d75ac8e45b8ff3e87fff2631d19 100644 (file)
@@ -497,7 +497,7 @@ cpus {
        };
 
        idle-states {
-               entry-method = "arm,psci";
+               entry-method = "psci";
 
                CPU_RETENTION_0_0: cpu-retention-0-0 {
                        compatible = "arm,idle-state";
index 5788d5cf12524b95c556ec0451204c3b735f6d43..82d40e2505f641be635dd8769b0051508bcf0120 100644 (file)
@@ -16,7 +16,9 @@ properties, each containing a 'gpio-list':
 GPIO properties should be named "[<name>-]gpios", with <name> being the purpose
 of this GPIO for the device. While a non-existent <name> is considered valid
 for compatibility reasons (resolving to the "gpios" property), it is not allowed
-for new bindings.
+for new bindings. Also, GPIO properties named "[<name>-]gpio" are valid and old
+bindings use it, but are only supported for compatibility reasons and should not
+be used for newer bindings since it has been deprecated.
 
 GPIO properties can contain one or more GPIO phandles, but only in exceptional
 cases should they contain more than one. If your device uses several GPIOs with
index c5933573e0f6d920951da90806ab1900b905beb5..4a3679d5445760b517883a72c9a12352d88c86a6 100644 (file)
@@ -1,10 +1,11 @@
-* Bosch BMA180 triaxial acceleration sensor
+* Bosch BMA180 / BMA250 triaxial acceleration sensor
 
 http://omapworld.com/BMA180_111_1002839.pdf
+http://ae-bst.resource.bosch.com/media/products/dokumente/bma250/bst-bma250-ds002-05.pdf
 
 Required properties:
 
-  - compatible : should be "bosch,bma180"
+  - compatible : should be "bosch,bma180" or "bosch,bma250"
   - reg : the I2C address of the sensor
 
 Optional properties:
@@ -13,6 +14,9 @@ Optional properties:
 
   - interrupts : interrupt mapping for GPIO IRQ, it should by configured with
                flags IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_EDGE_RISING
+               For the bma250 the first interrupt listed must be the one
+               connected to the INT1 pin, the second (optional) interrupt
+               listed must be the one connected to the INT2 pin.
 
 Example:
 
index 635a3b03663002d8f4eb47b25fd504d2a7ebca93..8d91ba9ff2fd0918bbf18fc1149f2fb3613bf80e 100644 (file)
@@ -25,7 +25,7 @@ Example:
                /* Cypress Gen3 touchpad */
                touchpad@67 {
                        compatible = "cypress,cyapa";
-                       reg = <0x24>;
+                       reg = <0x67>;
                        interrupt-parent = <&gpio>;
                        interrupts = <2 IRQ_TYPE_EDGE_FALLING>; /* GPIO 2 */
                        wakeup-source;
index 391717a68f3b1dffe100762775a4bd0368184a83..ec96b1f0147886102554c16e3bd260dc3f425619 100644 (file)
@@ -4,8 +4,8 @@ The MISC interrupt controller is a secondary controller for lower priority
 interrupt.
 
 Required Properties:
-- compatible: has to be "qca,<soctype>-cpu-intc", "qca,ar7100-misc-intc"
-  as fallback
+- compatible: has to be "qca,<soctype>-cpu-intc", "qca,ar7100-misc-intc" or
+  "qca,<soctype>-cpu-intc", "qca,ar7240-misc-intc"
 - reg: Base address and size of the controllers memory area
 - interrupt-parent: phandle of the parent interrupt controller.
 - interrupts: Interrupt specifier for the controllers interrupt.
@@ -13,6 +13,9 @@ Required Properties:
 - #interrupt-cells : Specifies the number of cells needed to encode interrupt
                     source, should be 1
 
+Compatible fallback depends on the SoC. Use ar7100 for ar71xx and ar913x,
+use ar7240 for all other SoCs.
+
 Please refer to interrupts.txt in this directory for details of the common
 Interrupt Controllers bindings used by client devices.
 
@@ -28,3 +31,16 @@ Example:
                interrupt-controller;
                #interrupt-cells = <1>;
        };
+
+Another example:
+
+       interrupt-controller@18060010 {
+               compatible = "qca,ar9331-misc-intc", qca,ar7240-misc-intc";
+               reg = <0x18060010 0x4>;
+
+               interrupt-parent = <&cpuintc>;
+               interrupts = <6>;
+
+               interrupt-controller;
+               #interrupt-cells = <1>;
+       };
index a9df21aaa1548a64da26c74dfbbef13e652cf3da..a2cae4eb4a60a38c83059c66934e6462ca5a2c6c 100644 (file)
@@ -39,6 +39,7 @@ Required properties:
 Optional properties:
 - dual_emac_res_vlan   : Specifies VID to be used to segregate the ports
 - mac-address          : See ethernet.txt file in the same directory
+- phy-handle           : See ethernet.txt file in the same directory
 
 Note: "ti,hwmods" field is used to fetch the base address and irq
 resources from TI, omap hwmod data base during device registration.
diff --git a/Documentation/devicetree/bindings/net/smsc-lan87xx.txt b/Documentation/devicetree/bindings/net/smsc-lan87xx.txt
new file mode 100644 (file)
index 0000000..974edd5
--- /dev/null
@@ -0,0 +1,24 @@
+SMSC LAN87xx Ethernet PHY
+
+Some boards require special tuning values. Configure them
+through an Ethernet OF device node.
+
+Optional properties:
+
+- smsc,disable-energy-detect:
+  If set, do not enable energy detect mode for the SMSC phy.
+  default: enable energy detect mode
+
+Examples:
+smsc phy with disabled energy detect mode on an am335x based board.
+&davinci_mdio {
+       pinctrl-names = "default", "sleep";
+       pinctrl-0 = <&davinci_mdio_default>;
+       pinctrl-1 = <&davinci_mdio_sleep>;
+       status = "okay";
+
+       ethernetphy0: ethernet-phy@0 {
+               reg = <0>;
+               smsc,disable-energy-detect;
+       };
+};
index d8ef5bf50f113939b645d4c54f9006c030752b57..7fab84b335313bbd8abc668f347f06c8d0cfe87d 100644 (file)
@@ -7,7 +7,8 @@ OHCI and EHCI controllers.
 
 Required properties:
 - compatible: "renesas,pci-r8a7790" for the R8A7790 SoC;
-             "renesas,pci-r8a7791" for the R8A7791 SoC.
+             "renesas,pci-r8a7791" for the R8A7791 SoC;
+             "renesas,pci-r8a7794" for the R8A7794 SoC.
 - reg: A list of physical regions to access the device: the first is
        the operational registers for the OHCI/EHCI controllers and the
        second is for the bridge configuration and control registers.
index 32aa26f1e434561b60a6256e3b14e1ec71ede853..acbcb452a69ab40d528954634517dc94f9620065 100644 (file)
@@ -2,7 +2,12 @@ PBIAS internal regulator for SD card dual voltage i/o pads on OMAP SoCs.
 
 Required properties:
 - compatible:
-  - "ti,pbias-omap" for OMAP2, OMAP3, OMAP4, OMAP5, DRA7.
+  - should be "ti,pbias-dra7" for DRA7
+  - should be "ti,pbias-omap2" for OMAP2
+  - should be "ti,pbias-omap3" for OMAP3
+  - should be "ti,pbias-omap4" for OMAP4
+  - should be "ti,pbias-omap5" for OMAP5
+  - "ti,pbias-omap" is deprecated
 - reg: pbias register offset from syscon base and size of pbias register.
 - syscon : phandle of the system control module
 - regulator-name : should be
diff --git a/Documentation/devicetree/bindings/spi/brcm,bcm2835-aux-spi.txt b/Documentation/devicetree/bindings/spi/brcm,bcm2835-aux-spi.txt
new file mode 100644 (file)
index 0000000..9887b07
--- /dev/null
@@ -0,0 +1,38 @@
+Broadcom BCM2835 auxiliar SPI1/2 controller
+
+The BCM2835 contains two forms of SPI master controller, one known simply as
+SPI0, and the other known as the "Universal SPI Master"; part of the
+auxiliary block. This binding applies to the SPI1/2 controller.
+
+Required properties:
+- compatible: Should be "brcm,bcm2835-aux-spi".
+- reg: Should contain register location and length for the spi block
+- interrupts: Should contain shared interrupt of the aux block
+- clocks: The clock feeding the SPI controller - needs to
+         point to the auxiliar clock driver of the bcm2835,
+         as this clock will enable the output gate for the specific
+         clock.
+- cs-gpios: the cs-gpios (native cs is NOT supported)
+           see also spi-bus.txt
+
+Example:
+
+spi1@7e215080 {
+       compatible = "brcm,bcm2835-aux-spi";
+       reg = <0x7e215080 0x40>;
+       interrupts = <1 29>;
+       clocks = <&aux_clocks BCM2835_AUX_CLOCK_SPI1>;
+       #address-cells = <1>;
+       #size-cells = <0>;
+       cs-gpios = <&gpio 18>, <&gpio 17>, <&gpio 16>;
+};
+
+spi2@7e2150c0 {
+       compatible = "brcm,bcm2835-aux-spi";
+       reg = <0x7e2150c0 0x40>;
+       interrupts = <1 29>;
+       clocks = <&aux_clocks BCM2835_AUX_CLOCK_SPI2>;
+       #address-cells = <1>;
+       #size-cells = <0>;
+       cs-gpios = <&gpio 43>, <&gpio 44>, <&gpio 45>;
+};
index 8f771441be60556ace93f2b29d87df856882c344..705075da2f10156e92a60828177c8483ee16eeec 100644 (file)
@@ -51,7 +51,7 @@ Optional properties, deprecated for soctype-specific bindings:
 - renesas,tx-fifo-size : Overrides the default tx fifo size given in words
                         (default is 64)
 - renesas,rx-fifo-size : Overrides the default rx fifo size given in words
-                        (default is 64, or 256 on R-Car Gen2)
+                        (default is 64)
 
 Pinctrl properties might be needed, too.  See
 Documentation/devicetree/bindings/pinctrl/renesas,*.
index dcefc438272f0a4124657c051749929c6e944f1f..ce363c923f446b66dcfffc51274da4623630f15d 100644 (file)
@@ -15,21 +15,25 @@ Required properties:
 - interrupts: Should contain spi interrupt
 
 - clocks: phandles to input clocks.
-  The first should be <&topckgen CLK_TOP_SPI_SEL>.
-  The second should be one of the following.
+  The first should be one of the following. It's PLL.
    -  <&clk26m>: specify parent clock 26MHZ.
    -  <&topckgen CLK_TOP_SYSPLL3_D2>: specify parent clock 109MHZ.
                                      It's the default one.
    -  <&topckgen CLK_TOP_SYSPLL4_D2>: specify parent clock 78MHZ.
    -  <&topckgen CLK_TOP_UNIVPLL2_D4>: specify parent clock 104MHZ.
    -  <&topckgen CLK_TOP_UNIVPLL1_D8>: specify parent clock 78MHZ.
+  The second should be <&topckgen CLK_TOP_SPI_SEL>. It's clock mux.
+  The third is <&pericfg CLK_PERI_SPI0>. It's clock gate.
 
-- clock-names: shall be "spi-clk" for the controller clock, and
-  "parent-clk" for the parent clock.
+- clock-names: shall be "parent-clk" for the parent clock, "sel-clk" for the
+  muxes clock, and "spi-clk" for the clock gate.
 
 Optional properties:
+-cs-gpios: see spi-bus.txt, only required for MT8173.
+
 - mediatek,pad-select: specify which pins group(ck/mi/mo/cs) spi
-  controller used, this value should be 0~3, only required for MT8173.
+  controller used. This is a array, the element value should be 0~3,
+  only required for MT8173.
     0: specify GPIO69,70,71,72 for spi pins.
     1: specify GPIO102,103,104,105 for spi pins.
     2: specify GPIO128,129,130,131 for spi pins.
@@ -44,8 +48,11 @@ spi: spi@1100a000 {
        #size-cells = <0>;
        reg = <0 0x1100a000 0 0x1000>;
        interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_LOW>;
-       clocks = <&topckgen CLK_TOP_SPI_SEL>, <&topckgen CLK_TOP_SYSPLL3_D2>;
-       clock-names = "spi-clk", "parent-clk";
-       mediatek,pad-select = <0>;
+       clocks = <&topckgen CLK_TOP_SYSPLL3_D2>,
+                <&topckgen CLK_TOP_SPI_SEL>,
+                <&pericfg CLK_PERI_SPI0>;
+       clock-names = "parent-clk", "sel-clk", "spi-clk";
+       cs-gpios = <&pio 105 GPIO_ACTIVE_LOW>, <&pio 72 GPIO_ACTIVE_LOW>;
+       mediatek,pad-select = <1>, <0>;
        status = "disabled";
 };
index 8a49362dea6e81c377d8762e401696c97555cd74..41b817f7b6706515025b9a6e4af05304a62d5c25 100644 (file)
@@ -55,19 +55,11 @@ of heat dissipation). For example a fan's cooling states correspond to
 the different fan speeds possible. Cooling states are referred to by
 single unsigned integers, where larger numbers mean greater heat
 dissipation. The precise set of cooling states associated with a device
-(as referred to be the cooling-min-state and cooling-max-state
+(as referred to by the cooling-min-level and cooling-max-level
 properties) should be defined in a particular device's binding.
 For more examples of cooling devices, refer to the example sections below.
 
 Required properties:
-- cooling-min-state:   An integer indicating the smallest
-  Type: unsigned       cooling state accepted. Typically 0.
-  Size: one cell
-
-- cooling-max-state:   An integer indicating the largest
-  Type: unsigned       cooling state accepted.
-  Size: one cell
-
 - #cooling-cells:      Used to provide cooling device specific information
   Type: unsigned       while referring to it. Must be at least 2, in order
   Size: one cell       to specify minimum and maximum cooling state used
@@ -77,6 +69,15 @@ Required properties:
                        See Cooling device maps section below for more details
                        on how consumers refer to cooling devices.
 
+Optional properties:
+- cooling-min-level:   An integer indicating the smallest
+  Type: unsigned       cooling state accepted. Typically 0.
+  Size: one cell
+
+- cooling-max-level:   An integer indicating the largest
+  Type: unsigned       cooling state accepted.
+  Size: one cell
+
 * Trip points
 
 The trip node is a node to describe a point in the temperature domain
@@ -225,8 +226,8 @@ cpus {
                        396000  950000
                        198000  850000
                >;
-               cooling-min-state = <0>;
-               cooling-max-state = <3>;
+               cooling-min-level = <0>;
+               cooling-max-level = <3>;
                #cooling-cells = <2>; /* min followed by max */
        };
        ...
@@ -240,8 +241,8 @@ cpus {
         */
        fan0: fan@0x48 {
                ...
-               cooling-min-state = <0>;
-               cooling-max-state = <9>;
+               cooling-min-level = <0>;
+               cooling-max-level = <9>;
                #cooling-cells = <2>; /* min followed by max */
        };
 };
index d71ef07bca5d1a3505ecab53f0b84bc8e5d12fc1..a057b75ba4b5f2d39b51f55c85b814b95f165820 100644 (file)
@@ -6,6 +6,7 @@ Required properties:
        "lsi,zevio-usb"
        "qcom,ci-hdrc"
        "chipidea,usb2"
+       "xlnx,zynq-usb-2.20a"
 - reg: base address and length of the registers
 - interrupts: interrupt for the USB controller
 
index 64a4ca6cf96ff5bd9df7c3b1c99abd7d086a701c..7d48f63db44ec9b9c0aa68ea0a54a70fc1a7014e 100644 (file)
@@ -5,6 +5,7 @@ Required properties:
        - "renesas,usbhs-r8a7790"
        - "renesas,usbhs-r8a7791"
        - "renesas,usbhs-r8a7794"
+       - "renesas,usbhs-r8a7795"
   - reg: Base address and length of the register for the USBHS
   - interrupts: Interrupt specifier for the USBHS
   - clocks: A list of phandle + clock specifier pairs
index ac5f0c34ae00a712b0d78ed4cc92fa88dd5491a6..82d2ac97af74b2a8e5569576cf92f15f1236c036 100644 (file)
@@ -203,6 +203,7 @@ sitronix    Sitronix Technology Corporation
 skyworks       Skyworks Solutions, Inc.
 smsc   Standard Microsystems Corporation
 snps   Synopsys, Inc.
+socionext      Socionext Inc.
 solidrun       SolidRun
 solomon        Solomon Systech Limited
 sony   Sony Corporation
index b80606de545ad809fb147688060b26b51af4d5e1..f59c43b6411b7d1b51b48c9acc1dd4b5f2338337 100644 (file)
@@ -21,8 +21,8 @@ exact way to do it depends on the GPIO controller providing the GPIOs, see the
 device tree bindings for your controller.
 
 GPIOs mappings are defined in the consumer device's node, in a property named
-<function>-gpios, where <function> is the function the driver will request
-through gpiod_get(). For example:
+either <function>-gpios or <function>-gpio, where <function> is the function
+the driver will request through gpiod_get(). For example:
 
        foo_device {
                compatible = "acme,foo";
@@ -31,7 +31,7 @@ through gpiod_get(). For example:
                            <&gpio 16 GPIO_ACTIVE_HIGH>, /* green */
                            <&gpio 17 GPIO_ACTIVE_HIGH>; /* blue */
 
-               power-gpios = <&gpio 1 GPIO_ACTIVE_LOW>;
+               power-gpio = <&gpio 1 GPIO_ACTIVE_LOW>;
        };
 
 This property will make GPIOs 15, 16 and 17 available to the driver under the
@@ -39,15 +39,24 @@ This property will make GPIOs 15, 16 and 17 available to the driver under the
 
        struct gpio_desc *red, *green, *blue, *power;
 
-       red = gpiod_get_index(dev, "led", 0);
-       green = gpiod_get_index(dev, "led", 1);
-       blue = gpiod_get_index(dev, "led", 2);
+       red = gpiod_get_index(dev, "led", 0, GPIOD_OUT_HIGH);
+       green = gpiod_get_index(dev, "led", 1, GPIOD_OUT_HIGH);
+       blue = gpiod_get_index(dev, "led", 2, GPIOD_OUT_HIGH);
 
-       power = gpiod_get(dev, "power");
+       power = gpiod_get(dev, "power", GPIOD_OUT_HIGH);
 
 The led GPIOs will be active-high, while the power GPIO will be active-low (i.e.
 gpiod_is_active_low(power) will be true).
 
+The second parameter of the gpiod_get() functions, the con_id string, has to be
+the <function>-prefix of the GPIO suffixes ("gpios" or "gpio", automatically
+looked up by the gpiod functions internally) used in the device tree. With above
+"led-gpios" example, use the prefix without the "-" as con_id parameter: "led".
+
+Internally, the GPIO subsystem prefixes the GPIO suffix ("gpios" or "gpio")
+with the string passed in con_id to get the resulting string
+(snprintf(... "%s-%s", con_id, gpio_suffixes[]).
+
 ACPI
 ----
 ACPI also supports function names for GPIOs in a similar fashion to DT.
@@ -142,13 +151,14 @@ The driver controlling "foo.0" will then be able to obtain its GPIOs as follows:
 
        struct gpio_desc *red, *green, *blue, *power;
 
-       red = gpiod_get_index(dev, "led", 0);
-       green = gpiod_get_index(dev, "led", 1);
-       blue = gpiod_get_index(dev, "led", 2);
+       red = gpiod_get_index(dev, "led", 0, GPIOD_OUT_HIGH);
+       green = gpiod_get_index(dev, "led", 1, GPIOD_OUT_HIGH);
+       blue = gpiod_get_index(dev, "led", 2, GPIOD_OUT_HIGH);
 
-       power = gpiod_get(dev, "power");
-       gpiod_direction_output(power, 1);
+       power = gpiod_get(dev, "power", GPIOD_OUT_HIGH);
 
-Since the "power" GPIO is mapped as active-low, its actual signal will be 0
-after this code. Contrary to the legacy integer GPIO interface, the active-low
-property is handled during mapping and is thus transparent to GPIO consumers.
+Since the "led" GPIOs are mapped as active-high, this example will switch their
+signals to 1, i.e. enabling the LEDs. And for the "power" GPIO, which is mapped
+as active-low, its actual signal will be 0 after this code. Contrary to the legacy
+integer GPIO interface, the active-low property is handled during mapping and is
+thus transparent to GPIO consumers.
index a206639454ab7acdbf797c2598d818d2dc372544..e000502fde2006aa958a01e5c4fd357c5a6a21f9 100644 (file)
@@ -39,6 +39,9 @@ device that displays digits), an additional index argument can be specified:
                                          const char *con_id, unsigned int idx,
                                          enum gpiod_flags flags)
 
+For a more detailed description of the con_id parameter in the DeviceTree case
+see Documentation/gpio/board.txt
+
 The flags parameter is used to optionally specify a direction and initial value
 for the GPIO. Values can be:
 
index f0dd3d2fec96da61b56d010c19a83755d320f52f..76add4c9cd6893f4aa6aeaae427bf6becec6b4a3 100644 (file)
@@ -32,6 +32,10 @@ Supported chips:
     Prefix: 'nct6792'
     Addresses scanned: ISA address retrieved from Super I/O registers
     Datasheet: Available from Nuvoton upon request
+  * Nuvoton NCT6793D
+    Prefix: 'nct6793'
+    Addresses scanned: ISA address retrieved from Super I/O registers
+    Datasheet: Available from Nuvoton upon request
 
 Authors:
         Guenter Roeck <linux@roeck-us.net>
index b85d000faeb4067c9ab1ed06690105d459a40a4e..c51f1146f3bd8396f572cddb9c87ae2620d236ba 100644 (file)
@@ -361,7 +361,7 @@ For win8 devices with both T and C coordinates, the position mapping is
    ABS_MT_POSITION_X := T_X
    ABS_MT_POSITION_Y := T_Y
    ABS_MT_TOOL_X := C_X
-   ABS_MT_TOOL_X := C_Y
+   ABS_MT_TOOL_Y := C_Y
 
 Unfortunately, there is not enough information to specify both the touching
 ellipse and the tool ellipse, so one has to resort to approximations.  One
diff --git a/Documentation/networking/vrf.txt b/Documentation/networking/vrf.txt
new file mode 100644 (file)
index 0000000..031ef4a
--- /dev/null
@@ -0,0 +1,96 @@
+Virtual Routing and Forwarding (VRF)
+====================================
+The VRF device combined with ip rules provides the ability to create virtual
+routing and forwarding domains (aka VRFs, VRF-lite to be specific) in the
+Linux network stack. One use case is the multi-tenancy problem where each
+tenant has their own unique routing tables and in the very least need
+different default gateways.
+
+Processes can be "VRF aware" by binding a socket to the VRF device. Packets
+through the socket then use the routing table associated with the VRF
+device. An important feature of the VRF device implementation is that it
+impacts only Layer 3 and above so L2 tools (e.g., LLDP) are not affected
+(ie., they do not need to be run in each VRF). The design also allows
+the use of higher priority ip rules (Policy Based Routing, PBR) to take
+precedence over the VRF device rules directing specific traffic as desired.
+
+In addition, VRF devices allow VRFs to be nested within namespaces. For
+example network namespaces provide separation of network interfaces at L1
+(Layer 1 separation), VLANs on the interfaces within a namespace provide
+L2 separation and then VRF devices provide L3 separation.
+
+Design
+------
+A VRF device is created with an associated route table. Network interfaces
+are then enslaved to a VRF device:
+
+         +-----------------------------+
+         |           vrf-blue          |  ===> route table 10
+         +-----------------------------+
+            |        |            |
+         +------+ +------+     +-------------+
+         | eth1 | | eth2 | ... |    bond1    |
+         +------+ +------+     +-------------+
+                                  |       |
+                              +------+ +------+
+                              | eth8 | | eth9 |
+                              +------+ +------+
+
+Packets received on an enslaved device and are switched to the VRF device
+using an rx_handler which gives the impression that packets flow through
+the VRF device. Similarly on egress routing rules are used to send packets
+to the VRF device driver before getting sent out the actual interface. This
+allows tcpdump on a VRF device to capture all packets into and out of the
+VRF as a whole.[1] Similiarly, netfilter [2] and tc rules can be applied
+using the VRF device to specify rules that apply to the VRF domain as a whole.
+
+[1] Packets in the forwarded state do not flow through the device, so those
+    packets are not seen by tcpdump. Will revisit this limitation in a
+    future release.
+
+[2] Iptables on ingress is limited to NF_INET_PRE_ROUTING only with skb->dev
+    set to real ingress device and egress is limited to NF_INET_POST_ROUTING.
+    Will revisit this limitation in a future release.
+
+
+Setup
+-----
+1. VRF device is created with an association to a FIB table.
+   e.g, ip link add vrf-blue type vrf table 10
+        ip link set dev vrf-blue up
+
+2. Rules are added that send lookups to the associated FIB table when the
+   iif or oif is the VRF device. e.g.,
+       ip ru add oif vrf-blue table 10
+       ip ru add iif vrf-blue table 10
+
+   Set the default route for the table (and hence default route for the VRF).
+   e.g, ip route add table 10 prohibit default
+
+3. Enslave L3 interfaces to a VRF device.
+   e.g,  ip link set dev eth1 master vrf-blue
+
+   Local and connected routes for enslaved devices are automatically moved to
+   the table associated with VRF device. Any additional routes depending on
+   the enslaved device will need to be reinserted following the enslavement.
+
+4. Additional VRF routes are added to associated table.
+   e.g., ip route add table 10 ...
+
+
+Applications
+------------
+Applications that are to work within a VRF need to bind their socket to the
+VRF device:
+
+    setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, dev, strlen(dev)+1);
+
+or to specify the output device using cmsg and IP_PKTINFO.
+
+
+Limitations
+-----------
+VRF device currently only works for IPv4. Support for IPv6 is under development.
+
+Index of original ingress interface is not available via cmsg. Will address
+soon.
index 62328d76b55bd9cfc59294666b49a70e0ddca5da..b0e911e0e8f50ad749686961e494377a1a49db45 100644 (file)
@@ -979,20 +979,45 @@ every time right after the runtime_resume() callback has returned
 (alternatively, the runtime_suspend() callback will have to check if the
 device should really be suspended and return -EAGAIN if that is not the case).
 
-The runtime PM of PCI devices is disabled by default.  It is also blocked by
-pci_pm_init() that runs the pm_runtime_forbid() helper function.  If a PCI
-driver implements the runtime PM callbacks and intends to use the runtime PM
-framework provided by the PM core and the PCI subsystem, it should enable this
-feature by executing the pm_runtime_enable() helper function.  However, the
-driver should not call the pm_runtime_allow() helper function unblocking
-the runtime PM of the device.  Instead, it should allow user space or some
-platform-specific code to do that (user space can do it via sysfs), although
-once it has called pm_runtime_enable(), it must be prepared to handle the
+The runtime PM of PCI devices is enabled by default by the PCI core.  PCI
+device drivers do not need to enable it and should not attempt to do so.
+However, it is blocked by pci_pm_init() that runs the pm_runtime_forbid()
+helper function.  In addition to that, the runtime PM usage counter of
+each PCI device is incremented by local_pci_probe() before executing the
+probe callback provided by the device's driver.
+
+If a PCI driver implements the runtime PM callbacks and intends to use the
+runtime PM framework provided by the PM core and the PCI subsystem, it needs
+to decrement the device's runtime PM usage counter in its probe callback
+function.  If it doesn't do that, the counter will always be different from
+zero for the device and it will never be runtime-suspended.  The simplest
+way to do that is by calling pm_runtime_put_noidle(), but if the driver
+wants to schedule an autosuspend right away, for example, it may call
+pm_runtime_put_autosuspend() instead for this purpose.  Generally, it
+just needs to call a function that decrements the devices usage counter
+from its probe routine to make runtime PM work for the device.
+
+It is important to remember that the driver's runtime_suspend() callback
+may be executed right after the usage counter has been decremented, because
+user space may already have cuased the pm_runtime_allow() helper function
+unblocking the runtime PM of the device to run via sysfs, so the driver must
+be prepared to cope with that.
+
+The driver itself should not call pm_runtime_allow(), though.  Instead, it
+should let user space or some platform-specific code do that (user space can
+do it via sysfs as stated above), but it must be prepared to handle the
 runtime PM of the device correctly as soon as pm_runtime_allow() is called
-(which may happen at any time).  [It also is possible that user space causes
-pm_runtime_allow() to be called via sysfs before the driver is loaded, so in
-fact the driver has to be prepared to handle the runtime PM of the device as
-soon as it calls pm_runtime_enable().]
+(which may happen at any time, even before the driver is loaded).
+
+When the driver's remove callback runs, it has to balance the decrementation
+of the device's runtime PM usage counter at the probe time.  For this reason,
+if it has decremented the counter in its probe callback, it must run
+pm_runtime_get_noresume() in its remove callback.  [Since the core carries
+out a runtime resume of the device and bumps up the device's usage counter
+before running the driver's remove callback, the runtime PM of the device
+is effectively disabled for the duration of the remove execution and all
+runtime PM helper functions incrementing the device's usage counter are
+then effectively equivalent to pm_runtime_get_noresume().]
 
 The runtime PM framework works by processing requests to suspend or resume
 devices, or to check if they are idle (in which cases it is reasonable to
index 2bc8abc57fa04c1a4e47bb2d2b8626f8209b24a9..6c6247aaa7b93a0a038e5f65b30679486b410cc2 100644 (file)
@@ -18,6 +18,7 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 #define _GNU_SOURCE
+#define __SANE_USERSPACE_TYPES__        /* For PPC64, to get LL64 types */
 #include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
index f4cb0b2d5cd79048c51cf7b89f803561c2070e28..477927becacba69ee4bdea2203dd796979d14449 100644 (file)
@@ -15,8 +15,8 @@ The updated API replacements are:
 
 DEFINE_STATIC_KEY_TRUE(key);
 DEFINE_STATIC_KEY_FALSE(key);
-static_key_likely()
-statick_key_unlikely()
+static_branch_likely()
+static_branch_unlikely()
 
 0) Abstract
 
index 6294b5186ae552b8b2fcb78ac4b8617ee6f8fe38..809ab6efcc744ec3dcad28bb075d696e6613f836 100644 (file)
@@ -54,13 +54,15 @@ default_qdisc
 --------------
 
 The default queuing discipline to use for network devices. This allows
-overriding the default queue discipline of pfifo_fast with an
-alternative. Since the default queuing discipline is created with the
-no additional parameters so is best suited to queuing disciplines that
-work well without configuration like stochastic fair queue (sfq),
-CoDel (codel) or fair queue CoDel (fq_codel). Don't use queuing disciplines
-like Hierarchical Token Bucket or Deficit Round Robin which require setting
-up classes and bandwidths.
+overriding the default of pfifo_fast with an alternative. Since the default
+queuing discipline is created without additional parameters so is best suited
+to queuing disciplines that work well without configuration like stochastic
+fair queue (sfq), CoDel (codel) or fair queue CoDel (fq_codel). Don't use
+queuing disciplines like Hierarchical Token Bucket or Deficit Round Robin
+which require setting up classes and bandwidths. Note that physical multiqueue
+interfaces still use mq as root qdisc, which in turn uses this default for its
+leaves. Virtual devices (like e.g. lo or veth) ignore this setting and instead
+default to noqueue.
 Default: pfifo_fast
 
 busy_read
index c3797b529991f03ad0673cc5a249931a7a370f09..a1ce2235f121c29f3520e5504d06c22c60030f99 100644 (file)
@@ -4,7 +4,7 @@ Power allocator governor tunables
 Trip points
 -----------
 
-The governor requires the following two passive trip points:
+The governor works optimally with the following two passive trip points:
 
 1.  "switch on" trip point: temperature above which the governor
     control loop starts operating.  This is the first passive trip
index 7ba7ab749c853a7691dff808d85b2a8f80973fe6..747c65316167a70ec147d1254dc33afe7708c149 100644 (file)
@@ -615,9 +615,8 @@ F:  Documentation/hwmon/fam15h_power
 F:     drivers/hwmon/fam15h_power.c
 
 AMD GEODE CS5536 USB DEVICE CONTROLLER DRIVER
-M:     Thomas Dahlmann <dahlmann.thomas@arcor.de>
 L:     linux-geode@lists.infradead.org (moderated for non-subscribers)
-S:     Supported
+S:     Orphan
 F:     drivers/usb/gadget/udc/amd5536udc.*
 
 AMD GEODE PROCESSOR/CHIPSET SUPPORT
@@ -808,6 +807,13 @@ S: Maintained
 F:     drivers/video/fbdev/arcfb.c
 F:     drivers/video/fbdev/core/fb_defio.c
 
+ARCNET NETWORK LAYER
+M:     Michael Grzeschik <m.grzeschik@pengutronix.de>
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     drivers/net/arcnet/
+F:     include/uapi/linux/if_arcnet.h
+
 ARM MFM AND FLOPPY DRIVERS
 M:     Ian Molton <spyro@f2s.com>
 S:     Maintained
@@ -888,11 +894,12 @@ M:        Lennert Buytenhek <kernel@wantstofly.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 
-ARM/Allwinner A1X SoC support
+ARM/Allwinner sunXi SoC support
 M:     Maxime Ripard <maxime.ripard@free-electrons.com>
+M:     Chen-Yu Tsai <wens@csie.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
-N:     sun[x4567]i
+N:     sun[x456789]i
 
 ARM/Allwinner SoC Clock Support
 M:     Emilio López <emilio@elopez.com.ar>
@@ -3394,7 +3401,6 @@ F:        drivers/staging/dgnc/
 
 DIGI EPCA PCI PRODUCTS
 M:     Lidza Louina <lidza.louina@gmail.com>
-M:     Mark Hounschell <markh@compro.net>
 M:     Daeseok Youn <daeseok.youn@gmail.com>
 L:     driverdev-devel@linuxdriverproject.org
 S:     Maintained
@@ -3586,6 +3592,13 @@ F:       drivers/gpu/drm/i915/
 F:     include/drm/i915*
 F:     include/uapi/drm/i915*
 
+DRM DRIVERS FOR ATMEL HLCDC
+M:     Boris Brezillon <boris.brezillon@free-electrons.com>
+L:     dri-devel@lists.freedesktop.org
+S:     Supported
+F:     drivers/gpu/drm/atmel-hlcdc/
+F:     Documentation/devicetree/bindings/drm/atmel/
+
 DRM DRIVERS FOR EXYNOS
 M:     Inki Dae <inki.dae@samsung.com>
 M:     Joonyoung Shim <jy0922.shim@samsung.com>
@@ -3614,6 +3627,14 @@ S:       Maintained
 F:     drivers/gpu/drm/imx/
 F:     Documentation/devicetree/bindings/drm/imx/
 
+DRM DRIVERS FOR GMA500 (Poulsbo, Moorestown and derivative chipsets)
+M:     Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
+L:     dri-devel@lists.freedesktop.org
+T:     git git://github.com/patjak/drm-gma500
+S:     Maintained
+F:     drivers/gpu/drm/gma500
+F:     include/drm/gma500*
+
 DRM DRIVERS FOR NVIDIA TEGRA
 M:     Thierry Reding <thierry.reding@gmail.com>
 M:     Terje Bergström <tbergstrom@nvidia.com>
@@ -3998,7 +4019,7 @@ S:        Maintained
 F:     sound/usb/misc/ua101.c
 
 EXTENSIBLE FIRMWARE INTERFACE (EFI)
-M:     Matt Fleming <matt.fleming@intel.com>
+M:     Matt Fleming <matt@codeblueprint.co.uk>
 L:     linux-efi@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi.git
 S:     Maintained
@@ -4013,7 +4034,7 @@ F:        include/linux/efi*.h
 EFI VARIABLE FILESYSTEM
 M:     Matthew Garrett <matthew.garrett@nebula.com>
 M:     Jeremy Kerr <jk@ozlabs.org>
-M:     Matt Fleming <matt.fleming@intel.com>
+M:     Matt Fleming <matt@codeblueprint.co.uk>
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi.git
 L:     linux-efi@vger.kernel.org
 S:     Maintained
@@ -4407,6 +4428,14 @@ L:       linuxppc-dev@lists.ozlabs.org
 S:     Maintained
 F:     drivers/net/ethernet/freescale/ucc_geth*
 
+FREESCALE eTSEC ETHERNET DRIVER (GIANFAR)
+M:     Claudiu Manoil <claudiu.manoil@freescale.com>
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     drivers/net/ethernet/freescale/gianfar*
+X:     drivers/net/ethernet/freescale/gianfar_ptp.c
+F:     Documentation/devicetree/bindings/net/fsl-tsec-phy.txt
+
 FREESCALE QUICC ENGINE UCC UART DRIVER
 M:     Timur Tabi <timur@tabi.org>
 L:     linuxppc-dev@lists.ozlabs.org
@@ -5952,7 +5981,7 @@ F:        virt/kvm/
 KERNEL VIRTUAL MACHINE (KVM) FOR AMD-V
 M:     Joerg Roedel <joro@8bytes.org>
 L:     kvm@vger.kernel.org
-W:     http://kvm.qumranet.com
+W:     http://www.linux-kvm.org/
 S:     Maintained
 F:     arch/x86/include/asm/svm.h
 F:     arch/x86/kvm/svm.c
@@ -5960,7 +5989,7 @@ F:        arch/x86/kvm/svm.c
 KERNEL VIRTUAL MACHINE (KVM) FOR POWERPC
 M:     Alexander Graf <agraf@suse.com>
 L:     kvm-ppc@vger.kernel.org
-W:     http://kvm.qumranet.com
+W:     http://www.linux-kvm.org/
 T:     git git://github.com/agraf/linux-2.6.git
 S:     Supported
 F:     arch/powerpc/include/asm/kvm*
@@ -6452,11 +6481,11 @@ F:      drivers/hwmon/ltc4261.c
 LTP (Linux Test Project)
 M:     Mike Frysinger <vapier@gentoo.org>
 M:     Cyril Hrubis <chrubis@suse.cz>
-M:     Wanlong Gao <gaowanlong@cn.fujitsu.com>
+M:     Wanlong Gao <wanlong.gao@gmail.com>
 M:     Jan Stancek <jstancek@redhat.com>
 M:     Stanislav Kholmanskikh <stanislav.kholmanskikh@oracle.com>
 M:     Alexey Kodanev <alexey.kodanev@oracle.com>
-L:     ltp-list@lists.sourceforge.net (subscribers-only)
+L:     ltp@lists.linux.it (subscribers-only)
 W:     http://linux-test-project.github.io/
 T:     git git://github.com/linux-test-project/ltp.git
 S:     Maintained
@@ -6773,7 +6802,6 @@ F:        drivers/scsi/megaraid/
 
 MELLANOX ETHERNET DRIVER (mlx4_en)
 M:     Amir Vadai <amirv@mellanox.com>
-M:     Ido Shamay <idos@mellanox.com>
 L:     netdev@vger.kernel.org
 S:     Supported
 W:     http://www.mellanox.com
@@ -8500,7 +8528,6 @@ F:        Documentation/networking/LICENSE.qla3xxx
 F:     drivers/net/ethernet/qlogic/qla3xxx.*
 
 QLOGIC QLCNIC (1/10)Gb ETHERNET DRIVER
-M:     Shahed Shaikh <shahed.shaikh@qlogic.com>
 M:     Dept-GELinuxNICDev@qlogic.com
 L:     netdev@vger.kernel.org
 S:     Supported
@@ -9097,6 +9124,15 @@ S: Supported
 F: Documentation/devicetree/bindings/net/snps,dwc-qos-ethernet.txt
 F: drivers/net/ethernet/synopsys/dwc_eth_qos.c
 
+SYNOPSYS DESIGNWARE I2C DRIVER
+M:     Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+M:     Jarkko Nikula <jarkko.nikula@linux.intel.com>
+M:     Mika Westerberg <mika.westerberg@linux.intel.com>
+L:     linux-i2c@vger.kernel.org
+S:     Maintained
+F:     drivers/i2c/busses/i2c-designware-*
+F:     include/linux/platform_data/i2c-designware.h
+
 SYNOPSYS DESIGNWARE MMC/SD/SDIO DRIVER
 M:     Seungwon Jeon <tgih.jun@samsung.com>
 M:     Jaehoon Chung <jh80.chung@samsung.com>
@@ -9904,13 +9940,12 @@ F:      drivers/staging/media/lirc/
 STAGING - LUSTRE PARALLEL FILESYSTEM
 M:     Oleg Drokin <oleg.drokin@intel.com>
 M:     Andreas Dilger <andreas.dilger@intel.com>
-L:     HPDD-discuss@lists.01.org (moderated for non-subscribers)
-W:     http://lustre.opensfs.org/
+L:     lustre-devel@lists.lustre.org (moderated for non-subscribers)
+W:     http://wiki.lustre.org/
 S:     Maintained
 F:     drivers/staging/lustre
 
 STAGING - NVIDIA COMPLIANT EMBEDDED CONTROLLER INTERFACE (nvec)
-M:     Julian Andres Klode <jak@jak-linux.org>
 M:     Marc Dietrich <marvin24@gmx.de>
 L:     ac100@lists.launchpad.net (moderated for non-subscribers)
 L:     linux-tegra@vger.kernel.org
@@ -10338,6 +10373,16 @@ F:     include/uapi/linux/thermal.h
 F:     include/linux/cpu_cooling.h
 F:     Documentation/devicetree/bindings/thermal/
 
+THERMAL/CPU_COOLING
+M:     Amit Daniel Kachhap <amit.kachhap@gmail.com>
+M:     Viresh Kumar <viresh.kumar@linaro.org>
+M:     Javi Merino <javi.merino@arm.com>
+L:     linux-pm@vger.kernel.org
+S:     Supported
+F:     Documentation/thermal/cpu-cooling-api.txt
+F:     drivers/thermal/cpu_cooling.c
+F:     include/linux/cpu_cooling.h
+
 THINGM BLINK(1) USB RGB LED DRIVER
 M:     Vivien Didelot <vivien.didelot@savoirfairelinux.com>
 S:     Maintained
@@ -11187,7 +11232,7 @@ F:      drivers/vlynq/vlynq.c
 F:     include/linux/vlynq.h
 
 VME SUBSYSTEM
-M:     Martyn Welch <martyn.welch@ge.com>
+M:     Martyn Welch <martyn@welchs.me.uk>
 M:     Manohar Vanga <manohar.vanga@gmail.com>
 M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 L:     devel@driverdev.osuosl.org
@@ -11239,7 +11284,6 @@ VOLTAGE AND CURRENT REGULATOR FRAMEWORK
 M:     Liam Girdwood <lgirdwood@gmail.com>
 M:     Mark Brown <broonie@kernel.org>
 L:     linux-kernel@vger.kernel.org
-W:     http://opensource.wolfsonmicro.com/node/15
 W:     http://www.slimlogic.co.uk/?p=48
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git
 S:     Supported
@@ -11253,6 +11297,7 @@ L:      netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/vrf.c
 F:     include/net/vrf.h
+F:     Documentation/networking/vrf.txt
 
 VT1211 HARDWARE MONITOR DRIVER
 M:     Juerg Haefliger <juergh@gmail.com>
@@ -11364,21 +11409,10 @@ W:    http://oops.ghostprotocols.net:81/blog
 S:     Maintained
 F:     drivers/net/wireless/wl3501*
 
-WM97XX TOUCHSCREEN DRIVERS
-M:     Mark Brown <broonie@kernel.org>
-M:     Liam Girdwood <lrg@slimlogic.co.uk>
-L:     linux-input@vger.kernel.org
-T:     git git://opensource.wolfsonmicro.com/linux-2.6-touch
-W:     http://opensource.wolfsonmicro.com/node/7
-S:     Supported
-F:     drivers/input/touchscreen/*wm97*
-F:     include/linux/wm97xx.h
-
 WOLFSON MICROELECTRONICS DRIVERS
 L:     patches@opensource.wolfsonmicro.com
-T:     git git://opensource.wolfsonmicro.com/linux-2.6-asoc
-T:     git git://opensource.wolfsonmicro.com/linux-2.6-audioplus
-W:     http://opensource.wolfsonmicro.com/content/linux-drivers-wolfson-devices
+T:     git https://github.com/CirrusLogic/linux-drivers.git
+W:     https://github.com/CirrusLogic/linux-drivers/wiki
 S:     Supported
 F:     Documentation/hwmon/wm83??
 F:     arch/arm/mach-s3c64xx/mach-crag6410*
@@ -11649,6 +11683,7 @@ F:      drivers/tty/serial/zs.*
 ZSMALLOC COMPRESSED SLAB MEMORY ALLOCATOR
 M:     Minchan Kim <minchan@kernel.org>
 M:     Nitin Gupta <ngupta@vflare.org>
+R:     Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com>
 L:     linux-mm@kvack.org
 S:     Maintained
 F:     mm/zsmalloc.c
index 1a132ea43ca52588909bb054624177c8f8f63095..d5b37391195f80866ad2b831a417039b3ee230cf 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
 VERSION = 4
 PATCHLEVEL = 3
 SUBLEVEL = 0
-EXTRAVERSION = -rc1
-NAME = Hurr durr I'ma sheep
+EXTRAVERSION =
+NAME = Blurry Fish Butt
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
index f05bdb4b1cb97ee8f0d3bbec58fbc7285522c852..ff4049155c840c2fc4bc9e8015b5282dadb57469 100644 (file)
@@ -297,7 +297,9 @@ static inline void __iomem * ioremap_nocache(unsigned long offset,
                                             unsigned long size)
 {
        return ioremap(offset, size);
-} 
+}
+
+#define ioremap_uc ioremap_nocache
 
 static inline void iounmap(volatile void __iomem *addr)
 {
index 6b340d0f1521c3ad9c4edf984abe60982ae24c04..902e6ab00a066fead53614ed86cb88980aea2fba 100644 (file)
@@ -52,4 +52,6 @@ static inline unsigned long find_zero(unsigned long bits)
 #endif
 }
 
+#define zero_bytemask(mask) ((2ul << (find_zero(mask) * 8)) - 1)
+
 #endif /* _ASM_WORD_AT_A_TIME_H */
index 2804648c8ff4008d15761145b92167e721212935..2d6efcff3bf35cf1c11ebf180d2912d4033059b7 100644 (file)
@@ -117,6 +117,6 @@ handle_irq(int irq)
        }
 
        irq_enter();
-       generic_handle_irq_desc(irq, desc);
+       generic_handle_irq_desc(desc);
        irq_exit();
 }
index cded02c890aacb5b32813332b61df3b4523fbd05..5f387ee5b5c5e0a69fb4817e9437cef5cf0c7cdd 100644 (file)
@@ -242,7 +242,12 @@ pci_restore_srm_config(void)
 
 void pcibios_fixup_bus(struct pci_bus *bus)
 {
-       struct pci_dev *dev;
+       struct pci_dev *dev = bus->self;
+
+       if (pci_has_flag(PCI_PROBE_ONLY) && dev &&
+           (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
+               pci_read_bridge_bases(bus);
+       }
 
        list_for_each_entry(dev, &bus->devices, bus_list) {
                pdev_save_srm_config(dev);
index 69d52aa37bae2c27ddf568b10b28e43d14af4084..f2d81ff38aa6474f6443412889443cfb4904b3e0 100644 (file)
@@ -30,6 +30,7 @@ __delay(int loops)
                "       bgt %0,1b"
                : "=&r" (tmp), "=r" (loops) : "1"(loops));
 }
+EXPORT_SYMBOL(__delay);
 
 #ifdef CONFIG_SMP
 #define LPJ     cpu_data[smp_processor_id()].loops_per_jiffy
index 7611b10a2d238c7b4bb73696b59e2fe8b14ceb2c..0b10ef2a43726e0188b61de96bd5a5bf1ba50067 100644 (file)
@@ -48,4 +48,5 @@ generic-y += types.h
 generic-y += ucontext.h
 generic-y += user.h
 generic-y += vga.h
+generic-y += word-at-a-time.h
 generic-y += xor.h
index d9e44b62df05d81a31305048aa91290784980e9d..4ffd1855f1bdc586c5f258f376a109ea11646a30 100644 (file)
@@ -252,7 +252,7 @@ static struct irq_chip idu_irq_chip = {
 
 static int idu_first_irq;
 
-static void idu_cascade_isr(unsigned int __core_irq, struct irq_desc *desc)
+static void idu_cascade_isr(struct irq_desc *desc)
 {
        struct irq_domain *domain = irq_desc_get_handler_data(desc);
        unsigned int core_irq = irq_desc_get_irq(desc);
index 72ad724c67ae94cd6682ec15f3834966dd7028c0..639411f73ca9571f2e0d8b1c4531429e87d11eb1 100644 (file)
@@ -645,6 +645,7 @@ config ARCH_SHMOBILE_LEGACY
 
 config ARCH_RPC
        bool "RiscPC"
+       depends on MMU
        select ARCH_ACORN
        select ARCH_MAY_HAVE_PC_FDC
        select ARCH_SPARSEMEM_ENABLE
index 7451b447cc2d2cb8cc68a9bf59f125f2dd2ce347..2c2b28ee48119771dfa92f353124795d456d770a 100644 (file)
@@ -54,6 +54,14 @@ AS           += -EL
 LD             += -EL
 endif
 
+#
+# The Scalar Replacement of Aggregates (SRA) optimization pass in GCC 4.9 and
+# later may result in code being generated that handles signed short and signed
+# char struct members incorrectly. So disable it.
+# (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65932)
+#
+KBUILD_CFLAGS  += $(call cc-option,-fno-ipa-sra)
+
 # This selects which instruction set is used.
 # Note that GCC does not numerically define an architecture version
 # macro, but instead defines a whole series of macros which makes
index 233159d2eaab3eac34d47c4d4a9308b0d1bdec60..bb8fa023d5741dff9b4f9033ed2cf6f6d7b69f2d 100644 (file)
@@ -578,7 +578,7 @@ dtb-$(CONFIG_MACH_SUN4I) += \
        sun4i-a10-hackberry.dtb \
        sun4i-a10-hyundai-a7hd.dtb \
        sun4i-a10-inet97fv2.dtb \
-       sun4i-a10-itead-iteaduino-plus.dts \
+       sun4i-a10-itead-iteaduino-plus.dtb \
        sun4i-a10-jesurun-q5.dtb \
        sun4i-a10-marsboard.dtb \
        sun4i-a10-mini-xplus.dtb \
index 4d28fc3aac69f746f05f24590f2d6aa1eef7ddc9..5dd084f3c81c4a3dc1b927021f83bedd01f95c03 100644 (file)
                };
 
                vdd1_reg: regulator@2 {
-                       /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
+                       /* VDD_MPU voltage limits 0.95V - 1.325V with +/-4% tolerance */
                        regulator-name = "vdd_mpu";
                        regulator-min-microvolt = <912500>;
-                       regulator-max-microvolt = <1312500>;
+                       regulator-max-microvolt = <1378000>;
                        regulator-boot-on;
                        regulator-always-on;
                };
index 3a05b94f59edf62112955ed338ce9d66fb620941..d55e3ea89fda51ba1d6b45f69eeaa8849dad9487 100644 (file)
                pinctrl-0 = <&extcon_usb1_pins>;
        };
 
-       extcon_usb2: extcon_usb2 {
-               compatible = "linux,extcon-usb-gpio";
-               id-gpio = <&gpio7 24 GPIO_ACTIVE_HIGH>;
-               pinctrl-names = "default";
-               pinctrl-0 = <&extcon_usb2_pins>;
-       };
-
        hdmi0: connector {
                compatible = "hdmi-connector";
                label = "hdmi";
                >;
        };
 
-       extcon_usb2_pins: extcon_usb2_pins {
-               pinctrl-single,pins = <
-                       0x3e8 (PIN_INPUT_PULLUP | MUX_MODE14) /* uart1_ctsn.gpio7_24 */
-               >;
-       };
-
        tpd12s015_pins: pinmux_tpd12s015_pins {
                pinctrl-single,pins = <
                        0x3b0 (PIN_OUTPUT | MUX_MODE14)         /* gpio7_10 CT_CP_HPD */
                                /* SMPS9 unused */
 
                                ldo1_reg: ldo1 {
-                                       /* VDD_SD  */
+                                       /* VDD_SD / VDDSHV8  */
                                        regulator-name = "ldo1";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <3300000>;
                                        regulator-boot-on;
+                                       regulator-always-on;
                                };
 
                                ldo2_reg: ldo2 {
                                };
 
                                ldo3_reg: ldo3 {
-                                       /* VDDA_1V8_PHY */
+                                       /* VDDA_1V8_PHYA */
                                        regulator-name = "ldo3";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <1800000>;
                                        regulator-boot-on;
                                };
 
+                               ldo4_reg: ldo4 {
+                                       /* VDDA_1V8_PHYB */
+                                       regulator-name = "ldo4";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <1800000>;
+                                       regulator-always-on;
+                                       regulator-boot-on;
+                               };
+
                                ldo9_reg: ldo9 {
                                        /* VDD_RTC */
                                        regulator-name = "ldo9";
                        gpio-controller;
                        #gpio-cells = <2>;
                };
+
+               extcon_usb2: tps659038_usb {
+                       compatible = "ti,palmas-usb-vid";
+                       ti,enable-vbus-detection;
+                       ti,enable-id-detection;
+                       id-gpios = <&gpio7 24 GPIO_ACTIVE_HIGH>;
+               };
+
        };
 
        tmp102: tmp102@48 {
        mcp_rtc: rtc@6f {
                compatible = "microchip,mcp7941x";
                reg = <0x6f>;
-               interrupts = <GIC_SPI 2 IRQ_TYPE_EDGE_RISING>;  /* IRQ_SYS_1N */
+               interrupts-extended = <&crossbar_mpu GIC_SPI 2 IRQ_TYPE_EDGE_RISING>,
+                                     <&dra7_pmx_core 0x424>;
 
                pinctrl-names = "default";
                pinctrl-0 = <&mcp79410_pins_default>;
        pinctrl-0 = <&mmc1_pins_default>;
 
        vmmc-supply = <&ldo1_reg>;
-       vmmc_aux-supply = <&vdd_3v3>;
        bus-width = <4>;
        cd-gpios = <&gpio6 27 0>; /* gpio 219 */
 };
 };
 
 &usb2 {
+       /*
+        * Stand alone usage is peripheral only.
+        * However, with some resistor modifications
+        * this port can be used via expansion connectors
+        * as "host" or "dual-role". If so, provide
+        * the necessary dr_mode override in the expansion
+        * board's DT.
+        */
        dr_mode = "peripheral";
 };
 
 
 &hdmi {
        status = "ok";
-       vdda-supply = <&ldo3_reg>;
+       vdda-supply = <&ldo4_reg>;
 
        pinctrl-names = "default";
        pinctrl-0 = <&hdmi_pins>;
index 89f5a95954ed9020c070491cae36cc7b2556eccf..4047621b137e6b107f875dc2f7c82292752bf448 100644 (file)
@@ -46,7 +46,7 @@
 
 / {
        model = "Marvell Armada 385 Access Point Development Board";
-       compatible = "marvell,a385-db-ap", "marvell,armada385", "marvell,armada38x";
+       compatible = "marvell,a385-db-ap", "marvell,armada385", "marvell,armada380";
 
        chosen {
                stdout-path = "serial1:115200n8";
index 63a48490e2f9653ff83f7f6202fd993d101b6ec9..d4dbd28d348c0b74ae4b23b5886b1dfb29dc3aa6 100644 (file)
                };
 
                usb_phy2: phy@a2f400 {
-                       compatible = "marvell,berlin2-usb-phy";
+                       compatible = "marvell,berlin2cd-usb-phy";
                        reg = <0xa2f400 0x128>;
                        #phy-cells = <0>;
                        resets = <&chip_rst 0x104 14>;
                };
 
                usb_phy0: phy@b74000 {
-                       compatible = "marvell,berlin2-usb-phy";
+                       compatible = "marvell,berlin2cd-usb-phy";
                        reg = <0xb74000 0x128>;
                        #phy-cells = <0>;
                        resets = <&chip_rst 0x104 12>;
                };
 
                usb_phy1: phy@b78000 {
-                       compatible = "marvell,berlin2-usb-phy";
+                       compatible = "marvell,berlin2cd-usb-phy";
                        reg = <0xb78000 0x128>;
                        #phy-cells = <0>;
                        resets = <&chip_rst 0x104 13>;
index 92bacd3c8fab9f2730cbf53290de11b8f55372c3..109fd4711647ab7e170d506e75592e7d47cc9bcc 100644 (file)
 
 &cpsw_emac0 {
        phy_id = <&davinci_mdio>, <0>;
-       phy-mode = "mii";
+       phy-mode = "rgmii";
 };
 
 &cpsw_emac1 {
        phy_id = <&davinci_mdio>, <1>;
-       phy-mode = "mii";
+       phy-mode = "rgmii";
 };
index 8c4bbc7573df812c0e8461224ccd0f01e742c5a2..79838dd8dee7d81dc924ec2c35ceb8fa70345126 100644 (file)
@@ -8,7 +8,7 @@
 #include "dm814x.dtsi"
 
 / {
-       model = "DM8148 EVM";
+       model = "HP t410 Smart Zero Client";
        compatible = "hp,t410", "ti,dm8148";
 
        memory {
 
 &cpsw_emac0 {
        phy_id = <&davinci_mdio>, <0>;
-       phy-mode = "mii";
+       phy-mode = "rgmii";
 };
 
 &cpsw_emac1 {
        phy_id = <&davinci_mdio>, <1>;
-       phy-mode = "mii";
+       phy-mode = "rgmii";
 };
index 972c9c9e885b0566e1c0b6b365f4be81780289a8..7988b42e57640584df8f8c459f6ff6652e325ed6 100644 (file)
                                ti,hwmods = "timer3";
                        };
 
-                       control: control@160000 {
+                       control: control@140000 {
                                compatible = "ti,dm814-scm", "simple-bus";
-                               reg = <0x160000 0x16d000>;
+                               reg = <0x140000 0x16d000>;
                                #address-cells = <1>;
                                #size-cells = <1>;
                                ranges = <0 0x160000 0x16d000>;
                                mac-address = [ 00 00 00 00 00 00 ];
                        };
 
-                       phy_sel: cpsw-phy-sel@0x48160650 {
+                       phy_sel: cpsw-phy-sel@48140650 {
                                compatible = "ti,am3352-cpsw-phy-sel";
-                               reg= <0x48160650 0x4>;
+                               reg= <0x48140650 0x4>;
                                reg-names = "gmii-sel";
                        };
                };
index 5d65db9ebc2bed8b06100ae1a696999d8785a763..e289c706d27d50d5597f57a10b7ecd2891523d30 100644 (file)
                                        reg = <0x0 0x1400>;
                                        #address-cells = <1>;
                                        #size-cells = <1>;
+                                       ranges = <0 0x0 0x1400>;
 
                                        pbias_regulator: pbias_regulator {
-                                               compatible = "ti,pbias-omap";
+                                               compatible = "ti,pbias-dra7", "ti,pbias-omap";
                                                reg = <0xe00 0x4>;
                                                syscon = <&scm_conf>;
                                                pbias_mmc_reg: pbias_mmc_omap5 {
                        ti,irqs-safe-map = <0>;
                };
 
-               mac: ethernet@4a100000 {
+               mac: ethernet@48484000 {
                        compatible = "ti,dra7-cpsw","ti,cpsw";
                        ti,hwmods = "gmac";
                        clocks = <&dpll_gmac_ck>, <&gmac_gmii_ref_clk_div>;
index 955c24ee4a8cbfea89248c2efcb93d9536c0221b..8c24975e8f9d66387b23d9eeb38ab96142609421 100644 (file)
 
                button@1 {
                        debounce_interval = <50>;
-                       wakeup = <1>;
+                       wakeup-source;
                        label = "DSW2-1";
                        linux,code = <KEY_1>;
                        gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>;
                };
                button@2 {
                        debounce_interval = <50>;
-                       wakeup = <1>;
+                       wakeup-source;
                        label = "DSW2-2";
                        linux,code = <KEY_2>;
                        gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>;
                };
                button@3 {
                        debounce_interval = <50>;
-                       wakeup = <1>;
+                       wakeup-source;
                        label = "DSW2-3";
                        linux,code = <KEY_3>;
                        gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>;
                };
                button@4 {
                        debounce_interval = <50>;
-                       wakeup = <1>;
+                       wakeup-source;
                        label = "DSW2-4";
                        linux,code = <KEY_4>;
                        gpios = <&gpio0 17 GPIO_ACTIVE_HIGH>;
index ca0e3c15977f13febd2ae550949ae704ecbf33cb..294cfe40388dd582d77d45eac441b15318ac1cde 100644 (file)
@@ -98,6 +98,7 @@
                        opp-hz = /bits/ 64 <800000000>;
                        opp-microvolt = <1000000>;
                        clock-latency-ns = <200000>;
+                       opp-suspend;
                };
                opp07 {
                        opp-hz = /bits/ 64 <900000000>;
index 15aea760c1dadee45c631d78c64366cea7739276..c625e71217aa94d74c640c113286a5292179b62a 100644 (file)
                                regulator-name = "P1.8V_LDO_OUT10";
                                regulator-min-microvolt = <1800000>;
                                regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
                        };
 
                        ldo11_reg: LDO11 {
index 8f4d76c5e11c5821ef7e504f21aa87c6103c92de..1b95da79293c58a173ce833d2e72e995a7761cb0 100644 (file)
        };
 };
 
+&pmu_system_controller {
+       assigned-clocks = <&pmu_system_controller 0>;
+       assigned-clock-parents = <&clock CLK_FIN_PLL>;
+};
+
 &rtc {
        status = "okay";
        clocks = <&clock CLK_RTC>, <&max77802 MAX77802_CLK_32K_AP>;
index df9aee92ecf4d71c714e763665013e7d2f6f4591..1b3d6c769a3cbb37f88fe55914707316abea023c 100644 (file)
                interrupt-parent = <&combiner>;
                interrupts = <3 0>;
                clock-names = "sysmmu", "master";
-               clocks = <&clock CLK_SMMU_FIMD1M0>, <&clock CLK_FIMD1>;
+               clocks = <&clock CLK_SMMU_FIMD1M1>, <&clock CLK_FIMD1>;
                power-domains = <&disp_pd>;
                #iommu-cells = <0>;
        };
index 79ffdfe712aa4a8ad193d4afd671962edfb73646..3b43e57845ae92bea4fc25b5c9af428c26ce2aa6 100644 (file)
         */
        pinctrl-0 = <&pwm0_out &pwm1_out &pwm2_out &pwm3_out>;
        pinctrl-names = "default";
-       samsung,pwm-outputs = <0>;
        status = "okay";
 };
 
index 7d5b386b5ae6aeb32aed5baf55a2d50ddf374b39..8f40c7e549bd5ef48d77c4ee5c9dacaaae65d820 100644 (file)
        };
 };
 
+&pmu_system_controller {
+       assigned-clocks = <&pmu_system_controller 0>;
+       assigned-clock-parents = <&clock CLK_FIN_PLL>;
+};
+
 &rtc {
        status = "okay";
        clocks = <&clock CLK_RTC>, <&max77802 MAX77802_CLK_32K_AP>;
index 66e47de5e826b0b33aaa6d066aa3c6c3104ff796..96d7eede412e1343d5e4e0a982044cec3ac347d3 100644 (file)
@@ -36,7 +36,7 @@
                pinctrl-0 = <&pinctrl_pmic>;
                reg = <0x08>;
                interrupt-parent = <&gpio5>;
-               interrupts = <23 0x8>;
+               interrupts = <23 IRQ_TYPE_LEVEL_HIGH>;
                regulators {
                        sw1_reg: sw1a {
                                regulator-name = "SW1";
index c3e3ca9362fbb78b6b2ecb8ec0125b83abdb7352..cd170376eaca6be3bc6416363250271590b75153 100644 (file)
@@ -15,6 +15,7 @@
 #include <dt-bindings/clock/imx5-clock.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/irq.h>
 
 / {
        aliases {
index 3373fd958e95c72b098ed14ea2a3228ba7903ea6..a503562438888fe936de6c8b9b255a06a4455d26 100644 (file)
@@ -35,7 +35,6 @@
                        compatible = "regulator-fixed";
                        reg = <1>;
                        pinctrl-names = "default";
-                       pinctrl-0 = <&pinctrl_usbh1>;
                        regulator-name = "usbh1_vbus";
                        regulator-min-microvolt = <5000000>;
                        regulator-max-microvolt = <5000000>;
@@ -47,7 +46,6 @@
                        compatible = "regulator-fixed";
                        reg = <2>;
                        pinctrl-names = "default";
-                       pinctrl-0 = <&pinctrl_usbotg>;
                        regulator-name = "usb_otg_vbus";
                        regulator-min-microvolt = <5000000>;
                        regulator-max-microvolt = <5000000>;
index b738ce0f9d9bc31f5369b1c97284cf1ec7ff9bb7..6e444bb873f92ee28dd5cebec93d5947f3b8ea15 100644 (file)
                                status = "disabled";
                        };
 
-                       uart2: serial@30870000 {
+                       uart2: serial@30890000 {
                                compatible = "fsl,imx7d-uart",
                                             "fsl,imx6q-uart";
-                               reg = <0x30870000 0x10000>;
+                               reg = <0x30890000 0x10000>;
                                interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX7D_UART2_ROOT_CLK>,
                                        <&clks IMX7D_UART2_ROOT_CLK>;
index 91146c318798ff3422f5fecb87ec0d8f0c97df45..5b0430041ec6d1980cb47ba253ce410bcebd05d0 100644 (file)
@@ -12,7 +12,7 @@
 
 / {
        model = "LogicPD Zoom DM3730 Torpedo Development Kit";
-       compatible = "logicpd,dm3730-torpedo-devkit", "ti,omap36xx";
+       compatible = "logicpd,dm3730-torpedo-devkit", "ti,omap3630", "ti,omap3";
 
        gpio_keys {
                compatible = "gpio-keys";
index 548441384d2a39488d7daffef79ed6c707576a86..8c77c87660cdf2d72e1df3f00d2c76a8e447293c 100644 (file)
@@ -67,7 +67,7 @@
 
        timer@c1109940 {
                compatible = "amlogic,meson6-timer";
-               reg = <0xc1109940 0x14>;
+               reg = <0xc1109940 0x18>;
                interrupts = <0 10 1>;
        };
 
                wdt: watchdog@c1109900 {
                        compatible = "amlogic,meson6-wdt";
                        reg = <0xc1109900 0x8>;
+                       interrupts = <0 0 1>;
                };
 
                uart_AO: serial@c81004c0 {
                        compatible = "amlogic,meson-uart";
-                       reg = <0xc81004c0 0x14>;
+                       reg = <0xc81004c0 0x18>;
                        interrupts = <0 90 1>;
                        clocks = <&clk81>;
                        status = "disabled";
                };
 
-               uart_A: serial@c81084c0 {
+               uart_A: serial@c11084c0 {
                        compatible = "amlogic,meson-uart";
-                       reg = <0xc81084c0 0x14>;
-                       interrupts = <0 90 1>;
+                       reg = <0xc11084c0 0x18>;
+                       interrupts = <0 26 1>;
                        clocks = <&clk81>;
                        status = "disabled";
                };
 
-               uart_B: serial@c81084dc {
+               uart_B: serial@c11084dc {
                        compatible = "amlogic,meson-uart";
-                       reg = <0xc81084dc 0x14>;
-                       interrupts = <0 90 1>;
+                       reg = <0xc11084dc 0x18>;
+                       interrupts = <0 75 1>;
                        clocks = <&clk81>;
                        status = "disabled";
                };
 
-               uart_C: serial@c8108700 {
+               uart_C: serial@c1108700 {
                        compatible = "amlogic,meson-uart";
-                       reg = <0xc8108700 0x14>;
-                       interrupts = <0 90 1>;
+                       reg = <0xc1108700 0x18>;
+                       interrupts = <0 93 1>;
                        clocks = <&clk81>;
                        status = "disabled";
                };
index 2390f387c27163bb76e918bb73e26966bee7fb48..798dda072b2a0fd5fd9a91064d049b8aa099c119 100644 (file)
@@ -56,6 +56,7 @@
                                        reg = <0x270 0x240>;
                                        #address-cells = <1>;
                                        #size-cells = <1>;
+                                       ranges = <0 0x270 0x240>;
 
                                        scm_clocks: clocks {
                                                #address-cells = <1>;
@@ -63,7 +64,7 @@
                                        };
 
                                        pbias_regulator: pbias_regulator {
-                                               compatible = "ti,pbias-omap";
+                                               compatible = "ti,pbias-omap2", "ti,pbias-omap";
                                                reg = <0x230 0x4>;
                                                syscon = <&scm_conf>;
                                                pbias_mmc_reg: pbias_mmc_omap2430 {
index a5474113cd50647f4b945b8db7ea3ff3a7643c83..67659a0ed13e12727e22c26703d29007e628bc99 100644 (file)
 
        tfp410_pins: pinmux_tfp410_pins {
                pinctrl-single,pins = <
-                       0x194 (PIN_OUTPUT | MUX_MODE4)  /* hdq_sio.gpio_170 */
+                       0x196 (PIN_OUTPUT | MUX_MODE4)  /* hdq_sio.gpio_170 */
                >;
        };
 
index 16e8ce350ddaae4f4bedc3d86f9d0418e4852f87..bb339d1648e071c4c456a3f627de68f805e1aa9b 100644 (file)
@@ -13,7 +13,7 @@
 
 / {
        model = "TI OMAP37XX EVM (TMDSEVM3730)";
-       compatible = "ti,omap3-evm-37xx", "ti,omap36xx";
+       compatible = "ti,omap3-evm-37xx", "ti,omap3630", "ti,omap3";
 
        memory {
                device_type = "memory";
index d5e5cd449b16757d269836609b16b35d34ecc039..2230e1c03320d1d4f4ce5c041f80126b3c9691f6 100644 (file)
                >;
        };
 
-       smsc9221_pins: pinmux_smsc9221_pins {
-               pinctrl-single,pins = <
-                       0x1a2 (PIN_INPUT | MUX_MODE4)           /* mcspi1_cs2.gpio_176 */
-               >;
-       };
-
        i2c1_pins: pinmux_i2c1_pins {
                pinctrl-single,pins = <
                        0x18a (PIN_INPUT | MUX_MODE0)   /* i2c1_scl.i2c1_scl */
index e458c2185e3c9cd8f775dc67996604bb913c6ae1..5ad688c57a0063faaabce22df06e3975fffbf931 100644 (file)
                        OMAP3_CORE1_IOPAD(0x217a, PIN_INPUT | MUX_MODE0)        /* uart2_rx.uart2_rx */
                >;
        };
+
+       smsc9221_pins: pinmux_smsc9221_pins {
+               pinctrl-single,pins = <
+                       OMAP3_CORE1_IOPAD(0x21d2, PIN_INPUT | MUX_MODE4)        /* mcspi1_cs2.gpio_176 */
+               >;
+       };
 };
 
 &omap3_pmx_core2 {
index 69a40cfc1f29dddbd515b4f821459442787d401a..8a2b25332b8c73092fb39ea962bd752dd166ae6a 100644 (file)
                                };
 
                                scm_conf: scm_conf@270 {
-                                       compatible = "syscon";
+                                       compatible = "syscon", "simple-bus";
                                        reg = <0x270 0x330>;
                                        #address-cells = <1>;
                                        #size-cells = <1>;
+                                       ranges = <0 0x270 0x330>;
+
+                                       pbias_regulator: pbias_regulator {
+                                               compatible = "ti,pbias-omap3", "ti,pbias-omap";
+                                               reg = <0x2b0 0x4>;
+                                               syscon = <&scm_conf>;
+                                               pbias_mmc_reg: pbias_mmc_omap2430 {
+                                                       regulator-name = "pbias_mmc_omap2430";
+                                                       regulator-min-microvolt = <1800000>;
+                                                       regulator-max-microvolt = <3000000>;
+                                               };
+                                       };
 
                                        scm_clocks: clocks {
                                                #address-cells = <1>;
                        dma-requests = <96>;
                };
 
-               pbias_regulator: pbias_regulator {
-                       compatible = "ti,pbias-omap";
-                       reg = <0x2b0 0x4>;
-                       syscon = <&scm_conf>;
-                       pbias_mmc_reg: pbias_mmc_omap2430 {
-                               regulator-name = "pbias_mmc_omap2430";
-                               regulator-min-microvolt = <1800000>;
-                               regulator-max-microvolt = <3000000>;
-                       };
-               };
-
                gpio1: gpio@48310000 {
                        compatible = "ti,omap3-gpio";
                        reg = <0x48310000 0x200>;
index abc4473e6f8a17e51d5e66416be089ab24d7b472..5a206c100ce287b34ce35f454d80749dfe6e9f06 100644 (file)
                                        reg = <0x5a0 0x170>;
                                        #address-cells = <1>;
                                        #size-cells = <1>;
+                                       ranges = <0 0x5a0 0x170>;
 
                                        pbias_regulator: pbias_regulator {
-                                               compatible = "ti,pbias-omap";
+                                               compatible = "ti,pbias-omap4", "ti,pbias-omap";
                                                reg = <0x60 0x4>;
                                                syscon = <&omap4_padconf_global>;
                                                pbias_mmc_reg: pbias_mmc_omap4 {
index 3cc8f357d5b8f5187814a202d2b5f6e74d837fb8..3cb030f9d2c4dcc1e36d17b41616b18287d38611 100644 (file)
 
        i2c5_pins: pinmux_i2c5_pins {
                pinctrl-single,pins = <
-                       0x184 (PIN_INPUT | MUX_MODE0)           /* i2c5_scl */
-                       0x186 (PIN_INPUT | MUX_MODE0)           /* i2c5_sda */
+                       0x186 (PIN_INPUT | MUX_MODE0)           /* i2c5_scl */
+                       0x188 (PIN_INPUT | MUX_MODE0)           /* i2c5_sda */
                >;
        };
 
index 4205a8ac9ddb1cbad8caeb7054c948000132b89a..4c04389dab3252fdbdc4c6e904bac0964eb58421 100644 (file)
                                        reg = <0x5a0 0xec>;
                                        #address-cells = <1>;
                                        #size-cells = <1>;
+                                       ranges = <0 0x5a0 0xec>;
 
                                        pbias_regulator: pbias_regulator {
-                                               compatible = "ti,pbias-omap";
+                                               compatible = "ti,pbias-omap5", "ti,pbias-omap";
                                                reg = <0x60 0x4>;
                                                syscon = <&omap5_padconf_global>;
                                                pbias_mmc_reg: pbias_mmc_omap5 {
index a0b2a79cbfbdf0b42286dea205fe6751fdaf57f6..4624d0f2a75425310a65b462221374eabde85210 100644 (file)
                                "mix.0", "mix.1",
                                "dvc.0", "dvc.1",
                                "clk_a", "clk_b", "clk_c", "clk_i";
+               power-domains = <&cpg_clocks>;
 
                status = "disabled";
 
index 831525dd39a60ad75b024e07b8d6153ff027e6b3..1666c8a6b1432e4f1c8a1a822fb59cb7d5de7375 100644 (file)
                                "mix.0", "mix.1",
                                "dvc.0", "dvc.1",
                                "clk_a", "clk_b", "clk_c", "clk_i";
+               power-domains = <&cpg_clocks>;
 
                status = "disabled";
 
index 2fa7a0dc83f76b17e287c7fa4b385d778e2a74c5..275c78ccc0f3e1e378983871f0c71df91ab1dd89 100644 (file)
 };
 
 &hdmi {
+       ddc-i2c-bus = <&i2c5>;
        status = "okay";
 };
 
index 810cda743b6d56ae19118260367f986dcee690af..9c2387b34d0c73c6942c4051d7f6ce72ee2a0aec 100644 (file)
@@ -56,7 +56,7 @@
                                        /* VMMCI level-shifter enable */
                                        default_hrefv60_cfg2 {
                                                pins = "GPIO169_D22";
-                                               ste,config = <&gpio_out_lo>;
+                                               ste,config = <&gpio_out_hi>;
                                        };
                                        /* VMMCI level-shifter voltage select */
                                        default_hrefv60_cfg3 {
index 32a5ccb14e7ebfbaec118ceed1f3bc14c2b646df..e80e42163883610005287282d9673c80377b6ce4 100644 (file)
 
                button@1 {
                        debounce_interval = <50>;
-                       wakeup = <1>;
+                       wakeup-source;
                        linux,code = <2>;
                        label = "userpb";
                        gpios = <&gpio1 0 0x4>;
                };
                button@2 {
                        debounce_interval = <50>;
-                       wakeup = <1>;
+                       wakeup-source;
                        linux,code = <3>;
                        label = "extkb1";
                        gpios = <&gpio4 23 0x4>;
                };
                button@3 {
                        debounce_interval = <50>;
-                       wakeup = <1>;
+                       wakeup-source;
                        linux,code = <4>;
                        label = "extkb2";
                        gpios = <&gpio4 24 0x4>;
                };
                button@4 {
                        debounce_interval = <50>;
-                       wakeup = <1>;
+                       wakeup-source;
                        linux,code = <5>;
                        label = "extkb3";
                        gpios = <&gpio5 1 0x4>;
                };
                button@5 {
                        debounce_interval = <50>;
-                       wakeup = <1>;
+                       wakeup-source;
                        linux,code = <6>;
                        label = "extkb4";
                        gpios = <&gpio5 2 0x4>;
index 3efa3b2ebe900df62c504340a8ca60c7aa7849c1..6b914e4bb0994de2a60327972329fb3d9010b627 100644 (file)
                                                         <&clk_s_d0_quadfs 0>,
                                                         <&clk_s_d2_quadfs 0>,
                                                         <&clk_s_d2_quadfs 0>;
-                               ranges;
-
-                               sti-hdmi@8d04000 {
-                                       compatible = "st,stih407-hdmi";
-                                       reg = <0x8d04000 0x1000>;
-                                       reg-names = "hdmi-reg";
-                                       interrupts = <GIC_SPI 106 IRQ_TYPE_NONE>;
-                                       interrupt-names = "irq";
-                                       clock-names = "pix",
-                                                     "tmds",
-                                                     "phy",
-                                                     "audio",
-                                                     "main_parent",
-                                                     "aux_parent";
-
-                                       clocks = <&clk_s_d2_flexgen CLK_PIX_HDMI>,
-                                                <&clk_s_d2_flexgen CLK_TMDS_HDMI>,
-                                                <&clk_s_d2_flexgen CLK_REF_HDMIPHY>,
-                                                <&clk_s_d0_flexgen CLK_PCM_0>,
-                                                <&clk_s_d2_quadfs 0>,
-                                                <&clk_s_d2_quadfs 1>;
-
-                                       hdmi,hpd-gpio = <&pio5 3>;
-                                       reset-names = "hdmi";
-                                       resets = <&softreset STIH407_HDMI_TX_PHY_SOFTRESET>;
-                                       ddc = <&hdmiddc>;
-
-                               };
-
-                               sti-hda@8d02000 {
-                                       compatible = "st,stih407-hda";
-                                       reg = <0x8d02000 0x400>, <0x92b0120 0x4>;
-                                       reg-names = "hda-reg", "video-dacs-ctrl";
-                                       clock-names = "pix",
-                                                     "hddac",
-                                                     "main_parent",
-                                                     "aux_parent";
-                                       clocks = <&clk_s_d2_flexgen CLK_PIX_HDDAC>,
-                                                <&clk_s_d2_flexgen CLK_HDDAC>,
-                                                <&clk_s_d2_quadfs 0>,
-                                                <&clk_s_d2_quadfs 1>;
-                               };
+                       };
+
+                       sti-hdmi@8d04000 {
+                               compatible = "st,stih407-hdmi";
+                               reg = <0x8d04000 0x1000>;
+                               reg-names = "hdmi-reg";
+                               interrupts = <GIC_SPI 106 IRQ_TYPE_NONE>;
+                               interrupt-names = "irq";
+                               clock-names = "pix",
+                                             "tmds",
+                                             "phy",
+                                             "audio",
+                                             "main_parent",
+                                             "aux_parent";
+
+                               clocks = <&clk_s_d2_flexgen CLK_PIX_HDMI>,
+                                        <&clk_s_d2_flexgen CLK_TMDS_HDMI>,
+                                        <&clk_s_d2_flexgen CLK_REF_HDMIPHY>,
+                                        <&clk_s_d0_flexgen CLK_PCM_0>,
+                                        <&clk_s_d2_quadfs 0>,
+                                        <&clk_s_d2_quadfs 1>;
+
+                               hdmi,hpd-gpio = <&pio5 3>;
+                               reset-names = "hdmi";
+                               resets = <&softreset STIH407_HDMI_TX_PHY_SOFTRESET>;
+                               ddc = <&hdmiddc>;
+                       };
+
+                       sti-hda@8d02000 {
+                               compatible = "st,stih407-hda";
+                               reg = <0x8d02000 0x400>, <0x92b0120 0x4>;
+                               reg-names = "hda-reg", "video-dacs-ctrl";
+                               clock-names = "pix",
+                                             "hddac",
+                                             "main_parent",
+                                             "aux_parent";
+                               clocks = <&clk_s_d2_flexgen CLK_PIX_HDDAC>,
+                                        <&clk_s_d2_flexgen CLK_HDDAC>,
+                                        <&clk_s_d2_quadfs 0>,
+                                        <&clk_s_d2_quadfs 1>;
                        };
                };
        };
index 6f40bc99c22f120240a1b05e123f5bf39c1e81f1..8c6e61a272346a0d5573c3c57475f9b338ca7219 100644 (file)
                                                         <&clk_s_d0_quadfs 0>,
                                                         <&clk_s_d2_quadfs 0>,
                                                         <&clk_s_d2_quadfs 0>;
-                               ranges;
-
-                               sti-hdmi@8d04000 {
-                                       compatible = "st,stih407-hdmi";
-                                       reg = <0x8d04000 0x1000>;
-                                       reg-names = "hdmi-reg";
-                                       interrupts = <GIC_SPI 106 IRQ_TYPE_NONE>;
-                                       interrupt-names = "irq";
-                                       clock-names = "pix",
-                                                     "tmds",
-                                                     "phy",
-                                                     "audio",
-                                                     "main_parent",
-                                                     "aux_parent";
-
-                                       clocks = <&clk_s_d2_flexgen CLK_PIX_HDMI>,
-                                                <&clk_s_d2_flexgen CLK_TMDS_HDMI>,
-                                                <&clk_s_d2_flexgen CLK_REF_HDMIPHY>,
-                                                <&clk_s_d0_flexgen CLK_PCM_0>,
-                                                <&clk_s_d2_quadfs 0>,
-                                                <&clk_s_d2_quadfs 1>;
-
-                                       hdmi,hpd-gpio = <&pio5 3>;
-                                       reset-names = "hdmi";
-                                       resets = <&softreset STIH407_HDMI_TX_PHY_SOFTRESET>;
-                                       ddc = <&hdmiddc>;
-
-                               };
-
-                               sti-hda@8d02000 {
-                                       compatible = "st,stih407-hda";
-                                       reg = <0x8d02000 0x400>, <0x92b0120 0x4>;
-                                       reg-names = "hda-reg", "video-dacs-ctrl";
-                                       clock-names = "pix",
-                                                     "hddac",
-                                                     "main_parent",
-                                                     "aux_parent";
-                                       clocks = <&clk_s_d2_flexgen CLK_PIX_HDDAC>,
-                                                <&clk_s_d2_flexgen CLK_HDDAC>,
-                                                <&clk_s_d2_quadfs 0>,
-                                                <&clk_s_d2_quadfs 1>;
-                               };
+                       };
+
+                       sti-hdmi@8d04000 {
+                               compatible = "st,stih407-hdmi";
+                               reg = <0x8d04000 0x1000>;
+                               reg-names = "hdmi-reg";
+                               interrupts = <GIC_SPI 106 IRQ_TYPE_NONE>;
+                               interrupt-names = "irq";
+                               clock-names = "pix",
+                                             "tmds",
+                                             "phy",
+                                             "audio",
+                                             "main_parent",
+                                             "aux_parent";
+
+                               clocks = <&clk_s_d2_flexgen CLK_PIX_HDMI>,
+                                        <&clk_s_d2_flexgen CLK_TMDS_HDMI>,
+                                        <&clk_s_d2_flexgen CLK_REF_HDMIPHY>,
+                                        <&clk_s_d0_flexgen CLK_PCM_0>,
+                                        <&clk_s_d2_quadfs 0>,
+                                        <&clk_s_d2_quadfs 1>;
+
+                               hdmi,hpd-gpio = <&pio5 3>;
+                               reset-names = "hdmi";
+                               resets = <&softreset STIH407_HDMI_TX_PHY_SOFTRESET>;
+                               ddc = <&hdmiddc>;
+                       };
+
+                       sti-hda@8d02000 {
+                               compatible = "st,stih407-hda";
+                               reg = <0x8d02000 0x400>, <0x92b0120 0x4>;
+                               reg-names = "hda-reg", "video-dacs-ctrl";
+                               clock-names = "pix",
+                                             "hddac",
+                                             "main_parent",
+                                             "aux_parent";
+                               clocks = <&clk_s_d2_flexgen CLK_PIX_HDDAC>,
+                                        <&clk_s_d2_flexgen CLK_HDDAC>,
+                                        <&clk_s_d2_quadfs 0>,
+                                        <&clk_s_d2_quadfs 1>;
                        };
                };
 
index 2bebaa286f9a3a49c65908f8a4874d5e3091b32a..391230c3dc938fb1a0a4c92ea91e05a209319baa 100644 (file)
                                720000  1200000
                                528000  1100000
                                312000  1000000
-                               144000  900000
+                               144000  1000000
                                >;
                        #cooling-cells = <2>;
                        cooling-min-level = <0>;
index 9d4f86e9c50ada156a5ae785399799b23d67efba..d845bd1448b5459f9a6e4ab52c538c541b8832ef 100644 (file)
                gpio-controller;
                #interrupt-cells = <2>;
                interrupt-controller;
+               /*
                gpio-ranges = <&pinmux 0 0 246>;
+               */
        };
 
        apbmisc@70000800 {
index 1e204a6de12c3a4156821a289a2f7064bd346574..819e2ae2cabe28b09952807ca2f0249c1aa82b7f 100644 (file)
                gpio-controller;
                #interrupt-cells = <2>;
                interrupt-controller;
+               /*
                gpio-ranges = <&pinmux 0 0 251>;
+               */
        };
 
        apbdma: dma@0,60020000 {
index e058709e6d98c0db886bf4549366722605380985..969b828505ae4404846ff169ce17ad7ffd178ec2 100644 (file)
                gpio-controller;
                #interrupt-cells = <2>;
                interrupt-controller;
+               /*
                gpio-ranges = <&pinmux 0 0 224>;
+               */
        };
 
        apbmisc@70000800 {
index fe04fb5e155f4c7dd39509b8877d95eb7a6f8021..c6938ad1b543fb93cf22d297dda5b2d18795afe8 100644 (file)
                gpio-controller;
                #interrupt-cells = <2>;
                interrupt-controller;
+               /*
                gpio-ranges = <&pinmux 0 0 248>;
+               */
        };
 
        apbmisc@70000800 {
index 33963acd7e8f9227eaca31a60c240a37d9f6e754..f80f772d99fb5750ca4cb484a49bbea18b8ba61a 100644 (file)
@@ -85,7 +85,7 @@
 };
 
 &ethsc {
-       interrupts = <0 50 4>;
+       interrupts = <0 52 4>;
 };
 
 &serial0 {
index 96dabcb6c62107f5675fde3c78dd2f86b4588cf2..996aed3b4eee69883045bc3bc2f4500d085316ac 100644 (file)
@@ -95,7 +95,7 @@ void it8152_init_irq(void)
        }
 }
 
-void it8152_irq_demux(unsigned int irq, struct irq_desc *desc)
+void it8152_irq_demux(struct irq_desc *desc)
 {
        int bits_pd, bits_lp, bits_ld;
        int i;
index 304adea4bc52f4b8e32157dcd0f64d530ccb3a4c..0e97b4b871f9b045fb8b01d4e9a8cd686f775fd6 100644 (file)
@@ -138,7 +138,7 @@ static struct locomo_dev_info locomo_devices[] = {
        },
 };
 
-static void locomo_handler(unsigned int __irq, struct irq_desc *desc)
+static void locomo_handler(struct irq_desc *desc)
 {
        struct locomo *lchip = irq_desc_get_chip_data(desc);
        int req, i;
index 4f290250fa9328f2bc00c6d701267c4e6e4f21c4..3d224941b5419e88a25aae2ae70632dba047606c 100644 (file)
@@ -196,10 +196,8 @@ static struct sa1111_dev_info sa1111_devices[] = {
  * active IRQs causes the interrupt output to pulse, the upper levels
  * will call us again if there are more interrupts to process.
  */
-static void
-sa1111_irq_handler(unsigned int __irq, struct irq_desc *desc)
+static void sa1111_irq_handler(struct irq_desc *desc)
 {
-       unsigned int irq = irq_desc_get_irq(desc);
        unsigned int stat0, stat1, i;
        struct sa1111 *sachip = irq_desc_get_handler_data(desc);
        void __iomem *mapbase = sachip->base + SA1111_INTC;
@@ -214,7 +212,7 @@ sa1111_irq_handler(unsigned int __irq, struct irq_desc *desc)
        sa1111_writel(stat1, mapbase + SA1111_INTSTATCLR1);
 
        if (stat0 == 0 && stat1 == 0) {
-               do_bad_IRQ(irq, desc);
+               do_bad_IRQ(desc);
                return;
        }
 
index 50c84e1876fc857f3e5b08843b24f6c6e39e3416..3f15a5cae16778137de0279a637306661d35099f 100644 (file)
@@ -240,7 +240,8 @@ CONFIG_SSI_PROTOCOL=m
 CONFIG_PINCTRL_SINGLE=y
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
-CONFIG_GPIO_PCF857X=m
+CONFIG_GPIO_PCA953X=m
+CONFIG_GPIO_PCF857X=y
 CONFIG_GPIO_TWL4030=y
 CONFIG_GPIO_PALMAS=y
 CONFIG_W1=m
@@ -350,6 +351,8 @@ CONFIG_USB_MUSB_HDRC=m
 CONFIG_USB_MUSB_OMAP2PLUS=m
 CONFIG_USB_MUSB_AM35X=m
 CONFIG_USB_MUSB_DSPS=m
+CONFIG_USB_INVENTRA_DMA=y
+CONFIG_USB_TI_CPPI41_DMA=y
 CONFIG_USB_DWC3=m
 CONFIG_USB_TEST=m
 CONFIG_AM335X_PHY_USB=y
index 7bbf325a4f31f12c9d867381853579a495590f89..b2bc8e11471d3ee3e4fcd5f207406222ffa04bf1 100644 (file)
@@ -491,11 +491,6 @@ THUMB(     orr     \reg , \reg , #PSR_T_BIT        )
 #endif
        .endm
 
-       .macro  uaccess_save_and_disable, tmp
-       uaccess_save \tmp
-       uaccess_disable \tmp
-       .endm
-
        .irp    c,,eq,ne,cs,cc,mi,pl,vs,vc,hi,ls,ge,lt,gt,le,hs,lo
        .macro  ret\c, reg
 #if __LINUX_ARM_ARCH__ < 6
index b274bde24905a7503f60d38672346636d093854b..e7335a92144ef1d20d296ebdf26798148b2fa711 100644 (file)
@@ -40,6 +40,7 @@ do {                                                          \
                "2:\t.asciz " #__file "\n"                      \
                ".popsection\n"                                 \
                ".pushsection __bug_table,\"a\"\n"              \
+               ".align 2\n"                                    \
                "3:\t.word 1b, 2b\n"                            \
                "\t.hword " #__line ", 0\n"                     \
                ".popsection");                                 \
index e878129f2fee5dfec3d36bec2e9fcb7d8ef046e4..fc8ba1663601e0743a05b7cda52703df9f9bc07a 100644 (file)
@@ -12,6 +12,7 @@
 
 #ifndef __ASSEMBLY__
 #include <asm/barrier.h>
+#include <asm/thread_info.h>
 #endif
 
 /*
@@ -89,7 +90,8 @@ static inline unsigned int get_domain(void)
 
        asm(
        "mrc    p15, 0, %0, c3, c0      @ get domain"
-        : "=r" (domain));
+        : "=r" (domain)
+        : "m" (current_thread_info()->cpu_domain));
 
        return domain;
 }
@@ -98,7 +100,7 @@ static inline void set_domain(unsigned val)
 {
        asm volatile(
        "mcr    p15, 0, %0, c3, c0      @ set domain"
-         : : "r" (val));
+         : : "r" (val) : "memory");
        isb();
 }
 
index d36a73d7c0e8d956253f3a66c783cf4a33f24221..076777ff3daa3c5db361ee481c8b8ba15aa00718 100644 (file)
@@ -106,7 +106,7 @@ extern void __iomem *it8152_base_address;
 struct pci_dev;
 struct pci_sys_data;
 
-extern void it8152_irq_demux(unsigned int irq, struct irq_desc *desc);
+extern void it8152_irq_demux(struct irq_desc *desc);
 extern void it8152_init_irq(void);
 extern int it8152_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
 extern int it8152_pci_setup(int nr, struct pci_sys_data *sys);
index af79da40af2a1b949e94de520d867dd08c5c628d..9beb92914f4df4313f2bd4fba410fb6f720b9a24 100644 (file)
@@ -11,12 +11,6 @@ static inline void ack_bad_irq(int irq)
        pr_crit("unexpected IRQ trap at vector %02x\n", irq);
 }
 
-void set_irq_flags(unsigned int irq, unsigned int flags);
-
-#define IRQF_VALID     (1 << 0)
-#define IRQF_PROBE     (1 << 1)
-#define IRQF_NOAUTOEN  (1 << 2)
-
 #define ARCH_IRQ_INIT_FLAGS    (IRQ_NOREQUEST | IRQ_NOPROBE)
 
 #endif
index dcba0fa5176e990f8a23333f08e34e192351b407..c4072d9f32c7718c9be3a92626f01d80ff74b3c1 100644 (file)
 
 #define __KVM_HAVE_ARCH_INTC_INITIALIZED
 
-#if defined(CONFIG_KVM_ARM_MAX_VCPUS)
-#define KVM_MAX_VCPUS CONFIG_KVM_ARM_MAX_VCPUS
-#else
-#define KVM_MAX_VCPUS 0
-#endif
-
 #define KVM_USER_MEM_SLOTS 32
 #define KVM_PRIVATE_MEM_SLOTS 4
 #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
 #define KVM_HAVE_ONE_REG
+#define KVM_HALT_POLL_NS_DEFAULT 500000
 
 #define KVM_VCPU_MAX_FEATURES 2
 
 #include <kvm/arm_vgic.h>
 
+#define KVM_MAX_VCPUS VGIC_V2_MAX_CPUS
+
 u32 *kvm_vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num, u32 mode);
 int __attribute_const__ kvm_target_cpu(void);
 int kvm_reset_vcpu(struct kvm_vcpu *vcpu);
@@ -148,6 +145,7 @@ struct kvm_vm_stat {
 
 struct kvm_vcpu_stat {
        u32 halt_successful_poll;
+       u32 halt_attempted_poll;
        u32 halt_wakeup;
 };
 
index 2092ee1e1300075c628b9e4cf89b0045cb118a04..de4634b514563387b54f884e3e3e83c41fbae110 100644 (file)
@@ -23,10 +23,10 @@ extern int show_fiq_list(struct seq_file *, int);
 /*
  * This is for easy migration, but should be changed in the source
  */
-#define do_bad_IRQ(irq,desc)                           \
+#define do_bad_IRQ(desc)                               \
 do {                                                   \
        raw_spin_lock(&desc->lock);                     \
-       handle_bad_irq(irq, desc);                      \
+       handle_bad_irq(desc);                           \
        raw_spin_unlock(&desc->lock);                   \
 } while(0)
 
index d0a1119dcaf38ba92d99354aaeba18bbf0452004..776757d1604ab3901996bb24bb02748e54c2aee7 100644 (file)
@@ -25,7 +25,6 @@
 struct task_struct;
 
 #include <asm/types.h>
-#include <asm/domain.h>
 
 typedef unsigned long mm_segment_t;
 
index 32640c431a087f682ff461f971ca0c7c960c737e..7cba573c2cc9541a23ff2e0675a701117f7cf269 100644 (file)
@@ -19,7 +19,7 @@
  * This may need to be greater than __NR_last_syscall+1 in order to
  * account for the padding in the syscall table
  */
-#define __NR_syscalls  (388)
+#define __NR_syscalls  (392)
 
 /*
  * *NOTE*: This is a ghost syscall private to the kernel.  Only the
index 0c3f5a0dafd32c04af58eec20e6af09f2efca0fe..7a2a32a1d5a8c3fef87e995ac349435de1daeb6f 100644 (file)
 #define __NR_memfd_create              (__NR_SYSCALL_BASE+385)
 #define __NR_bpf                       (__NR_SYSCALL_BASE+386)
 #define __NR_execveat                  (__NR_SYSCALL_BASE+387)
+#define __NR_userfaultfd               (__NR_SYSCALL_BASE+388)
+#define __NR_membarrier                        (__NR_SYSCALL_BASE+389)
 
 /*
  * The following SWIs are ARM private.
index 05745eb838c599dc2dd6034a71b8ebec619b9995..fde6c88d560cffcf8d1433fe486695e763704ca9 100644 (file)
 /* 385 */      CALL(sys_memfd_create)
                CALL(sys_bpf)
                CALL(sys_execveat)
+               CALL(sys_userfaultfd)
+               CALL(sys_membarrier)
 #ifndef syscalls_counted
 .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
 #define syscalls_counted
index 5ff4826cb154b0b646e281f4903a4e45a1c69ae9..2766183e69df255371f0586ff96b7112ec3dc643 100644 (file)
@@ -79,26 +79,6 @@ asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
        handle_IRQ(irq, regs);
 }
 
-void set_irq_flags(unsigned int irq, unsigned int iflags)
-{
-       unsigned long clr = 0, set = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
-
-       if (irq >= nr_irqs) {
-               pr_err("Trying to set irq flags for IRQ%d\n", irq);
-               return;
-       }
-
-       if (iflags & IRQF_VALID)
-               clr |= IRQ_NOREQUEST;
-       if (iflags & IRQF_PROBE)
-               clr |= IRQ_NOPROBE;
-       if (!(iflags & IRQF_NOAUTOEN))
-               clr |= IRQ_NOAUTOEN;
-       /* Order is clear bits in "clr" then set bits in "set" */
-       irq_modify_status(irq, clr, set & ~clr);
-}
-EXPORT_SYMBOL_GPL(set_irq_flags);
-
 void __init init_IRQ(void)
 {
        int ret;
index a6ad93c9bce35ea33185bbb5abb2e61867a09173..fd9eefce0a7b8d66e019b048e4ee24753da7acc0 100644 (file)
@@ -259,15 +259,17 @@ int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
        if (err)
                return err;
 
-       patch_text((void *)bpt->bpt_addr,
-                  *(unsigned int *)arch_kgdb_ops.gdb_bpt_instr);
+       /* Machine is already stopped, so we can use __patch_text() directly */
+       __patch_text((void *)bpt->bpt_addr,
+                    *(unsigned int *)arch_kgdb_ops.gdb_bpt_instr);
 
        return err;
 }
 
 int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
 {
-       patch_text((void *)bpt->bpt_addr, *(unsigned int *)bpt->saved_instr);
+       /* Machine is already stopped, so we can use __patch_text() directly */
+       __patch_text((void *)bpt->bpt_addr, *(unsigned int *)bpt->saved_instr);
 
        return 0;
 }
index a3089bacb8d822ded284b432f1cb37ecd8b0ff66..7a7c4cea55231b1c793982ab63d6c5598004b14b 100644 (file)
@@ -226,6 +226,7 @@ copy_thread(unsigned long clone_flags, unsigned long stack_start,
 
        memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save));
 
+#ifdef CONFIG_CPU_USE_DOMAINS
        /*
         * Copy the initial value of the domain access control register
         * from the current thread: thread->addr_limit will have been
@@ -233,6 +234,7 @@ copy_thread(unsigned long clone_flags, unsigned long stack_start,
         * kernel/fork.c
         */
        thread->cpu_domain = get_domain();
+#endif
 
        if (likely(!(p->flags & PF_KTHREAD))) {
                *childregs = *current_pt_regs();
index b6cda06b455fc6e3b6fcde6313a93ad052bb3ada..7b8f2141427bda172899bfe8ae5113367163af47 100644 (file)
@@ -343,15 +343,18 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig,
                 */
                thumb = handler & 1;
 
-#if __LINUX_ARM_ARCH__ >= 7
                /*
-                * Clear the If-Then Thumb-2 execution state
-                * ARM spec requires this to be all 000s in ARM mode
-                * Snapdragon S4/Krait misbehaves on a Thumb=>ARM
-                * signal transition without this.
+                * Clear the If-Then Thumb-2 execution state.  ARM spec
+                * requires this to be all 000s in ARM mode.  Snapdragon
+                * S4/Krait misbehaves on a Thumb=>ARM signal transition
+                * without this.
+                *
+                * We must do this whenever we are running on a Thumb-2
+                * capable CPU, which includes ARMv6T2.  However, we elect
+                * to always do this to simplify the code; this field is
+                * marked UNK/SBZP for older architectures.
                 */
                cpsr &= ~PSR_IT_MASK;
-#endif
 
                if (thumb) {
                        cpsr |= PSR_T_BIT;
index bfb915d0566566978b8e51c5ae7c93adfad04d0f..356970f3b25e3d2f54b691c8c8b1bb9baca1d7b1 100644 (file)
@@ -21,6 +21,7 @@ config KVM
        depends on MMU && OF
        select PREEMPT_NOTIFIERS
        select ANON_INODES
+       select ARM_GIC
        select HAVE_KVM_CPU_RELAX_INTERCEPT
        select HAVE_KVM_ARCH_TLB_FLUSH_ALL
        select KVM_MMIO
@@ -45,15 +46,4 @@ config KVM_ARM_HOST
        ---help---
          Provides host support for ARM processors.
 
-config KVM_ARM_MAX_VCPUS
-       int "Number maximum supported virtual CPUs per VM"
-       depends on KVM_ARM_HOST
-       default 4
-       help
-         Static number of max supported virtual CPUs per VM.
-
-         If you choose a high number, the vcpu structures will be quite
-         large, so only choose a reasonable number that you expect to
-         actually use.
-
 endif # VIRTUALIZATION
index ce404a5c30628c72533a62e430c6150a54032fea..78b286994577183b8d9ef415ae3ba5f6a41113c4 100644 (file)
@@ -446,7 +446,7 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)
         * Map the VGIC hardware resources before running a vcpu the first
         * time on this VM.
         */
-       if (unlikely(!vgic_ready(kvm))) {
+       if (unlikely(irqchip_in_kernel(kvm) && !vgic_ready(kvm))) {
                ret = kvm_vgic_map_resources(kvm);
                if (ret)
                        return ret;
@@ -1080,7 +1080,7 @@ static int init_hyp_mode(void)
         */
        err = kvm_timer_hyp_init();
        if (err)
-               goto out_free_mappings;
+               goto out_free_context;
 
 #ifndef CONFIG_HOTPLUG_CPU
        free_boot_hyp_pgd();
index 702740d37465c31299b24ccd4b9fed7184267689..51a59504bef4096708c1c4c481fb9ab753a1d8d2 100644 (file)
@@ -515,8 +515,7 @@ ARM_BE8(rev r6, r6  )
 
        mrc     p15, 0, r2, c14, c3, 1  @ CNTV_CTL
        str     r2, [vcpu, #VCPU_TIMER_CNTV_CTL]
-       bic     r2, #1                  @ Clear ENABLE
-       mcr     p15, 0, r2, c14, c3, 1  @ CNTV_CTL
+
        isb
 
        mrrc    p15, 3, rr_lo_hi(r2, r3), c14   @ CNTV_CVAL
@@ -529,6 +528,9 @@ ARM_BE8(rev r6, r6  )
        mcrr    p15, 4, r2, r2, c14     @ CNTVOFF
 
 1:
+       mov     r2, #0                  @ Clear ENABLE
+       mcr     p15, 0, r2, c14, c3, 1  @ CNTV_CTL
+
        @ Allow physical timer/counter access for the host
        mrc     p15, 4, r2, c14, c1, 0  @ CNTHCTL
        orr     r2, r2, #(CNTHCTL_PL1PCEN | CNTHCTL_PL1PCTEN)
index 7b42012941872155dfc9dc0678cf7a653e9f3c64..6984342da13d09fd0194563f4b598cfb913ec6c1 100644 (file)
@@ -1792,8 +1792,10 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
                if (vma->vm_flags & VM_PFNMAP) {
                        gpa_t gpa = mem->guest_phys_addr +
                                    (vm_start - mem->userspace_addr);
-                       phys_addr_t pa = (vma->vm_pgoff << PAGE_SHIFT) +
-                                        vm_start - vma->vm_start;
+                       phys_addr_t pa;
+
+                       pa = (phys_addr_t)vma->vm_pgoff << PAGE_SHIFT;
+                       pa += vm_start - vma->vm_start;
 
                        /* IO region dirty page logging not allowed */
                        if (memslot->flags & KVM_MEM_LOG_DIRTY_PAGES)
index 4b94b513168da4ae52f517e7bb4937652308b427..ad6f6424f1d1b3aac2b94792178bd2d41fed3f97 100644 (file)
@@ -126,7 +126,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
 
 static unsigned long kvm_psci_vcpu_affinity_info(struct kvm_vcpu *vcpu)
 {
-       int i;
+       int i, matching_cpus = 0;
        unsigned long mpidr;
        unsigned long target_affinity;
        unsigned long target_affinity_mask;
@@ -151,12 +151,16 @@ static unsigned long kvm_psci_vcpu_affinity_info(struct kvm_vcpu *vcpu)
         */
        kvm_for_each_vcpu(i, tmp, kvm) {
                mpidr = kvm_vcpu_get_mpidr_aff(tmp);
-               if (((mpidr & target_affinity_mask) == target_affinity) &&
-                   !tmp->arch.pause) {
-                       return PSCI_0_2_AFFINITY_LEVEL_ON;
+               if ((mpidr & target_affinity_mask) == target_affinity) {
+                       matching_cpus++;
+                       if (!tmp->arch.pause)
+                               return PSCI_0_2_AFFINITY_LEVEL_ON;
                }
        }
 
+       if (!matching_cpus)
+               return PSCI_RET_INVALID_PARAMS;
+
        return PSCI_0_2_AFFINITY_LEVEL_OFF;
 }
 
index 305d7c6242bb50ba488e4b2132ebeb54b4d3858f..bfb3703357c55aba72674827527e0fba68650b3e 100644 (file)
@@ -69,14 +69,14 @@ static struct irq_chip pmu_irq_chip = {
        .irq_ack        = pmu_irq_ack,
 };
 
-static void pmu_irq_handler(unsigned int __irq, struct irq_desc *desc)
+static void pmu_irq_handler(struct irq_desc *desc)
 {
-       unsigned int irq = irq_desc_get_irq(desc);
        unsigned long cause = readl(PMU_INTERRUPT_CAUSE);
+       unsigned int irq;
 
        cause &= readl(PMU_INTERRUPT_MASK);
        if (cause == 0) {
-               do_bad_IRQ(irq, desc);
+               do_bad_IRQ(desc);
                return;
        }
 
index 9bdf54795f05de26283881729a4427bd781ea2eb..56978199c4798fa236394c232e50d58a61e4fd3d 100644 (file)
@@ -20,6 +20,7 @@
 #include <asm/cputype.h>
 #include <asm/cp15.h>
 #include <asm/mcpm.h>
+#include <asm/smp_plat.h>
 
 #include "regs-pmu.h"
 #include "common.h"
@@ -70,7 +71,31 @@ static int exynos_cpu_powerup(unsigned int cpu, unsigned int cluster)
                cluster >= EXYNOS5420_NR_CLUSTERS)
                return -EINVAL;
 
-       exynos_cpu_power_up(cpunr);
+       if (!exynos_cpu_power_state(cpunr)) {
+               exynos_cpu_power_up(cpunr);
+
+               /*
+                * This assumes the cluster number of the big cores(Cortex A15)
+                * is 0 and the Little cores(Cortex A7) is 1.
+                * When the system was booted from the Little core,
+                * they should be reset during power up cpu.
+                */
+               if (cluster &&
+                   cluster == MPIDR_AFFINITY_LEVEL(cpu_logical_map(0), 1)) {
+                       /*
+                        * Before we reset the Little cores, we should wait
+                        * the SPARE2 register is set to 1 because the init
+                        * codes of the iROM will set the register after
+                        * initialization.
+                        */
+                       while (!pmu_raw_readl(S5P_PMU_SPARE2))
+                               udelay(10);
+
+                       pmu_raw_writel(EXYNOS5420_KFC_CORE_RESET(cpu),
+                                       EXYNOS_SWRESET);
+               }
+       }
+
        return 0;
 }
 
index 4a87e86dec45d1546153ca0ebb7310bbd5f82d93..7c21760f590ffd0d4cd47fcafcbcaffe64a85952 100644 (file)
@@ -200,15 +200,15 @@ no_clk:
                args.args_count = 0;
                child_domain = of_genpd_get_from_provider(&args);
                if (IS_ERR(child_domain))
-                       goto next_pd;
+                       continue;
 
                if (of_parse_phandle_with_args(np, "power-domains",
                                         "#power-domain-cells", 0, &args) != 0)
-                       goto next_pd;
+                       continue;
 
                parent_domain = of_genpd_get_from_provider(&args);
                if (IS_ERR(parent_domain))
-                       goto next_pd;
+                       continue;
 
                if (pm_genpd_add_subdomain(parent_domain, child_domain))
                        pr_warn("%s failed to add subdomain: %s\n",
@@ -216,8 +216,6 @@ no_clk:
                else
                        pr_info("%s has as child subdomain: %s.\n",
                                parent_domain->name, child_domain->name);
-next_pd:
-               of_node_put(np);
        }
 
        return 0;
index b7614333d2968befa767109f693bf7947528db4a..fba9068ed260de7f8211525e772ffc25d7d88f0a 100644 (file)
@@ -513,6 +513,12 @@ static inline unsigned int exynos_pmu_cpunr(unsigned int mpidr)
 #define SPREAD_ENABLE                                          0xF
 #define SPREAD_USE_STANDWFI                                    0xF
 
+#define EXYNOS5420_KFC_CORE_RESET0                             BIT(8)
+#define EXYNOS5420_KFC_ETM_RESET0                              BIT(20)
+
+#define EXYNOS5420_KFC_CORE_RESET(_nr)                         \
+       ((EXYNOS5420_KFC_CORE_RESET0 | EXYNOS5420_KFC_ETM_RESET0) << (_nr))
+
 #define EXYNOS5420_BB_CON1                                     0x0784
 #define EXYNOS5420_BB_SEL_EN                                   BIT(31)
 #define EXYNOS5420_BB_PMOS_EN                                  BIT(7)
index fcd79bc3a3e1d86639fd8b3d859133017e2deb99..c01fca11b224cfbc78f3038f581f9d95f56b3f35 100644 (file)
@@ -87,13 +87,12 @@ static struct irq_chip isa_hi_chip = {
        .irq_unmask     = isa_unmask_pic_hi_irq,
 };
 
-static void
-isa_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void isa_irq_handler(struct irq_desc *desc)
 {
        unsigned int isa_irq = *(unsigned char *)PCIIACK_BASE;
 
        if (isa_irq < _ISA_IRQ(0) || isa_irq >= _ISA_IRQ(16)) {
-               do_bad_IRQ(isa_irq, desc);
+               do_bad_IRQ(desc);
                return;
        }
 
index 220333ed741db064e066d79d6ea57503b694ac4e..2478d9f4d92dc7c75cec60267dfffd747b7f4120 100644 (file)
@@ -126,7 +126,7 @@ static int gpio_set_irq_type(struct irq_data *d, unsigned int type)
        return 0;
 }
 
-static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void gpio_irq_handler(struct irq_desc *desc)
 {
        unsigned int port = (unsigned int)irq_desc_get_handler_data(desc);
        unsigned int gpio_irq_no, irq_stat;
index 45903be6e7b3d7efd01656f21d24ea94cdaf74bf..16496a071ecb8c3174639a15fbc3d6fe092d3e3b 100644 (file)
@@ -85,7 +85,7 @@ static struct platform_device smsc_lan9217_device = {
        .resource = smsc911x_resources,
 };
 
-static void mxc_expio_irq_handler(u32 irq, struct irq_desc *desc)
+static void mxc_expio_irq_handler(struct irq_desc *desc)
 {
        u32 imr_val;
        u32 int_valid;
index 2c0853560bd2f6777144005e2ff5a83d975fc0f3..2b147e4bf9c91297deb0522bcfb14150b61f5b11 100644 (file)
@@ -154,7 +154,7 @@ static inline void mxc_init_imx_uart(void)
        imx31_add_imx_uart0(&uart_pdata);
 }
 
-static void mx31ads_expio_irq_handler(u32 irq, struct irq_desc *desc)
+static void mx31ads_expio_irq_handler(struct irq_desc *desc)
 {
        u32 imr_val;
        u32 int_valid;
index 9f89e76dfbb94a6ad27e4769545049726ae4c99b..f6235b28578c2fcaec332d9d091dd732ca861090 100644 (file)
@@ -91,7 +91,7 @@ static void (*write_imipr[])(u32) = {
        write_imipr_3,
 };
 
-static void iop13xx_msi_handler(unsigned int irq, struct irq_desc *desc)
+static void iop13xx_msi_handler(struct irq_desc *desc)
 {
        int i, j;
        unsigned long status;
index cce4cef12b6eefa7ddc7fd4e4d204b635b9e5934..2ae431e8bc1bd6236c9fcdfbafff707156a1e51d 100644 (file)
@@ -370,7 +370,7 @@ static struct irq_chip lpc32xx_irq_chip = {
        .irq_set_wake = lpc32xx_irq_wake
 };
 
-static void lpc32xx_sic1_handler(unsigned int irq, struct irq_desc *desc)
+static void lpc32xx_sic1_handler(struct irq_desc *desc)
 {
        unsigned long ints = __raw_readl(LPC32XX_INTC_STAT(LPC32XX_SIC1_BASE));
 
@@ -383,7 +383,7 @@ static void lpc32xx_sic1_handler(unsigned int irq, struct irq_desc *desc)
        }
 }
 
-static void lpc32xx_sic2_handler(unsigned int irq, struct irq_desc *desc)
+static void lpc32xx_sic2_handler(struct irq_desc *desc)
 {
        unsigned long ints = __raw_readl(LPC32XX_INTC_STAT(LPC32XX_SIC2_BASE));
 
index 6373e2bff203e609bdc6eff4b55bdd014f11f436..842302df99c1bfdcdf0a0c00fa8131e30206562d 100644 (file)
@@ -69,8 +69,7 @@ static struct platform_device *devices[] __initdata = {
 #define DEBUG_IRQ(fmt...)      while (0) {}
 #endif
 
-static void
-netx_hif_demux_handler(unsigned int irq_unused, struct irq_desc *desc)
+static void netx_hif_demux_handler(struct irq_desc *desc)
 {
        unsigned int irq = NETX_IRQ_HIF_CHAINED(0);
        unsigned int stat;
index dfec671b1639427ae65f8f57773bbf56ba301803..39e20d0ead084ec60ed42c11dacfae891cb63f4d 100644 (file)
@@ -87,7 +87,7 @@ static void fpga_mask_ack_irq(struct irq_data *d)
        fpga_ack_irq(d);
 }
 
-static void innovator_fpga_IRQ_demux(unsigned int irq, struct irq_desc *desc)
+static void innovator_fpga_IRQ_demux(struct irq_desc *desc)
 {
        u32 stat;
        int fpga_irq;
index 07d2e100caabf935c019beda8c2a830e3d2ae3f7..33d1460a56391c397ef305d8ed8275fa94b15720 100644 (file)
@@ -44,10 +44,12 @@ config SOC_OMAP5
        select ARM_CPU_SUSPEND if PM
        select ARM_GIC
        select HAVE_ARM_SCU if SMP
-       select HAVE_ARM_TWD if SMP
        select HAVE_ARM_ARCH_TIMER
        select ARM_ERRATA_798181 if SMP
+       select OMAP_INTERCONNECT
        select OMAP_INTERCONNECT_BARRIER
+       select PM_OPP if PM
+       select ZONE_DMA if ARM_LPAE
 
 config SOC_AM33XX
        bool "TI AM33XX"
@@ -70,10 +72,14 @@ config SOC_DRA7XX
        select ARCH_OMAP2PLUS
        select ARM_CPU_SUSPEND if PM
        select ARM_GIC
+       select HAVE_ARM_SCU if SMP
        select HAVE_ARM_ARCH_TIMER
        select IRQ_CROSSBAR
        select ARM_ERRATA_798181 if SMP
+       select OMAP_INTERCONNECT
        select OMAP_INTERCONNECT_BARRIER
+       select PM_OPP if PM
+       select ZONE_DMA if ARM_LPAE
 
 config ARCH_OMAP2PLUS
        bool
index 24c9afc9e8a70206bbb799c106345a9bd59bef5b..fb219a30c10c60ff56f8b6c0ae754a861f886dc0 100644 (file)
 
 #include "common.h"
 
-#if !(defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3))
-#define intc_of_init   NULL
-#endif
-#ifndef CONFIG_ARCH_OMAP4
-#define gic_of_init            NULL
-#endif
-
 static const struct of_device_id omap_dt_match_table[] __initconst = {
        { .compatible = "simple-bus", },
        { .compatible = "ti,omap-infra", },
@@ -113,6 +106,7 @@ DT_MACHINE_START(OMAP3_DT, "Generic OMAP3 (Flattened Device Tree)")
 MACHINE_END
 
 static const char *const omap36xx_boards_compat[] __initconst = {
+       "ti,omap3630",
        "ti,omap36xx",
        NULL,
 };
@@ -250,6 +244,9 @@ static const char *const omap5_boards_compat[] __initconst = {
 };
 
 DT_MACHINE_START(OMAP5_DT, "Generic OMAP5 (Flattened Device Tree)")
+#if defined(CONFIG_ZONE_DMA) && defined(CONFIG_ARM_LPAE)
+       .dma_zone_size  = SZ_2G,
+#endif
        .reserve        = omap_reserve,
        .smp            = smp_ops(omap4_smp_ops),
        .map_io         = omap5_map_io,
@@ -295,6 +292,9 @@ static const char *const dra74x_boards_compat[] __initconst = {
 };
 
 DT_MACHINE_START(DRA74X_DT, "Generic DRA74X (Flattened Device Tree)")
+#if defined(CONFIG_ZONE_DMA) && defined(CONFIG_ARM_LPAE)
+       .dma_zone_size  = SZ_2G,
+#endif
        .reserve        = omap_reserve,
        .smp            = smp_ops(omap4_smp_ops),
        .map_io         = dra7xx_map_io,
@@ -315,6 +315,9 @@ static const char *const dra72x_boards_compat[] __initconst = {
 };
 
 DT_MACHINE_START(DRA72X_DT, "Generic DRA72X (Flattened Device Tree)")
+#if defined(CONFIG_ZONE_DMA) && defined(CONFIG_ARM_LPAE)
+       .dma_zone_size  = SZ_2G,
+#endif
        .reserve        = omap_reserve,
        .map_io         = dra7xx_map_io,
        .init_early     = dra7xx_init_early,
index e3f713ffb06b7f7fd2e9187668b7698286a29dad..54a5ba54d2ffaea58cef114db9950d643ae17d77 100644 (file)
@@ -653,8 +653,12 @@ void __init dra7xxx_check_revision(void)
                        omap_revision = DRA752_REV_ES1_0;
                        break;
                case 1:
-               default:
                        omap_revision = DRA752_REV_ES1_1;
+                       break;
+               case 2:
+               default:
+                       omap_revision = DRA752_REV_ES2_0;
+                       break;
                }
                break;
 
@@ -674,7 +678,7 @@ void __init dra7xxx_check_revision(void)
                /* Unknown default to latest silicon rev as default*/
                pr_warn("%s: unknown idcode=0x%08x (hawkeye=0x%08x,rev=0x%x)\n",
                        __func__, idcode, hawkeye, rev);
-               omap_revision = DRA752_REV_ES1_1;
+               omap_revision = DRA752_REV_ES2_0;
        }
 
        sprintf(soc_name, "DRA%03x", omap_rev() >> 16);
index 980c9372e6fd6eb439e4161721289874992d0dd2..3eaeaca5da05f95fffe03d8927bc0b9ec0f63ef5 100644 (file)
@@ -676,6 +676,7 @@ void __init am43xx_init_early(void)
 void __init am43xx_init_late(void)
 {
        omap_common_late_init();
+       omap2_clk_enable_autoidle_all();
 }
 #endif
 
index 4cb8fd9f741fee7d86f78112616e32999544b016..72ebc4c16bae7e55a69775b02bfc534b9c56fda4 100644 (file)
@@ -901,7 +901,8 @@ static int __init omap_device_late_idle(struct device *dev, void *data)
                if (od->hwmods[i]->flags & HWMOD_INIT_NO_IDLE)
                        return 0;
 
-       if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER) {
+       if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER &&
+           od->_driver_status != BUS_NOTIFY_BIND_DRIVER) {
                if (od->_state == OMAP_DEVICE_STATE_ENABLED) {
                        dev_warn(dev, "%s: enabled but no driver.  Idling\n",
                                 __func__);
index ea56397599c21b1f0c7d806ccfe9b1f4fb062f52..1dfe34654c43a353a34ac2cb9b941ff9f951b275 100644 (file)
@@ -559,7 +559,14 @@ static void pdata_quirks_check(struct pdata_init *quirks)
 
 void __init pdata_quirks_init(const struct of_device_id *omap_dt_match_table)
 {
-       omap_sdrc_init(NULL, NULL);
+       /*
+        * We still need this for omap2420 and omap3 PM to work, others are
+        * using drivers/misc/sram.c already.
+        */
+       if (of_machine_is_compatible("ti,omap2420") ||
+           of_machine_is_compatible("ti,omap3"))
+               omap_sdrc_init(NULL, NULL);
+
        pdata_quirks_check(auxdata_quirks);
        of_platform_populate(NULL, omap_dt_match_table,
                             omap_auxdata_lookup, NULL);
index 425bfcd67db62e48ec03a83e941fc858301b01f4..b668719b9b25a7ada81229ba18ad2645777cf487 100644 (file)
@@ -103,7 +103,8 @@ static inline void enable_omap3630_toggle_l2_on_restore(void) { }
 #define PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD     (1 << 0)
 #define PM_OMAP4_CPU_OSWR_DISABLE              (1 << 1)
 
-#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP4)
+#if defined(CONFIG_PM) && (defined(CONFIG_ARCH_OMAP4) ||\
+          defined(CONFIG_SOC_OMAP5) || defined(CONFIG_SOC_DRA7XX))
 extern u16 pm44xx_errata;
 #define IS_PM44XX_ERRATUM(id)          (pm44xx_errata & (id))
 #else
index 257e98c266188c395f6ee135afb2ea60ba85a565..3fc2cbe52113b4c1b2f12a6f3cc4c33d874f4e30 100644 (file)
@@ -102,7 +102,7 @@ static void omap_prcm_events_filter_priority(unsigned long *events,
  * dispatched accordingly. Clearing of the wakeup events should be
  * done by the SoC specific individual handlers.
  */
-static void omap_prcm_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void omap_prcm_irq_handler(struct irq_desc *desc)
 {
        unsigned long pending[OMAP_PRCM_MAX_NR_PENDING_REG];
        unsigned long priority_pending[OMAP_PRCM_MAX_NR_PENDING_REG];
index f97654d11ea5ea33aedc2b290e4dad2ff0a97344..2d1d3845253c33493f2a3f66edf05db136c03a65 100644 (file)
@@ -469,6 +469,8 @@ IS_OMAP_TYPE(3430, 0x3430)
 #define DRA7XX_CLASS           0x07000000
 #define DRA752_REV_ES1_0       (DRA7XX_CLASS | (0x52 << 16) | (0x10 << 8))
 #define DRA752_REV_ES1_1       (DRA7XX_CLASS | (0x52 << 16) | (0x11 << 8))
+#define DRA752_REV_ES2_0       (DRA7XX_CLASS | (0x52 << 16) | (0x20 << 8))
+#define DRA722_REV_ES1_0       (DRA7XX_CLASS | (0x22 << 16) | (0x10 << 8))
 #define DRA722_REV_ES1_0       (DRA7XX_CLASS | (0x22 << 16) | (0x10 << 8))
 
 void omap2xxx_check_revision(void);
index e4d8701f99f9cb8694301c18b51345b9daf03850..a55655127ef23e7b3a325fdd43c4d9ff729719fd 100644 (file)
@@ -297,12 +297,8 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
        if (IS_ERR(src))
                return PTR_ERR(src);
 
-       r = clk_set_parent(timer->fclk, src);
-       if (r < 0) {
-               pr_warn("%s: %s cannot set source\n", __func__, oh->name);
-               clk_put(src);
-               return r;
-       }
+       WARN(clk_set_parent(timer->fclk, src) < 0,
+            "Cannot set timer parent clock, no PLL clock driver?");
 
        clk_put(src);
 
index e5a35f6b83a79058cf23092c0348400d05a47675..d44d311704ba97e72a8736d79cfb024ebc78a214 100644 (file)
@@ -300,7 +300,7 @@ static void __init omap3_vc_init_pmic_signaling(struct voltagedomain *voltdm)
 
        val = voltdm->read(OMAP3_PRM_POLCTRL_OFFSET);
        if (!(val & OMAP3430_PRM_POLCTRL_CLKREQ_POL) ||
-           (val & OMAP3430_PRM_POLCTRL_CLKREQ_POL)) {
+           (val & OMAP3430_PRM_POLCTRL_OFFMODE_POL)) {
                val |= OMAP3430_PRM_POLCTRL_CLKREQ_POL;
                val &= ~OMAP3430_PRM_POLCTRL_OFFMODE_POL;
                pr_debug("PM: fixing sys_clkreq and sys_off_mode polarity to 0x%x\n",
index 70366b35d299bad321aefcd020220bd81fe5332b..a727282bfa99605b51c3fd498af006829442b286 100644 (file)
@@ -496,13 +496,13 @@ static struct irq_chip balloon3_irq_chip = {
        .irq_unmask     = balloon3_unmask_irq,
 };
 
-static void balloon3_irq_handler(unsigned int __irq, struct irq_desc *desc)
+static void balloon3_irq_handler(struct irq_desc *desc)
 {
        unsigned long pending = __raw_readl(BALLOON3_INT_CONTROL_REG) &
                                        balloon3_irq_enabled;
        do {
                struct irq_data *d = irq_desc_get_irq_data(desc);
-               struct irq_chip *chip = irq_data_get_chip(d);
+               struct irq_chip *chip = irq_desc_get_chip(desc);
                unsigned int irq;
 
                /* clear useless edge notification */
index 1fa79f1f832deeacf04529f6772ceaab1f6eed15..3221ae15bef761b6a8548ac20b0a77fff70d9aee 100644 (file)
 void __iomem *it8152_base_address;
 static int cmx2xx_it8152_irq_gpio;
 
-static void cmx2xx_it8152_irq_demux(unsigned int __irq, struct irq_desc *desc)
+static void cmx2xx_it8152_irq_demux(struct irq_desc *desc)
 {
-       unsigned int irq = irq_desc_get_irq(desc);
        /* clear our parent irq */
        desc->irq_data.chip->irq_ack(&desc->irq_data);
 
-       it8152_irq_demux(irq, desc);
+       it8152_irq_demux(desc);
 }
 
 void __cmx2xx_pci_init_irq(int irq_gpio)
index d28fe291233a55ddb0173bcd71e124fc900010e2..07b93fd244747312be8b2ab4fe1d7de68d617675 100644 (file)
  * 0xf6200000..0xf6201000
  */
 
+/*
+ * DFI Bus for NAND, PXA3xx only
+ */
+#define NAND_PHYS              0x43100000
+#define NAND_VIRT              IOMEM(0xf6300000)
+#define NAND_SIZE              0x00100000
+
 /*
  * Internal Memory Controller (PXA27x and later)
  */
index b070167deef278e9859f3b86e929073ba8f5a43a..4823d972e64745dd4ae10dbfed0138eb46d10311 100644 (file)
@@ -120,7 +120,7 @@ static struct irq_chip lpd270_irq_chip = {
        .irq_unmask     = lpd270_unmask_irq,
 };
 
-static void lpd270_irq_handler(unsigned int __irq, struct irq_desc *desc)
+static void lpd270_irq_handler(struct irq_desc *desc)
 {
        unsigned int irq;
        unsigned long pending;
index 9a0c8affdadb635ad5c1b5684812fdd0eba5640e..d8319b54299a571d223321a53cd7776aa71ccece 100644 (file)
@@ -284,7 +284,7 @@ static struct irq_chip pcm990_irq_chip = {
        .irq_unmask     = pcm990_unmask_irq,
 };
 
-static void pcm990_irq_handler(unsigned int __irq, struct irq_desc *desc)
+static void pcm990_irq_handler(struct irq_desc *desc)
 {
        unsigned int irq;
        unsigned long pending;
index ce0f8d6242e2a047429a031f7ab9e6e53193d917..20ce2d386f172c849459e94d1bb88601f1fdd0e7 100644 (file)
 #define PECR_IS(n)     ((1 << ((n) * 2)) << 29)
 
 extern void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int));
+
+/*
+ * NAND NFC: DFI bus arbitration subset
+ */
+#define NDCR                   (*(volatile u32 __iomem*)(NAND_VIRT + 0))
+#define NDCR_ND_ARB_EN         (1 << 12)
+#define NDCR_ND_ARB_CNTL       (1 << 19)
+
 #ifdef CONFIG_PM
 
 #define ISRAM_START    0x5c000000
@@ -362,7 +370,12 @@ static struct map_desc pxa3xx_io_desc[] __initdata = {
                .pfn            = __phys_to_pfn(PXA3XX_SMEMC_BASE),
                .length         = SMEMC_SIZE,
                .type           = MT_DEVICE
-       }
+       }, {
+               .virtual        = (unsigned long)NAND_VIRT,
+               .pfn            = __phys_to_pfn(NAND_PHYS),
+               .length         = NAND_SIZE,
+               .type           = MT_DEVICE
+       },
 };
 
 void __init pxa3xx_map_io(void)
@@ -419,6 +432,13 @@ static int __init pxa3xx_init(void)
                 */
                ASCR &= ~(ASCR_RDH | ASCR_D1S | ASCR_D2S | ASCR_D3S);
 
+               /*
+                * Disable DFI bus arbitration, to prevent a system bus lock if
+                * somebody disables the NAND clock (unused clock) while this
+                * bit remains set.
+                */
+               NDCR = (NDCR & ~NDCR_ND_ARB_EN) | NDCR_ND_ARB_CNTL;
+
                if ((ret = pxa_init_dma(IRQ_DMA, 32)))
                        return ret;
 
index 4841d6cefe76affc01d8bdf1b82d97f67909c7af..8ab26370107ea5d0df2742b1ac0ab31aa18eb425 100644 (file)
@@ -276,7 +276,7 @@ static inline unsigned long viper_irq_pending(void)
                        viper_irq_enabled_mask;
 }
 
-static void viper_irq_handler(unsigned int __irq, struct irq_desc *desc)
+static void viper_irq_handler(struct irq_desc *desc)
 {
        unsigned int irq;
        unsigned long pending;
index 6f94dd7b4dee0135307df00576d6a6be176577ca..30e62a3f0701a5884ca0835cf7c5db47aeab2330 100644 (file)
@@ -105,7 +105,7 @@ static inline unsigned long zeus_irq_pending(void)
        return __raw_readw(ZEUS_CPLD_ISA_IRQ) & zeus_irq_enabled_mask;
 }
 
-static void zeus_irq_handler(unsigned int __irq, struct irq_desc *desc)
+static void zeus_irq_handler(struct irq_desc *desc)
 {
        unsigned int irq;
        unsigned long pending;
index f726d4c4e6dd8caf6ab5966a8bd63a02183e5057..dc67a7fb383199ba26657d7ab9e5611031c9e20c 100644 (file)
@@ -551,8 +551,7 @@ static void ecard_check_lockup(struct irq_desc *desc)
        }
 }
 
-static void
-ecard_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void ecard_irq_handler(struct irq_desc *desc)
 {
        ecard_t *ec;
        int called = 0;
index ced1ab86ac83a7037edd2727ba54234c8b90867b..2bb08961e934ca91c704e32b6f0a324516157e17 100644 (file)
@@ -100,9 +100,7 @@ static struct irq_chip  bast_pc104_chip = {
        .irq_ack        = bast_pc104_maskack
 };
 
-static void
-bast_irq_pc104_demux(unsigned int irq,
-                    struct irq_desc *desc)
+static void bast_irq_pc104_demux(struct irq_desc *desc)
 {
        unsigned int stat;
        unsigned int irqno;
index fd63ecfb2f81f37d38e41d6eb06cdbf365efee4d..ddb30b8434c539588afaebef7d08ce086e5b6726 100644 (file)
@@ -388,22 +388,22 @@ static inline void s3c_irq_demux_eint(unsigned int start, unsigned int end)
        }
 }
 
-static void s3c_irq_demux_eint0_3(unsigned int irq, struct irq_desc *desc)
+static void s3c_irq_demux_eint0_3(struct irq_desc *desc)
 {
        s3c_irq_demux_eint(0, 3);
 }
 
-static void s3c_irq_demux_eint4_11(unsigned int irq, struct irq_desc *desc)
+static void s3c_irq_demux_eint4_11(struct irq_desc *desc)
 {
        s3c_irq_demux_eint(4, 11);
 }
 
-static void s3c_irq_demux_eint12_19(unsigned int irq, struct irq_desc *desc)
+static void s3c_irq_demux_eint12_19(struct irq_desc *desc)
 {
        s3c_irq_demux_eint(12, 19);
 }
 
-static void s3c_irq_demux_eint20_27(unsigned int irq, struct irq_desc *desc)
+static void s3c_irq_demux_eint20_27(struct irq_desc *desc)
 {
        s3c_irq_demux_eint(20, 27);
 }
index 6d237b4f7a8ef226acb57bb196f066183a754fb6..8411985af9ff89addd5ae0cc04ff365842961c5d 100644 (file)
@@ -166,7 +166,7 @@ static struct sa1100_port_fns neponset_port_fns = {
  * ensure that the IRQ signal is deasserted before returning.  This
  * is rather unfortunate.
  */
-static void neponset_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void neponset_irq_handler(struct irq_desc *desc)
 {
        struct neponset_drvdata *d = irq_desc_get_handler_data(desc);
        unsigned int irr;
index 9769f1eefe3bc51b29188576a5e2aacc2f1dcedc..00b7f7de28a182c849249a242fb0ecd2d68b09ca 100644 (file)
@@ -365,15 +365,21 @@ do_alignment_ldrhstrh(unsigned long addr, unsigned long instr, struct pt_regs *r
  user:
        if (LDST_L_BIT(instr)) {
                unsigned long val;
+               unsigned int __ua_flags = uaccess_save_and_enable();
+
                get16t_unaligned_check(val, addr);
+               uaccess_restore(__ua_flags);
 
                /* signed half-word? */
                if (instr & 0x40)
                        val = (signed long)((signed short) val);
 
                regs->uregs[rd] = val;
-       } else
+       } else {
+               unsigned int __ua_flags = uaccess_save_and_enable();
                put16t_unaligned_check(regs->uregs[rd], addr);
+               uaccess_restore(__ua_flags);
+       }
 
        return TYPE_LDST;
 
@@ -420,14 +426,21 @@ do_alignment_ldrdstrd(unsigned long addr, unsigned long instr,
 
  user:
        if (load) {
-               unsigned long val;
+               unsigned long val, val2;
+               unsigned int __ua_flags = uaccess_save_and_enable();
+
                get32t_unaligned_check(val, addr);
+               get32t_unaligned_check(val2, addr + 4);
+
+               uaccess_restore(__ua_flags);
+
                regs->uregs[rd] = val;
-               get32t_unaligned_check(val, addr + 4);
-               regs->uregs[rd2] = val;
+               regs->uregs[rd2] = val2;
        } else {
+               unsigned int __ua_flags = uaccess_save_and_enable();
                put32t_unaligned_check(regs->uregs[rd], addr);
                put32t_unaligned_check(regs->uregs[rd2], addr + 4);
+               uaccess_restore(__ua_flags);
        }
 
        return TYPE_LDST;
@@ -458,10 +471,15 @@ do_alignment_ldrstr(unsigned long addr, unsigned long instr, struct pt_regs *reg
  trans:
        if (LDST_L_BIT(instr)) {
                unsigned int val;
+               unsigned int __ua_flags = uaccess_save_and_enable();
                get32t_unaligned_check(val, addr);
+               uaccess_restore(__ua_flags);
                regs->uregs[rd] = val;
-       } else
+       } else {
+               unsigned int __ua_flags = uaccess_save_and_enable();
                put32t_unaligned_check(regs->uregs[rd], addr);
+               uaccess_restore(__ua_flags);
+       }
        return TYPE_LDST;
 
  fault:
@@ -531,6 +549,7 @@ do_alignment_ldmstm(unsigned long addr, unsigned long instr, struct pt_regs *reg
 #endif
 
        if (user_mode(regs)) {
+               unsigned int __ua_flags = uaccess_save_and_enable();
                for (regbits = REGMASK_BITS(instr), rd = 0; regbits;
                     regbits >>= 1, rd += 1)
                        if (regbits & 1) {
@@ -542,6 +561,7 @@ do_alignment_ldmstm(unsigned long addr, unsigned long instr, struct pt_regs *reg
                                        put32t_unaligned_check(regs->uregs[rd], eaddr);
                                eaddr += 4;
                        }
+               uaccess_restore(__ua_flags);
        } else {
                for (regbits = REGMASK_BITS(instr), rd = 0; regbits;
                     regbits >>= 1, rd += 1)
index e62604384945e513a9b1ed14a2a5a2e3d8950630..1a7815e5421b6b1d3ad774b28915b84b52726136 100644 (file)
@@ -1249,7 +1249,7 @@ __iommu_create_mapping(struct device *dev, struct page **pages, size_t size)
        struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
        unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
        dma_addr_t dma_addr, iova;
-       int i, ret = DMA_ERROR_CODE;
+       int i;
 
        dma_addr = __alloc_iova(mapping, size);
        if (dma_addr == DMA_ERROR_CODE)
@@ -1257,6 +1257,8 @@ __iommu_create_mapping(struct device *dev, struct page **pages, size_t size)
 
        iova = dma_addr;
        for (i = 0; i < count; ) {
+               int ret;
+
                unsigned int next_pfn = page_to_pfn(pages[i]) + 1;
                phys_addr_t phys = page_to_phys(pages[i]);
                unsigned int len, j;
index 876060bcceeb3ea989e24fe18b42910f3cce4058..b8efb8cd1f73ee1cb7de196ae88d9173203c4d2a 100644 (file)
@@ -614,6 +614,7 @@ load_common:
                case BPF_LD | BPF_B | BPF_IND:
                        load_order = 0;
 load_ind:
+                       update_on_xread(ctx);
                        OP_IMM3(ARM_ADD, r_off, r_X, k, ctx);
                        goto load_common;
                case BPF_LDX | BPF_IMM:
index 71df4354765927da922606db930c6665cbd0c7f9..39c20afad7ed9ed3b4b967a54d3a435e07eccf9e 100644 (file)
@@ -95,9 +95,10 @@ emulate:
        reteq   r4                      @ no, return failure
 
 next:
+       uaccess_enable r3
 .Lx1:  ldrt    r6, [r5], #4            @ get the next instruction and
                                        @ increment PC
-
+       uaccess_disable r3
        and     r2, r6, #0x0F000000     @ test for FP insns
        teq     r2, #0x0C000000
        teqne   r2, #0x0D000000
index 2235081a04eeac818f58b44923aa565026c0b746..8861c367d06114651920b05420e53ebde3099712 100644 (file)
@@ -495,7 +495,7 @@ void __init orion_ge00_switch_init(struct dsa_platform_data *d, int irq)
 
        d->netdev = &orion_ge00.dev;
        for (i = 0; i < d->nr_chips; i++)
-               d->chip[i].host_dev = &orion_ge00_shared.dev;
+               d->chip[i].host_dev = &orion_ge_mvmdio.dev;
        orion_switch_device.dev.platform_data = d;
 
        platform_device_register(&orion_switch_device);
index 79c33eca09a352ea1563670aaf7f68ecbe74d7c9..7bd22d8e5b11bd31847ff0504b615d4639b64a5b 100644 (file)
@@ -407,7 +407,7 @@ static int gpio_irq_set_type(struct irq_data *d, u32 type)
        return 0;
 }
 
-static void gpio_irq_handler(unsigned __irq, struct irq_desc *desc)
+static void gpio_irq_handler(struct irq_desc *desc)
 {
        struct orion_gpio_chip *ochip = irq_desc_get_handler_data(desc);
        u32 cause, type;
index ad9529cc420374475039c1ae2681ac356fdd14b4..daa1a65f2eb799c7dc12365146207105b735d8ba 100644 (file)
@@ -107,7 +107,6 @@ static const struct of_device_id pxa_ssp_of_ids[] = {
        { .compatible = "mvrl,pxa168-ssp",      .data = (void *) PXA168_SSP },
        { .compatible = "mrvl,pxa910-ssp",      .data = (void *) PXA910_SSP },
        { .compatible = "mrvl,ce4100-ssp",      .data = (void *) CE4100_SSP },
-       { .compatible = "mrvl,lpss-ssp",        .data = (void *) LPSS_SSP },
        { },
 };
 MODULE_DEVICE_TABLE(of, pxa_ssp_of_ids);
index aedec81d11988181e3e6f0631113fd01e4737ac8..0cebd98cd88c3fcbfcb88e0d3b1eae757755b3d4 100644 (file)
@@ -45,7 +45,6 @@
  * it does.
  */
 
-#include <byteswap.h>
 #include <elf.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <sys/types.h>
 #include <unistd.h>
 
+#define swab16(x) \
+       ((((x) & 0x00ff) << 8) | \
+        (((x) & 0xff00) >> 8))
+
+#define swab32(x) \
+       ((((x) & 0x000000ff) << 24) | \
+        (((x) & 0x0000ff00) <<  8) | \
+        (((x) & 0x00ff0000) >>  8) | \
+        (((x) & 0xff000000) << 24))
+
 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
 #define HOST_ORDER ELFDATA2LSB
 #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
@@ -104,17 +113,17 @@ static void cleanup(void)
 
 static Elf32_Word read_elf_word(Elf32_Word word, bool swap)
 {
-       return swap ? bswap_32(word) : word;
+       return swap ? swab32(word) : word;
 }
 
 static Elf32_Half read_elf_half(Elf32_Half half, bool swap)
 {
-       return swap ? bswap_16(half) : half;
+       return swap ? swab16(half) : half;
 }
 
 static void write_elf_word(Elf32_Word val, Elf32_Word *dst, bool swap)
 {
-       *dst = swap ? bswap_32(val) : val;
+       *dst = swap ? swab32(val) : val;
 }
 
 int main(int argc, char **argv)
index f00e080759384afd300398be488c5740f55f1091..10fd99c568c62a9296b4ad7d2cc3584360b1b8a0 100644 (file)
@@ -98,8 +98,23 @@ ENTRY(privcmd_call)
        mov r1, r2
        mov r2, r3
        ldr r3, [sp, #8]
+       /*
+        * Privcmd calls are issued by the userspace. We need to allow the
+        * kernel to access the userspace memory before issuing the hypercall.
+        */
+       uaccess_enable r4
+
+       /* r4 is loaded now as we use it as scratch register before */
        ldr r4, [sp, #4]
        __HVC(XEN_IMM)
+
+       /*
+        * Disable userspace access from kernel. This is fine to do it
+        * unconditionally as no set_fs(KERNEL_DS)/set_fs(get_ds()) is
+        * called before.
+        */
+       uaccess_disable r4
+
        ldm sp!, {r4}
        ret lr
 ENDPROC(privcmd_call);
index 7d95663c0160bd2575199e3836570e46fb4a158d..07d1811aa03fcd1ecd5ee7c260688a59f7ab97e4 100644 (file)
@@ -32,6 +32,7 @@ config ARM64
        select GENERIC_CLOCKEVENTS_BROADCAST
        select GENERIC_CPU_AUTOPROBE
        select GENERIC_EARLY_IOREMAP
+       select GENERIC_IDLE_POLL_SETUP
        select GENERIC_IRQ_PROBE
        select GENERIC_IRQ_SHOW
        select GENERIC_IRQ_SHOW_LEVEL
@@ -331,6 +332,22 @@ config ARM64_ERRATUM_845719
 
          If unsure, say Y.
 
+config ARM64_ERRATUM_843419
+       bool "Cortex-A53: 843419: A load or store might access an incorrect address"
+       depends on MODULES
+       default y
+       help
+         This option builds kernel modules using the large memory model in
+         order to avoid the use of the ADRP instruction, which can cause
+         a subsequent memory access to use an incorrect address on Cortex-A53
+         parts up to r0p4.
+
+         Note that the kernel itself must be linked with a version of ld
+         which fixes potentially affected ADRP instructions through the
+         use of veneers.
+
+         If unsure, say Y.
+
 endmenu
 
 
index 15ff5b4156fd74a041f3ad926efbeae05ba382dc..d10b5d483022f5374fa16c7783b7fb62014c3acb 100644 (file)
@@ -41,6 +41,10 @@ endif
 
 CHECKFLAGS     += -D__aarch64__
 
+ifeq ($(CONFIG_ARM64_ERRATUM_843419), y)
+KBUILD_CFLAGS_MODULE   += -mcmodel=large
+endif
+
 # Default value
 head-y         := arch/arm64/kernel/head.o
 
index 637e046f0e367dd23fbe391dc1542dd97a315504..3c386680357ebc2af6b0b734e26cdb1165194020 100644 (file)
 
                                button@1 {
                                        debounce_interval = <50>;
-                                       wakeup = <1>;
+                                       wakeup-source;
                                        linux,code = <116>;
                                        label = "POWER";
                                        gpios = <&iofpga_gpio0 0 0x4>;
                                };
                                button@2 {
                                        debounce_interval = <50>;
-                                       wakeup = <1>;
+                                       wakeup-source;
                                        linux,code = <102>;
                                        label = "HOME";
                                        gpios = <&iofpga_gpio0 1 0x4>;
                                };
                                button@3 {
                                        debounce_interval = <50>;
-                                       wakeup = <1>;
+                                       wakeup-source;
                                        linux,code = <152>;
                                        label = "RLOCK";
                                        gpios = <&iofpga_gpio0 2 0x4>;
                                };
                                button@4 {
                                        debounce_interval = <50>;
-                                       wakeup = <1>;
+                                       wakeup-source;
                                        linux,code = <115>;
                                        label = "VOL+";
                                        gpios = <&iofpga_gpio0 3 0x4>;
                                };
                                button@5 {
                                        debounce_interval = <50>;
-                                       wakeup = <1>;
+                                       wakeup-source;
                                        linux,code = <114>;
                                        label = "VOL-";
                                        gpios = <&iofpga_gpio0 4 0x4>;
                                };
                                button@6 {
                                        debounce_interval = <50>;
-                                       wakeup = <1>;
+                                       wakeup-source;
                                        linux,code = <99>;
                                        label = "NMI";
                                        gpios = <&iofpga_gpio0 5 0x4>;
index d18ee4259ee57e280166334a01bcba5fba80d2e0..06a15644be38439e63dfee78f59f2f720921c24e 100644 (file)
@@ -81,7 +81,7 @@
                };
 
                idle-states {
-                       entry-method = "arm,psci";
+                       entry-method = "psci";
 
                        CPU_SLEEP_0: cpu-sleep-0 {
                                compatible = "arm,idle-state";
index a712bea3bf2c1b7fe1ffc908fe3e6a070a4ae46f..cc093a482aa461f9bd62914e28fc94b1d693d8b6 100644 (file)
                };
 
                idle-states {
-                       entry-method = "arm,psci";
+                       entry-method = "psci";
 
                        cpu_sleep: cpu-sleep-0 {
                                compatible = "arm,idle-state";
index 2bb7009bdac721f96973b679a585e875425b73d4..a57601f9d17cdffb1122e2864ae5353273eb59ee 100644 (file)
@@ -43,9 +43,4 @@ static inline void ack_bad_irq(unsigned int irq)
        irq_err_count++;
 }
 
-/*
- * No arch-specific IRQ flags.
- */
-#define set_irq_flags(irq, flags)
-
 #endif /* __ASM_HARDIRQ_H */
index 7605e095217f7c2434594327ae4b3453cb758f42..9694f26545930bf5cf282cde42d41035914d89b7 100644 (file)
@@ -95,6 +95,7 @@
                         SCTLR_EL2_SA | SCTLR_EL2_I)
 
 /* TCR_EL2 Registers bits */
+#define TCR_EL2_RES1   ((1 << 31) | (1 << 23))
 #define TCR_EL2_TBI    (1 << 20)
 #define TCR_EL2_PS     (7 << 16)
 #define TCR_EL2_PS_40B (2 << 16)
 #define TCR_EL2_MASK   (TCR_EL2_TG0 | TCR_EL2_SH0 | \
                         TCR_EL2_ORGN0 | TCR_EL2_IRGN0 | TCR_EL2_T0SZ)
 
-#define TCR_EL2_FLAGS  (TCR_EL2_PS_40B)
+#define TCR_EL2_FLAGS  (TCR_EL2_RES1 | TCR_EL2_PS_40B)
 
 /* VTCR_EL2 Registers bits */
+#define VTCR_EL2_RES1          (1 << 31)
 #define VTCR_EL2_PS_MASK       (7 << 16)
 #define VTCR_EL2_TG0_MASK      (1 << 14)
 #define VTCR_EL2_TG0_4K                (0 << 14)
  */
 #define VTCR_EL2_FLAGS         (VTCR_EL2_TG0_64K | VTCR_EL2_SH0_INNER | \
                                 VTCR_EL2_ORGN0_WBWA | VTCR_EL2_IRGN0_WBWA | \
-                                VTCR_EL2_SL0_LVL1 | VTCR_EL2_T0SZ_40B)
+                                VTCR_EL2_SL0_LVL1 | VTCR_EL2_T0SZ_40B | \
+                                VTCR_EL2_RES1)
 #define VTTBR_X                (38 - VTCR_EL2_T0SZ_40B)
 #else
 /*
  */
 #define VTCR_EL2_FLAGS         (VTCR_EL2_TG0_4K | VTCR_EL2_SH0_INNER | \
                                 VTCR_EL2_ORGN0_WBWA | VTCR_EL2_IRGN0_WBWA | \
-                                VTCR_EL2_SL0_LVL1 | VTCR_EL2_T0SZ_40B)
+                                VTCR_EL2_SL0_LVL1 | VTCR_EL2_T0SZ_40B | \
+                                VTCR_EL2_RES1)
 #define VTTBR_X                (37 - VTCR_EL2_T0SZ_40B)
 #endif
 
 #define VTTBR_VMID_MASK          (UL(0xFF) << VTTBR_VMID_SHIFT)
 
 /* Hyp System Trap Register */
-#define HSTR_EL2_TTEE  (1 << 16)
 #define HSTR_EL2_T(x)  (1 << x)
 
 /* Hyp Coproccessor Trap Register Shifts */
index 67fa0de3d48324cc19a06871904f619189ed27da..5e377101f91948f9ee711bea3f7659c86010301c 100644 (file)
@@ -53,9 +53,7 @@
 #define        IFSR32_EL2      25      /* Instruction Fault Status Register */
 #define        FPEXC32_EL2     26      /* Floating-Point Exception Control Register */
 #define        DBGVCR32_EL2    27      /* Debug Vector Catch Register */
-#define        TEECR32_EL1     28      /* ThumbEE Configuration Register */
-#define        TEEHBR32_EL1    29      /* ThumbEE Handler Base Register */
-#define        NR_SYS_REGS     30
+#define        NR_SYS_REGS     28
 
 /* 32bit mapping */
 #define c0_MPIDR       (MPIDR_EL1 * 2) /* MultiProcessor ID Register */
index 415938dc45cff94600625963b71011882f3a3ae4..ed039688c221444e6e4526a0444eb5573d00609b 100644 (file)
 
 #define __KVM_HAVE_ARCH_INTC_INITIALIZED
 
-#if defined(CONFIG_KVM_ARM_MAX_VCPUS)
-#define KVM_MAX_VCPUS CONFIG_KVM_ARM_MAX_VCPUS
-#else
-#define KVM_MAX_VCPUS 0
-#endif
-
 #define KVM_USER_MEM_SLOTS 32
 #define KVM_PRIVATE_MEM_SLOTS 4
 #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
+#define KVM_HALT_POLL_NS_DEFAULT 500000
 
 #include <kvm/arm_vgic.h>
 #include <kvm/arm_arch_timer.h>
 
+#define KVM_MAX_VCPUS VGIC_V3_MAX_CPUS
+
 #define KVM_VCPU_MAX_FEATURES 3
 
 int __attribute_const__ kvm_target_cpu(void);
@@ -195,6 +192,7 @@ struct kvm_vm_stat {
 
 struct kvm_vcpu_stat {
        u32 halt_successful_poll;
+       u32 halt_attempted_poll;
        u32 halt_wakeup;
 };
 
index 6900b2d953717c721fb2318ef877428542baef17..26b066690593cd6304e81fdd24465a25ace2f396 100644 (file)
  * Software defined PTE bits definition.
  */
 #define PTE_VALID              (_AT(pteval_t, 1) << 0)
+#define PTE_WRITE              (PTE_DBM)                /* same as DBM (51) */
 #define PTE_DIRTY              (_AT(pteval_t, 1) << 55)
 #define PTE_SPECIAL            (_AT(pteval_t, 1) << 56)
-#ifdef CONFIG_ARM64_HW_AFDBM
-#define PTE_WRITE              (PTE_DBM)                /* same as DBM */
-#else
-#define PTE_WRITE              (_AT(pteval_t, 1) << 57)
-#endif
 #define PTE_PROT_NONE          (_AT(pteval_t, 1) << 58) /* only when !PTE_VALID */
 
 /*
@@ -83,7 +79,7 @@ extern void __pgd_error(const char *file, int line, unsigned long val);
 #define PAGE_S2                        __pgprot(PROT_DEFAULT | PTE_S2_MEMATTR(MT_S2_NORMAL) | PTE_S2_RDONLY)
 #define PAGE_S2_DEVICE         __pgprot(PROT_DEFAULT | PTE_S2_MEMATTR(MT_S2_DEVICE_nGnRE) | PTE_S2_RDONLY | PTE_UXN)
 
-#define PAGE_NONE              __pgprot(((_PAGE_DEFAULT) & ~PTE_TYPE_MASK) | PTE_PROT_NONE | PTE_PXN | PTE_UXN)
+#define PAGE_NONE              __pgprot(((_PAGE_DEFAULT) & ~PTE_VALID) | PTE_PROT_NONE | PTE_PXN | PTE_UXN)
 #define PAGE_SHARED            __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_WRITE)
 #define PAGE_SHARED_EXEC       __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_WRITE)
 #define PAGE_COPY              __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN)
@@ -146,7 +142,7 @@ extern struct page *empty_zero_page;
 #define pte_exec(pte)          (!(pte_val(pte) & PTE_UXN))
 
 #ifdef CONFIG_ARM64_HW_AFDBM
-#define pte_hw_dirty(pte)      (!(pte_val(pte) & PTE_RDONLY))
+#define pte_hw_dirty(pte)      (pte_write(pte) && !(pte_val(pte) & PTE_RDONLY))
 #else
 #define pte_hw_dirty(pte)      (0)
 #endif
@@ -238,7 +234,7 @@ extern void __sync_icache_dcache(pte_t pteval, unsigned long addr);
  * When hardware DBM is not present, the sofware PTE_DIRTY bit is updated via
  * the page fault mechanism. Checking the dirty status of a pte becomes:
  *
- *   PTE_DIRTY || !PTE_RDONLY
+ *   PTE_DIRTY || (PTE_WRITE && !PTE_RDONLY)
  */
 static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
                              pte_t *ptep, pte_t pte)
@@ -500,10 +496,10 @@ static inline pud_t *pud_offset(pgd_t *pgd, unsigned long addr)
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
        const pteval_t mask = PTE_USER | PTE_PXN | PTE_UXN | PTE_RDONLY |
-                             PTE_PROT_NONE | PTE_WRITE | PTE_TYPE_MASK;
+                             PTE_PROT_NONE | PTE_VALID | PTE_WRITE;
        /* preserve the hardware dirty information */
        if (pte_hw_dirty(pte))
-               newprot |= PTE_DIRTY;
+               pte = pte_mkdirty(pte);
        pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask);
        return pte;
 }
index 3bc498c250dc08b04f81abdde71e83f886454147..41e58fe3c041e9adcade0f113064ea42e87045ba 100644 (file)
@@ -44,7 +44,7 @@
 #define __ARM_NR_compat_cacheflush     (__ARM_NR_COMPAT_BASE+2)
 #define __ARM_NR_compat_set_tls                (__ARM_NR_COMPAT_BASE+5)
 
-#define __NR_compat_syscalls           388
+#define __NR_compat_syscalls           390
 #endif
 
 #define __ARCH_WANT_SYS_CLONE
index cef934a90f17ecec303a1dcd12133a962f27b9d1..5b925b761a2a8857a62720110076e062edd4d7f3 100644 (file)
@@ -797,3 +797,12 @@ __SYSCALL(__NR_memfd_create, sys_memfd_create)
 __SYSCALL(__NR_bpf, sys_bpf)
 #define __NR_execveat 387
 __SYSCALL(__NR_execveat, compat_sys_execveat)
+#define __NR_userfaultfd 388
+__SYSCALL(__NR_userfaultfd, sys_userfaultfd)
+#define __NR_membarrier 389
+__SYSCALL(__NR_membarrier, sys_membarrier)
+
+/*
+ * Please add new compat syscalls above this comment and update
+ * __NR_compat_syscalls in asm/unistd.h.
+ */
index 8d1e7236431b428490cfb95cb6bfbeba24143854..991bf5db2ca19aa19b617e4752d6fd65280b164b 100644 (file)
@@ -19,6 +19,9 @@
 /* Required for AArch32 compatibility. */
 #define SA_RESTORER    0x04000000
 
+#define MINSIGSTKSZ 5120
+#define SIGSTKSZ    16384
+
 #include <asm-generic/signal.h>
 
 #endif
index bcee7abac68ebb5bcbcde829039113e1e76d5a65..937f5e58a4d340a27234c76b5a84fedcf9aa6373 100644 (file)
@@ -284,21 +284,23 @@ static void register_insn_emulation_sysctl(struct ctl_table *table)
        __asm__ __volatile__(                                   \
        ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_HAS_PAN,    \
                    CONFIG_ARM64_PAN)                           \
-       "       mov             %w2, %w1\n"                     \
-       "0:     ldxr"B"         %w1, [%3]\n"                    \
-       "1:     stxr"B"         %w0, %w2, [%3]\n"               \
+       "0:     ldxr"B"         %w2, [%3]\n"                    \
+       "1:     stxr"B"         %w0, %w1, [%3]\n"               \
        "       cbz             %w0, 2f\n"                      \
        "       mov             %w0, %w4\n"                     \
+       "       b               3f\n"                           \
        "2:\n"                                                  \
+       "       mov             %w1, %w2\n"                     \
+       "3:\n"                                                  \
        "       .pushsection     .fixup,\"ax\"\n"               \
        "       .align          2\n"                            \
-       "3:     mov             %w0, %w5\n"                     \
-       "       b               2b\n"                           \
+       "4:     mov             %w0, %w5\n"                     \
+       "       b               3b\n"                           \
        "       .popsection"                                    \
        "       .pushsection     __ex_table,\"a\"\n"            \
        "       .align          3\n"                            \
-       "       .quad           0b, 3b\n"                       \
-       "       .quad           1b, 3b\n"                       \
+       "       .quad           0b, 4b\n"                       \
+       "       .quad           1b, 4b\n"                       \
        "       .popsection\n"                                  \
        ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN,    \
                CONFIG_ARM64_PAN)                               \
index 9b3b62ac9c244ba91b9f7020ac7fe0dbb141c5ec..253021ef2769078e69793288a8cc067aebb76d34 100644 (file)
@@ -134,7 +134,7 @@ static int os_lock_notify(struct notifier_block *self,
                                    unsigned long action, void *data)
 {
        int cpu = (unsigned long)data;
-       if (action == CPU_ONLINE)
+       if ((action & ~CPU_TASKS_FROZEN) == CPU_ONLINE)
                smp_call_function_single(cpu, clear_os_lock, NULL, 1);
        return NOTIFY_OK;
 }
@@ -201,7 +201,7 @@ void unregister_step_hook(struct step_hook *hook)
 }
 
 /*
- * Call registered single step handers
+ * Call registered single step handlers
  * There is no Syndrome info to check for determining the handler.
  * So we call all the registered handlers, until the right handler is
  * found which returns zero.
@@ -271,20 +271,21 @@ static int single_step_handler(unsigned long addr, unsigned int esr,
  * Use reader/writer locks instead of plain spinlock.
  */
 static LIST_HEAD(break_hook);
-static DEFINE_RWLOCK(break_hook_lock);
+static DEFINE_SPINLOCK(break_hook_lock);
 
 void register_break_hook(struct break_hook *hook)
 {
-       write_lock(&break_hook_lock);
-       list_add(&hook->node, &break_hook);
-       write_unlock(&break_hook_lock);
+       spin_lock(&break_hook_lock);
+       list_add_rcu(&hook->node, &break_hook);
+       spin_unlock(&break_hook_lock);
 }
 
 void unregister_break_hook(struct break_hook *hook)
 {
-       write_lock(&break_hook_lock);
-       list_del(&hook->node);
-       write_unlock(&break_hook_lock);
+       spin_lock(&break_hook_lock);
+       list_del_rcu(&hook->node);
+       spin_unlock(&break_hook_lock);
+       synchronize_rcu();
 }
 
 static int call_break_hook(struct pt_regs *regs, unsigned int esr)
@@ -292,11 +293,11 @@ static int call_break_hook(struct pt_regs *regs, unsigned int esr)
        struct break_hook *hook;
        int (*fn)(struct pt_regs *regs, unsigned int esr) = NULL;
 
-       read_lock(&break_hook_lock);
-       list_for_each_entry(hook, &break_hook, node)
+       rcu_read_lock();
+       list_for_each_entry_rcu(hook, &break_hook, node)
                if ((esr & hook->esr_mask) == hook->esr_val)
                        fn = hook->fn;
-       read_unlock(&break_hook_lock);
+       rcu_read_unlock();
 
        return fn ? fn(regs, esr) : DBG_HOOK_ERROR;
 }
index 816120ece6bcecfbcbc1c25be51324c5197b65cd..78dfbd34b6bffd2fa36312da89dc6ca43f036c3c 100644 (file)
@@ -25,10 +25,20 @@ efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table_arg,
        unsigned long kernel_size, kernel_memsize = 0;
        unsigned long nr_pages;
        void *old_image_addr = (void *)*image_addr;
+       unsigned long preferred_offset;
+
+       /*
+        * The preferred offset of the kernel Image is TEXT_OFFSET bytes beyond
+        * a 2 MB aligned base, which itself may be lower than dram_base, as
+        * long as the resulting offset equals or exceeds it.
+        */
+       preferred_offset = round_down(dram_base, SZ_2M) + TEXT_OFFSET;
+       if (preferred_offset < dram_base)
+               preferred_offset += SZ_2M;
 
        /* Relocate the image, if required. */
        kernel_size = _edata - _text;
-       if (*image_addr != (dram_base + TEXT_OFFSET)) {
+       if (*image_addr != preferred_offset) {
                kernel_memsize = kernel_size + (_end - _edata);
 
                /*
@@ -42,7 +52,7 @@ efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table_arg,
                 * Mustang), we can still place the kernel at the address
                 * 'dram_base + TEXT_OFFSET'.
                 */
-               *image_addr = *reserve_addr = dram_base + TEXT_OFFSET;
+               *image_addr = *reserve_addr = preferred_offset;
                nr_pages = round_up(kernel_memsize, EFI_ALLOC_ALIGN) /
                           EFI_PAGE_SIZE;
                status = efi_call_early(allocate_pages, EFI_ALLOCATE_ADDRESS,
index e8ca6eaedd0252e2056530d71d519f423931d323..13671a9cf0167057d583f1c2dddca54ee94658f8 100644 (file)
@@ -258,7 +258,8 @@ static bool __init efi_virtmap_init(void)
                 */
                if (!is_normal_ram(md))
                        prot = __pgprot(PROT_DEVICE_nGnRE);
-               else if (md->type == EFI_RUNTIME_SERVICES_CODE)
+               else if (md->type == EFI_RUNTIME_SERVICES_CODE ||
+                        !PAGE_ALIGNED(md->phys_addr))
                        prot = PAGE_KERNEL_EXEC;
                else
                        prot = PAGE_KERNEL;
index 08cafc518b9a57ad724530b9dbb144d50683c13f..0f03a8fe23144e777b3ead0a6ea18e038b5d1066 100644 (file)
@@ -178,6 +178,24 @@ ENTRY(ftrace_stub)
 ENDPROC(ftrace_stub)
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
+       /* save return value regs*/
+       .macro save_return_regs
+       sub sp, sp, #64
+       stp x0, x1, [sp]
+       stp x2, x3, [sp, #16]
+       stp x4, x5, [sp, #32]
+       stp x6, x7, [sp, #48]
+       .endm
+
+       /* restore return value regs*/
+       .macro restore_return_regs
+       ldp x0, x1, [sp]
+       ldp x2, x3, [sp, #16]
+       ldp x4, x5, [sp, #32]
+       ldp x6, x7, [sp, #48]
+       add sp, sp, #64
+       .endm
+
 /*
  * void ftrace_graph_caller(void)
  *
@@ -204,11 +222,11 @@ ENDPROC(ftrace_graph_caller)
  * only when CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST is enabled.
  */
 ENTRY(return_to_handler)
-       str     x0, [sp, #-16]!
+       save_return_regs
        mov     x0, x29                 //     parent's fp
        bl      ftrace_return_to_handler// addr = ftrace_return_to_hander(fp);
        mov     x30, x0                 // restore the original return address
-       ldr     x0, [sp], #16
+       restore_return_regs
        ret
 END(return_to_handler)
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
index a055be6125cf592d06e957df0b1125d409c9a5cf..90d09eddd5b27368e358efd44ab552db8330d39c 100644 (file)
@@ -523,6 +523,11 @@ CPU_LE(    movk    x0, #0x30d0, lsl #16    )       // Clear EE and E0E on LE systems
        msr     hstr_el2, xzr                   // Disable CP15 traps to EL2
 #endif
 
+       /* EL2 debug */
+       mrs     x0, pmcr_el0                    // Disable debug access traps
+       ubfx    x0, x0, #11, #5                 // to EL2 and allow access to
+       msr     mdcr_el2, x0                    // all PMU counters from EL1
+
        /* Stage-2 translation */
        msr     vttbr_el2, xzr
 
index c97040ecf838096069e1ebd0fdd50f2d0050b5ad..bba85c8f80373937ef9fe746e1a2ed4fc39f58ee 100644 (file)
@@ -872,7 +872,7 @@ static int hw_breakpoint_reset_notify(struct notifier_block *self,
                                                void *hcpu)
 {
        int cpu = (long)hcpu;
-       if (action == CPU_ONLINE)
+       if ((action & ~CPU_TASKS_FROZEN) == CPU_ONLINE)
                smp_call_function_single(cpu, hw_breakpoint_reset, NULL, 1);
        return NOTIFY_OK;
 }
index f341866aa810340e47aa9b7283b6b472ca2eae84..c08b9ad6f42931e8766d0186daa51a6cce8dbe39 100644 (file)
@@ -85,7 +85,7 @@ bool aarch64_insn_is_branch_imm(u32 insn)
                aarch64_insn_is_bcond(insn));
 }
 
-static DEFINE_SPINLOCK(patch_lock);
+static DEFINE_RAW_SPINLOCK(patch_lock);
 
 static void __kprobes *patch_map(void *addr, int fixmap)
 {
@@ -131,13 +131,13 @@ static int __kprobes __aarch64_insn_write(void *addr, u32 insn)
        unsigned long flags = 0;
        int ret;
 
-       spin_lock_irqsave(&patch_lock, flags);
+       raw_spin_lock_irqsave(&patch_lock, flags);
        waddr = patch_map(addr, FIX_TEXT_POKE0);
 
        ret = probe_kernel_write(waddr, &insn, AARCH64_INSN_SIZE);
 
        patch_unmap(FIX_TEXT_POKE0);
-       spin_unlock_irqrestore(&patch_lock, flags);
+       raw_spin_unlock_irqrestore(&patch_lock, flags);
 
        return ret;
 }
index 67bf4107f6efe8401e1df29ad471ff8aac8cb01d..876eb8df50bf3355ac8432a2ddf2a5c46810a5de 100644 (file)
@@ -332,12 +332,14 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
                        ovf = reloc_insn_imm(RELOC_OP_PREL, loc, val, 0, 21,
                                             AARCH64_INSN_IMM_ADR);
                        break;
+#ifndef CONFIG_ARM64_ERRATUM_843419
                case R_AARCH64_ADR_PREL_PG_HI21_NC:
                        overflow_check = false;
                case R_AARCH64_ADR_PREL_PG_HI21:
                        ovf = reloc_insn_imm(RELOC_OP_PAGE, loc, val, 12, 21,
                                             AARCH64_INSN_IMM_ADR);
                        break;
+#endif
                case R_AARCH64_ADD_ABS_LO12_NC:
                case R_AARCH64_LDST8_ABS_LO12_NC:
                        overflow_check = false;
index 6bab21f84a9ff38402e70345016ed50ae8e95e30..232247945b1c215c25fbfd708573fe3def5c68c5 100644 (file)
@@ -364,6 +364,8 @@ static void __init relocate_initrd(void)
                to_free = ram_end - orig_start;
 
        size = orig_end - orig_start;
+       if (!size)
+               return;
 
        /* initrd needs to be relocated completely inside linear mapping */
        new_start = memblock_find_in_range(0, PFN_PHYS(max_pfn),
index 948f0ad2de231b5e3f5efa62e204162cadf26503..71ef6dc89ae509cd299eab3f1959ffe4e8f96a33 100644 (file)
@@ -212,14 +212,32 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
 
 /*
  * VFP save/restore code.
+ *
+ * We have to be careful with endianness, since the fpsimd context-switch
+ * code operates on 128-bit (Q) register values whereas the compat ABI
+ * uses an array of 64-bit (D) registers. Consequently, we need to swap
+ * the two halves of each Q register when running on a big-endian CPU.
  */
+union __fpsimd_vreg {
+       __uint128_t     raw;
+       struct {
+#ifdef __AARCH64EB__
+               u64     hi;
+               u64     lo;
+#else
+               u64     lo;
+               u64     hi;
+#endif
+       };
+};
+
 static int compat_preserve_vfp_context(struct compat_vfp_sigframe __user *frame)
 {
        struct fpsimd_state *fpsimd = &current->thread.fpsimd_state;
        compat_ulong_t magic = VFP_MAGIC;
        compat_ulong_t size = VFP_STORAGE_SIZE;
        compat_ulong_t fpscr, fpexc;
-       int err = 0;
+       int i, err = 0;
 
        /*
         * Save the hardware registers to the fpsimd_state structure.
@@ -235,10 +253,15 @@ static int compat_preserve_vfp_context(struct compat_vfp_sigframe __user *frame)
        /*
         * Now copy the FP registers. Since the registers are packed,
         * we can copy the prefix we want (V0-V15) as it is.
-        * FIXME: Won't work if big endian.
         */
-       err |= __copy_to_user(&frame->ufp.fpregs, fpsimd->vregs,
-                             sizeof(frame->ufp.fpregs));
+       for (i = 0; i < ARRAY_SIZE(frame->ufp.fpregs); i += 2) {
+               union __fpsimd_vreg vreg = {
+                       .raw = fpsimd->vregs[i >> 1],
+               };
+
+               __put_user_error(vreg.lo, &frame->ufp.fpregs[i], err);
+               __put_user_error(vreg.hi, &frame->ufp.fpregs[i + 1], err);
+       }
 
        /* Create an AArch32 fpscr from the fpsr and the fpcr. */
        fpscr = (fpsimd->fpsr & VFP_FPSCR_STAT_MASK) |
@@ -263,7 +286,7 @@ static int compat_restore_vfp_context(struct compat_vfp_sigframe __user *frame)
        compat_ulong_t magic = VFP_MAGIC;
        compat_ulong_t size = VFP_STORAGE_SIZE;
        compat_ulong_t fpscr;
-       int err = 0;
+       int i, err = 0;
 
        __get_user_error(magic, &frame->magic, err);
        __get_user_error(size, &frame->size, err);
@@ -273,12 +296,14 @@ static int compat_restore_vfp_context(struct compat_vfp_sigframe __user *frame)
        if (magic != VFP_MAGIC || size != VFP_STORAGE_SIZE)
                return -EINVAL;
 
-       /*
-        * Copy the FP registers into the start of the fpsimd_state.
-        * FIXME: Won't work if big endian.
-        */
-       err |= __copy_from_user(fpsimd.vregs, frame->ufp.fpregs,
-                               sizeof(frame->ufp.fpregs));
+       /* Copy the FP registers into the start of the fpsimd_state. */
+       for (i = 0; i < ARRAY_SIZE(frame->ufp.fpregs); i += 2) {
+               union __fpsimd_vreg vreg;
+
+               __get_user_error(vreg.lo, &frame->ufp.fpregs[i], err);
+               __get_user_error(vreg.hi, &frame->ufp.fpregs[i + 1], err);
+               fpsimd.vregs[i >> 1] = vreg.raw;
+       }
 
        /* Extract the fpsr and the fpcr from the fpscr */
        __get_user_error(fpscr, &frame->ufp.fpscr, err);
index 407991bf79f5116eed6d5aa4aa2f1314ecabe0fc..ccb6078ed9f20fb55132deb48504df3a3134a784 100644 (file)
@@ -48,11 +48,7 @@ int notrace unwind_frame(struct stackframe *frame)
 
        frame->sp = fp + 0x10;
        frame->fp = *(unsigned long *)(fp);
-       /*
-        * -4 here because we care about the PC at time of bl,
-        * not where the return will go.
-        */
-       frame->pc = *(unsigned long *)(fp + 8) - 4;
+       frame->pc = *(unsigned long *)(fp + 8);
 
        return 0;
 }
index 8297d502217e13010bc891e7d68b5f7279ea62b9..44ca4143b013227ebf9eb40eafd721454ab45074 100644 (file)
@@ -80,17 +80,21 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
        if (ret == 0) {
                /*
                 * We are resuming from reset with TTBR0_EL1 set to the
-                * idmap to enable the MMU; restore the active_mm mappings in
-                * TTBR0_EL1 unless the active_mm == &init_mm, in which case
-                * the thread entered cpu_suspend with TTBR0_EL1 set to
-                * reserved TTBR0 page tables and should be restored as such.
+                * idmap to enable the MMU; set the TTBR0 to the reserved
+                * page tables to prevent speculative TLB allocations, flush
+                * the local tlb and set the default tcr_el1.t0sz so that
+                * the TTBR0 address space set-up is properly restored.
+                * If the current active_mm != &init_mm we entered cpu_suspend
+                * with mappings in TTBR0 that must be restored, so we switch
+                * them back to complete the address space configuration
+                * restoration before returning.
                 */
-               if (mm == &init_mm)
-                       cpu_set_reserved_ttbr0();
-               else
-                       cpu_switch_mm(mm->pgd, mm);
-
+               cpu_set_reserved_ttbr0();
                flush_tlb_all();
+               cpu_set_default_tcr_t0sz();
+
+               if (mm != &init_mm)
+                       cpu_switch_mm(mm->pgd, mm);
 
                /*
                 * Restore per-cpu offset before any kernel
index bfffe8f4bd53ef0ac9314acb79dbad197b953e53..5c7e920e486132c5257255ff843d81a6616670b1 100644 (file)
@@ -41,15 +41,4 @@ config KVM_ARM_HOST
        ---help---
          Provides host support for ARM processors.
 
-config KVM_ARM_MAX_VCPUS
-       int "Number maximum supported virtual CPUs per VM"
-       depends on KVM_ARM_HOST
-       default 4
-       help
-         Static number of max supported virtual CPUs per VM.
-
-         If you choose a high number, the vcpu structures will be quite
-         large, so only choose a reasonable number that you expect to
-         actually use.
-
 endif # VIRTUALIZATION
index 37c89ea2c572ed858c0425344b45e0897a89b74f..e5836138ec42a58841e7003bbb14f2b4a2126297 100644 (file)
        mrs     x5, ifsr32_el2
        stp     x4, x5, [x3]
 
-       skip_fpsimd_state x8, 3f
+       skip_fpsimd_state x8, 2f
        mrs     x6, fpexc32_el2
        str     x6, [x3, #16]
-3:
-       skip_debug_state x8, 2f
+2:
+       skip_debug_state x8, 1f
        mrs     x7, dbgvcr32_el2
        str     x7, [x3, #24]
-2:
-       skip_tee_state x8, 1f
-
-       add     x3, x2, #CPU_SYSREG_OFFSET(TEECR32_EL1)
-       mrs     x4, teecr32_el1
-       mrs     x5, teehbr32_el1
-       stp     x4, x5, [x3]
 1:
 .endm
 
        msr     dacr32_el2, x4
        msr     ifsr32_el2, x5
 
-       skip_debug_state x8, 2f
+       skip_debug_state x8, 1f
        ldr     x7, [x3, #24]
        msr     dbgvcr32_el2, x7
-2:
-       skip_tee_state x8, 1f
-
-       add     x3, x2, #CPU_SYSREG_OFFSET(TEECR32_EL1)
-       ldp     x4, x5, [x3]
-       msr     teecr32_el1, x4
-       msr     teehbr32_el1, x5
 1:
 .endm
 
@@ -570,8 +556,6 @@ alternative_endif
        mrs     x3, cntv_ctl_el0
        and     x3, x3, #3
        str     w3, [x0, #VCPU_TIMER_CNTV_CTL]
-       bic     x3, x3, #1              // Clear Enable
-       msr     cntv_ctl_el0, x3
 
        isb
 
@@ -579,6 +563,9 @@ alternative_endif
        str     x3, [x0, #VCPU_TIMER_CNTV_CVAL]
 
 1:
+       // Disable the virtual timer
+       msr     cntv_ctl_el0, xzr
+
        // Allow physical timer/counter access for the host
        mrs     x2, cnthctl_el2
        orr     x2, x2, #3
@@ -753,6 +740,9 @@ ENTRY(__kvm_vcpu_run)
        // Guest context
        add     x2, x0, #VCPU_CONTEXT
 
+       // We must restore the 32-bit state before the sysregs, thanks
+       // to Cortex-A57 erratum #852523.
+       restore_guest_32bit_state
        bl __restore_sysregs
 
        skip_debug_state x3, 1f
@@ -760,7 +750,6 @@ ENTRY(__kvm_vcpu_run)
        kern_hyp_va x3
        bl      __restore_debug
 1:
-       restore_guest_32bit_state
        restore_guest_regs
 
        // That's it, no more messing around.
index b41607d270ac83ebd1413a185753bf0b9e2af7f0..d03d3af17e7eef784d528479e2f4fed305ee5f75 100644 (file)
@@ -272,7 +272,7 @@ static int set_bvr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
 {
        __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_bvr[rd->reg];
 
-       if (copy_from_user(uaddr, r, KVM_REG_SIZE(reg->id)) != 0)
+       if (copy_from_user(r, uaddr, KVM_REG_SIZE(reg->id)) != 0)
                return -EFAULT;
        return 0;
 }
@@ -314,7 +314,7 @@ static int set_bcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
 {
        __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_bcr[rd->reg];
 
-       if (copy_from_user(uaddr, r, KVM_REG_SIZE(reg->id)) != 0)
+       if (copy_from_user(r, uaddr, KVM_REG_SIZE(reg->id)) != 0)
                return -EFAULT;
 
        return 0;
@@ -358,7 +358,7 @@ static int set_wvr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
 {
        __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_wvr[rd->reg];
 
-       if (copy_from_user(uaddr, r, KVM_REG_SIZE(reg->id)) != 0)
+       if (copy_from_user(r, uaddr, KVM_REG_SIZE(reg->id)) != 0)
                return -EFAULT;
        return 0;
 }
@@ -400,7 +400,7 @@ static int set_wcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
 {
        __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_wcr[rd->reg];
 
-       if (copy_from_user(uaddr, r, KVM_REG_SIZE(reg->id)) != 0)
+       if (copy_from_user(r, uaddr, KVM_REG_SIZE(reg->id)) != 0)
                return -EFAULT;
        return 0;
 }
@@ -539,13 +539,6 @@ static const struct sys_reg_desc sys_reg_descs[] = {
        { Op0(0b10), Op1(0b000), CRn(0b0111), CRm(0b1110), Op2(0b110),
          trap_dbgauthstatus_el1 },
 
-       /* TEECR32_EL1 */
-       { Op0(0b10), Op1(0b010), CRn(0b0000), CRm(0b0000), Op2(0b000),
-         NULL, reset_val, TEECR32_EL1, 0 },
-       /* TEEHBR32_EL1 */
-       { Op0(0b10), Op1(0b010), CRn(0b0001), CRm(0b0000), Op2(0b000),
-         NULL, reset_val, TEEHBR32_EL1, 0 },
-
        /* MDCCSR_EL1 */
        { Op0(0b10), Op1(0b011), CRn(0b0000), CRm(0b0001), Op2(0b000),
          trap_raz_wi },
index 0bcc4bc94b4ad3b4d72d735dc7e88a190c2e5cbe..99224dcebdc51d40cb2dff423280727ec44bacd3 100644 (file)
@@ -100,7 +100,7 @@ static void *__dma_alloc_coherent(struct device *dev, size_t size,
        if (IS_ENABLED(CONFIG_ZONE_DMA) &&
            dev->coherent_dma_mask <= DMA_BIT_MASK(32))
                flags |= GFP_DMA;
-       if (IS_ENABLED(CONFIG_DMA_CMA) && (flags & __GFP_WAIT)) {
+       if (dev_get_cma_area(dev) && (flags & __GFP_WAIT)) {
                struct page *page;
                void *addr;
 
index aba9ead1384c036a0d6a441c92ced63cfd7ed4ae..9fadf6d7039b721b072379b5af51abce726f5b92 100644 (file)
@@ -287,6 +287,7 @@ retry:
                         * starvation.
                         */
                        mm_flags &= ~FAULT_FLAG_ALLOW_RETRY;
+                       mm_flags |= FAULT_FLAG_TRIED;
                        goto retry;
                }
        }
index f61f2dd67464746c728474a7b5503dd7dfbdcb67..241b9b9729d821510fb2addde4b276e73e6185a7 100644 (file)
@@ -20,4 +20,5 @@ generic-y += sections.h
 generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += vga.h
+generic-y += word-at-a-time.h
 generic-y += xor.h
index d51ff8f1c541dd8cded2935f6890ce5c48dcb85e..96cabad68489fc888edfb807508abc62ec72d1ce 100644 (file)
@@ -144,7 +144,7 @@ static struct irq_chip eic_chip = {
        .irq_set_type   = eic_set_irq_type,
 };
 
-static void demux_eic_irq(unsigned int irq, struct irq_desc *desc)
+static void demux_eic_irq(struct irq_desc *desc)
 {
        struct eic *eic = irq_desc_get_handler_data(desc);
        unsigned long status, pending;
index 157a5e0e789f6744d62672dd0a03ca066d960079..4f61378c3453792af416dae65ffa1e9a8c70f4ff 100644 (file)
@@ -281,7 +281,7 @@ static struct irq_chip gpio_irqchip = {
        .irq_set_type   = gpio_irq_type,
 };
 
-static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+static void gpio_irq_handler(struct irq_desc *desc)
 {
        struct pio_device       *pio = irq_desc_get_chip_data(desc);
        unsigned                gpio_irq;
index 61cd1e786a142c440caa231a665349ed3d8f8e01..91d49c0a31185041055e627689ec09b2ab708bd1 100644 (file)
@@ -46,4 +46,5 @@ generic-y += types.h
 generic-y += ucontext.h
 generic-y += unaligned.h
 generic-y += user.h
+generic-y += word-at-a-time.h
 generic-y += xor.h
index 4b2a992794d77b187c657ad515d9db17bf4002ed..d2f90c72378eef684d04544ae401c41a047897a4 100644 (file)
@@ -60,7 +60,7 @@ extern void bfin_internal_mask_irq(unsigned int irq);
 extern void bfin_internal_unmask_irq(unsigned int irq);
 
 struct irq_desc;
-extern void bfin_demux_mac_status_irq(unsigned int, struct irq_desc *);
-extern void bfin_demux_gpio_irq(unsigned int, struct irq_desc *);
+extern void bfin_demux_mac_status_irq(struct irq_desc *);
+extern void bfin_demux_gpio_irq(struct irq_desc *);
 
 #endif
index 0ba25764b8c0472ccd01959b1300c9b2efe9fa34..052cde5ed2e403111fd8a1639dd29835177d7496 100644 (file)
@@ -107,7 +107,7 @@ asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
         * than crashing, do something sensible.
         */
        if (irq >= NR_IRQS)
-               handle_bad_irq(irq, &bad_irq_desc);
+               handle_bad_irq(&bad_irq_desc);
        else
                generic_handle_irq(irq);
 
index 14b2f74554dc6de142955b98482cbd8c4ff3e76b..a48baae4384dd3697e42eb07dcd95dbe197d7cab 100644 (file)
@@ -89,8 +89,7 @@ static struct irq_chip bf537_generic_error_irqchip = {
        .irq_unmask = bf537_generic_error_unmask_irq,
 };
 
-static void bf537_demux_error_irq(unsigned int int_err_irq,
-                                 struct irq_desc *inta_desc)
+static void bf537_demux_error_irq(struct irq_desc *inta_desc)
 {
        int irq = 0;
 
@@ -182,15 +181,12 @@ static struct irq_chip bf537_mac_rx_irqchip = {
        .irq_unmask = bf537_mac_rx_unmask_irq,
 };
 
-static void bf537_demux_mac_rx_irq(unsigned int __int_irq,
-                                  struct irq_desc *desc)
+static void bf537_demux_mac_rx_irq(struct irq_desc *desc)
 {
-       unsigned int int_irq = irq_desc_get_irq(desc);
-
        if (bfin_read_DMA1_IRQ_STATUS() & (DMA_DONE | DMA_ERR))
                bfin_handle_irq(IRQ_MAC_RX);
        else
-               bfin_demux_gpio_irq(int_irq, desc);
+               bfin_demux_gpio_irq(desc);
 }
 #endif
 
index a6d1b03cdf3693d2905e27ff113f6bbe34c7c056..e8d4d748d0fd759222bbc4d0e07f59dbb90d4a70 100644 (file)
@@ -656,8 +656,7 @@ static struct irq_chip bfin_mac_status_irqchip = {
        .irq_set_wake = bfin_mac_status_set_wake,
 };
 
-void bfin_demux_mac_status_irq(unsigned int int_err_irq,
-                              struct irq_desc *inta_desc)
+void bfin_demux_mac_status_irq(struct irq_desc *inta_desc)
 {
        int i, irq = 0;
        u32 status = bfin_read_EMAC_SYSTAT();
@@ -825,7 +824,7 @@ static void bfin_demux_gpio_block(unsigned int irq)
        }
 }
 
-void bfin_demux_gpio_irq(unsigned int __inta_irq, struct irq_desc *desc)
+void bfin_demux_gpio_irq(struct irq_desc *desc)
 {
        unsigned int inta_irq = irq_desc_get_irq(desc);
        unsigned int irq;
index f17c4dc6050c7d23ade635f749aa75eed8f0ac1d..945544ec603ee12408928c0abd4db19cfbc784d9 100644 (file)
@@ -59,4 +59,5 @@ generic-y += types.h
 generic-y += ucontext.h
 generic-y += user.h
 generic-y += vga.h
+generic-y += word-at-a-time.h
 generic-y += xor.h
index d487698e978a16411cf27b98ea02253ed84c4f44..ddcb45d7dfa7dcb4f16408ec8eaca6eeae03566d 100644 (file)
@@ -93,7 +93,7 @@ static struct irq_chip megamod_chip = {
        .irq_unmask     = unmask_megamod,
 };
 
-static void megamod_irq_cascade(unsigned int __irq, struct irq_desc *desc)
+static void megamod_irq_cascade(struct irq_desc *desc)
 {
        struct megamod_cascade_data *cascade;
        struct megamod_pic *pic;
index b7f68192d15b52cb4e6c34c78eac88a02fa971d5..1778805f63809d378a5cafb6c920b517ea753c7b 100644 (file)
@@ -43,4 +43,5 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += vga.h
+generic-y += word-at-a-time.h
 generic-y += xor.h
index 8e47b832cc7684af7a10d2a0680651cf5bf8cc0d..1fa084cf1a4398934889658b8b21f66154bf0ab6 100644 (file)
@@ -7,3 +7,4 @@ generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
+generic-y += word-at-a-time.h
index f9c86c475bbdafdbd37771c6834d7376b25673ec..f211839e2cae18f4d71999ec41ad8ed2a8ff1bca 100644 (file)
@@ -294,6 +294,8 @@ void pcibios_fixup_bus(struct pci_bus *bus)
        printk("### PCIBIOS_FIXUP_BUS(%d)\n",bus->number);
 #endif
 
+       pci_read_bridge_bases(bus);
+
        if (bus->number == 0) {
                struct pci_dev *dev;
                list_for_each_entry(dev, &bus->devices, bus_list) {
index 70e6ae1e700673e3acbd03452d22f57db9c1166d..373cb23301e30248bfd62f2a08c6529f93db0382 100644 (file)
@@ -73,4 +73,5 @@ generic-y += uaccess.h
 generic-y += ucontext.h
 generic-y += unaligned.h
 generic-y += vga.h
+generic-y += word-at-a-time.h
 generic-y += xor.h
index daee37bd09991a3edf732451587e59a8db001d54..db8ddabc6bd2819ba579c4c407a569e2232daa51 100644 (file)
@@ -58,4 +58,5 @@ generic-y += types.h
 generic-y += ucontext.h
 generic-y += unaligned.h
 generic-y += vga.h
+generic-y += word-at-a-time.h
 generic-y += xor.h
index 9de3ba12f6b97c0f8722e2f929c70fbae429fd34..502a91d8dbbd80df039d9a111de04c1caadf0e3c 100644 (file)
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += vtime.h
+generic-y += word-at-a-time.h
index 95c39b95e97e24f1ed3d7a58cf56dbbefc2ff419..db73390568c8dd873fc045cd35773714bd35f8e1 100644 (file)
@@ -11,7 +11,7 @@
 
 
 
-#define NR_syscalls                    319 /* length of syscall table */
+#define NR_syscalls                    322 /* length of syscall table */
 
 /*
  * The following defines stop scripts/checksyscalls.sh from complaining about
index 461079560c78728848b7631de5efbe700d146620..9038726e7d26777bf8f704f101ff86090e4d5059 100644 (file)
 #define __NR_memfd_create              1340
 #define __NR_bpf                       1341
 #define __NR_execveat                  1342
+#define __NR_userfaultfd               1343
+#define __NR_membarrier                        1344
+#define __NR_kcmp                      1345
 
 #endif /* _UAPI_ASM_IA64_UNISTD_H */
index ae0de7bf55257682dc11a1cc1fa31bc6cffa3112..dcd97f84d065435a8eca5c041f33bb67c3912797 100644 (file)
@@ -1768,5 +1768,8 @@ sys_call_table:
        data8 sys_memfd_create                  // 1340
        data8 sys_bpf
        data8 sys_execveat
+       data8 sys_userfaultfd
+       data8 sys_membarrier
+       data8 sys_kcmp                          // 1345
 
        .org sys_call_table + 8*NR_syscalls     // guard against failures to increase NR_syscalls
index d89b6013c9412c7f2ef5d72a3a5f9710f7544d3e..7cc3be9fa7c65a0dd700dfd30c04cc7be822922d 100644 (file)
@@ -533,9 +533,10 @@ void pcibios_fixup_bus(struct pci_bus *b)
 {
        struct pci_dev *dev;
 
-       if (b->self)
+       if (b->self) {
+               pci_read_bridge_bases(b);
                pcibios_fixup_bridge_resources(b->self);
-
+       }
        list_for_each_entry(dev, &b->devices, bus_list)
                pcibios_fixup_device_resources(dev);
        platform_pci_fixup_bus(b);
index e0eb704ca1fa93755d678e82c2336c8e188a34f0..fd104bd221ced1dff2c9485bdcb1be520171df7f 100644 (file)
@@ -9,3 +9,4 @@ generic-y += module.h
 generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
+generic-y += word-at-a-time.h
index 47b5f90002abe3c69bbc66ffee7a82f5cee4f6cb..7ff739e9489688a1bd81cd48bfa6ac49104ac5d9 100644 (file)
@@ -46,7 +46,7 @@ static struct irq_chip amiga_irq_chip = {
  * The builtin Amiga hardware interrupt handlers.
  */
 
-static void ami_int1(unsigned int irq, struct irq_desc *desc)
+static void ami_int1(struct irq_desc *desc)
 {
        unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
 
@@ -69,7 +69,7 @@ static void ami_int1(unsigned int irq, struct irq_desc *desc)
        }
 }
 
-static void ami_int3(unsigned int irq, struct irq_desc *desc)
+static void ami_int3(struct irq_desc *desc)
 {
        unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
 
@@ -92,7 +92,7 @@ static void ami_int3(unsigned int irq, struct irq_desc *desc)
        }
 }
 
-static void ami_int4(unsigned int irq, struct irq_desc *desc)
+static void ami_int4(struct irq_desc *desc)
 {
        unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
 
@@ -121,7 +121,7 @@ static void ami_int4(unsigned int irq, struct irq_desc *desc)
        }
 }
 
-static void ami_int5(unsigned int irq, struct irq_desc *desc)
+static void ami_int5(struct irq_desc *desc)
 {
        unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
 
index 47371de60427bd61b4d8c0f6abb6f5de95978c80..b0a19e207a636cba22f64ab154a765e7e9b03b1e 100644 (file)
@@ -143,12 +143,10 @@ static int intc_irq_set_type(struct irq_data *d, unsigned int type)
  * We need to be careful with the masking/acking due to the side effects
  * of masking an interrupt.
  */
-static void intc_external_irq(unsigned int __irq, struct irq_desc *desc)
+static void intc_external_irq(struct irq_desc *desc)
 {
-       unsigned int irq = irq_desc_get_irq(desc);
-
        irq_desc_get_chip(desc)->irq_ack(&desc->irq_data);
-       handle_simple_irq(irq, desc);
+       handle_simple_irq(desc);
 }
 
 static struct irq_chip intc_irq_chip = {
index 0b6b40d37b95b5acd2f0561a82f12b3859b35880..5b4ec541ba7c99936d8f5072dc5716a778751235 100644 (file)
@@ -10,6 +10,7 @@ CONFIG_LOG_BUF_SHIFT=16
 # CONFIG_PID_NS is not set
 # CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_USERFAULTFD=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
@@ -57,7 +58,6 @@ CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_NET_IPVTI=m
 CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE_CORE=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
@@ -67,10 +67,12 @@ CONFIG_INET_XFRM_MODE_BEET=m
 # CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=m
 CONFIG_INET_UDP_DIAG=m
+CONFIG_IPV6=m
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_ILA=m
 CONFIG_IPV6_VTI=m
 CONFIG_IPV6_GRE=m
 CONFIG_NETFILTER=y
@@ -179,6 +181,7 @@ CONFIG_IP_SET_HASH_NETIFACE=m
 CONFIG_IP_SET_LIST_SET=m
 CONFIG_NF_CONNTRACK_IPV4=m
 CONFIG_NFT_CHAIN_ROUTE_IPV4=m
+CONFIG_NFT_DUP_IPV4=m
 CONFIG_NF_TABLES_ARP=m
 CONFIG_NF_LOG_ARP=m
 CONFIG_NFT_CHAIN_NAT_IPV4=m
@@ -206,6 +209,7 @@ CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
 CONFIG_NFT_CHAIN_ROUTE_IPV6=m
+CONFIG_NFT_DUP_IPV6=m
 CONFIG_NFT_CHAIN_NAT_IPV6=m
 CONFIG_NFT_MASQ_IPV6=m
 CONFIG_NFT_REDIR_IPV6=m
@@ -271,6 +275,7 @@ CONFIG_NETLINK_DIAG=m
 CONFIG_MPLS=y
 CONFIG_NET_MPLS_GSO=m
 CONFIG_MPLS_ROUTING=m
+CONFIG_MPLS_IPTUNNEL=m
 # CONFIG_WIRELESS is not set
 # CONFIG_UEVENT_HELPER is not set
 CONFIG_DEVTMPFS=y
@@ -370,6 +375,7 @@ CONFIG_ZORRO8390=y
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_SMSC is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
 # CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PPP=m
@@ -537,6 +543,7 @@ CONFIG_TEST_USER_COPY=m
 CONFIG_TEST_BPF=m
 CONFIG_TEST_FIRMWARE=m
 CONFIG_TEST_UDELAY=m
+CONFIG_TEST_STATIC_KEYS=m
 CONFIG_EARLY_PRINTK=y
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_CRYPTO_RSA=m
index eeb3a8991fc411e952cd6a20b3e44602b80f38e0..6e5198e2c124f89b86d6b5267280f5596448cc0a 100644 (file)
@@ -10,6 +10,7 @@ CONFIG_LOG_BUF_SHIFT=16
 # CONFIG_PID_NS is not set
 # CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_USERFAULTFD=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
@@ -55,7 +56,6 @@ CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_NET_IPVTI=m
 CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE_CORE=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
@@ -65,10 +65,12 @@ CONFIG_INET_XFRM_MODE_BEET=m
 # CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=m
 CONFIG_INET_UDP_DIAG=m
+CONFIG_IPV6=m
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_ILA=m
 CONFIG_IPV6_VTI=m
 CONFIG_IPV6_GRE=m
 CONFIG_NETFILTER=y
@@ -177,6 +179,7 @@ CONFIG_IP_SET_HASH_NETIFACE=m
 CONFIG_IP_SET_LIST_SET=m
 CONFIG_NF_CONNTRACK_IPV4=m
 CONFIG_NFT_CHAIN_ROUTE_IPV4=m
+CONFIG_NFT_DUP_IPV4=m
 CONFIG_NF_TABLES_ARP=m
 CONFIG_NF_LOG_ARP=m
 CONFIG_NFT_CHAIN_NAT_IPV4=m
@@ -204,6 +207,7 @@ CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
 CONFIG_NFT_CHAIN_ROUTE_IPV6=m
+CONFIG_NFT_DUP_IPV6=m
 CONFIG_NFT_CHAIN_NAT_IPV6=m
 CONFIG_NFT_MASQ_IPV6=m
 CONFIG_NFT_REDIR_IPV6=m
@@ -269,6 +273,7 @@ CONFIG_NETLINK_DIAG=m
 CONFIG_MPLS=y
 CONFIG_NET_MPLS_GSO=m
 CONFIG_MPLS_ROUTING=m
+CONFIG_MPLS_IPTUNNEL=m
 # CONFIG_WIRELESS is not set
 # CONFIG_UEVENT_HELPER is not set
 CONFIG_DEVTMPFS=y
@@ -344,6 +349,7 @@ CONFIG_VETH=m
 # CONFIG_NET_VENDOR_SAMSUNG is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
 # CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PPP=m
@@ -495,6 +501,7 @@ CONFIG_TEST_USER_COPY=m
 CONFIG_TEST_BPF=m
 CONFIG_TEST_FIRMWARE=m
 CONFIG_TEST_UDELAY=m
+CONFIG_TEST_STATIC_KEYS=m
 CONFIG_EARLY_PRINTK=y
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_CRYPTO_RSA=m
index 3a7006654ce97c9df5bd521d66af5c29c61171fb..f75600b0ca23f78ec028948babb81b5b2c02b3ed 100644 (file)
@@ -10,6 +10,7 @@ CONFIG_LOG_BUF_SHIFT=16
 # CONFIG_PID_NS is not set
 # CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_USERFAULTFD=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
@@ -55,7 +56,6 @@ CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_NET_IPVTI=m
 CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE_CORE=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
@@ -65,10 +65,12 @@ CONFIG_INET_XFRM_MODE_BEET=m
 # CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=m
 CONFIG_INET_UDP_DIAG=m
+CONFIG_IPV6=m
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_ILA=m
 CONFIG_IPV6_VTI=m
 CONFIG_IPV6_GRE=m
 CONFIG_NETFILTER=y
@@ -177,6 +179,7 @@ CONFIG_IP_SET_HASH_NETIFACE=m
 CONFIG_IP_SET_LIST_SET=m
 CONFIG_NF_CONNTRACK_IPV4=m
 CONFIG_NFT_CHAIN_ROUTE_IPV4=m
+CONFIG_NFT_DUP_IPV4=m
 CONFIG_NF_TABLES_ARP=m
 CONFIG_NF_LOG_ARP=m
 CONFIG_NFT_CHAIN_NAT_IPV4=m
@@ -204,6 +207,7 @@ CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
 CONFIG_NFT_CHAIN_ROUTE_IPV6=m
+CONFIG_NFT_DUP_IPV6=m
 CONFIG_NFT_CHAIN_NAT_IPV6=m
 CONFIG_NFT_MASQ_IPV6=m
 CONFIG_NFT_REDIR_IPV6=m
@@ -269,6 +273,7 @@ CONFIG_NETLINK_DIAG=m
 CONFIG_MPLS=y
 CONFIG_NET_MPLS_GSO=m
 CONFIG_MPLS_ROUTING=m
+CONFIG_MPLS_IPTUNNEL=m
 # CONFIG_WIRELESS is not set
 # CONFIG_UEVENT_HELPER is not set
 CONFIG_DEVTMPFS=y
@@ -355,6 +360,7 @@ CONFIG_NE2000=y
 # CONFIG_NET_VENDOR_SEEQ is not set
 CONFIG_SMC91X=y
 # CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
 # CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PPP=m
@@ -517,6 +523,7 @@ CONFIG_TEST_USER_COPY=m
 CONFIG_TEST_BPF=m
 CONFIG_TEST_FIRMWARE=m
 CONFIG_TEST_UDELAY=m
+CONFIG_TEST_STATIC_KEYS=m
 CONFIG_EARLY_PRINTK=y
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_CRYPTO_RSA=m
index 0586b323a673791fff0661eb5804347bc7ad16fb..a42d91c389a6fbba1c2c8f27069acb53332dd56f 100644 (file)
@@ -10,6 +10,7 @@ CONFIG_LOG_BUF_SHIFT=16
 # CONFIG_PID_NS is not set
 # CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_USERFAULTFD=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
@@ -53,7 +54,6 @@ CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_NET_IPVTI=m
 CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE_CORE=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
@@ -63,10 +63,12 @@ CONFIG_INET_XFRM_MODE_BEET=m
 # CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=m
 CONFIG_INET_UDP_DIAG=m
+CONFIG_IPV6=m
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_ILA=m
 CONFIG_IPV6_VTI=m
 CONFIG_IPV6_GRE=m
 CONFIG_NETFILTER=y
@@ -175,6 +177,7 @@ CONFIG_IP_SET_HASH_NETIFACE=m
 CONFIG_IP_SET_LIST_SET=m
 CONFIG_NF_CONNTRACK_IPV4=m
 CONFIG_NFT_CHAIN_ROUTE_IPV4=m
+CONFIG_NFT_DUP_IPV4=m
 CONFIG_NF_TABLES_ARP=m
 CONFIG_NF_LOG_ARP=m
 CONFIG_NFT_CHAIN_NAT_IPV4=m
@@ -202,6 +205,7 @@ CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
 CONFIG_NFT_CHAIN_ROUTE_IPV6=m
+CONFIG_NFT_DUP_IPV6=m
 CONFIG_NFT_CHAIN_NAT_IPV6=m
 CONFIG_NFT_MASQ_IPV6=m
 CONFIG_NFT_REDIR_IPV6=m
@@ -267,6 +271,7 @@ CONFIG_NETLINK_DIAG=m
 CONFIG_MPLS=y
 CONFIG_NET_MPLS_GSO=m
 CONFIG_MPLS_ROUTING=m
+CONFIG_MPLS_IPTUNNEL=m
 # CONFIG_WIRELESS is not set
 # CONFIG_UEVENT_HELPER is not set
 CONFIG_DEVTMPFS=y
@@ -343,6 +348,7 @@ CONFIG_BVME6000_NET=y
 # CONFIG_NET_VENDOR_SAMSUNG is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
 # CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PPP=m
@@ -488,6 +494,7 @@ CONFIG_TEST_USER_COPY=m
 CONFIG_TEST_BPF=m
 CONFIG_TEST_FIRMWARE=m
 CONFIG_TEST_UDELAY=m
+CONFIG_TEST_STATIC_KEYS=m
 CONFIG_EARLY_PRINTK=y
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_CRYPTO_RSA=m
index ad1dbce07aa4b532fdb49fe515db2f2a19c37aa7..77f4a11083e9964050022f4ff22625b69b8672dd 100644 (file)
@@ -10,6 +10,7 @@ CONFIG_LOG_BUF_SHIFT=16
 # CONFIG_PID_NS is not set
 # CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_USERFAULTFD=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
@@ -55,7 +56,6 @@ CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_NET_IPVTI=m
 CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE_CORE=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
@@ -65,10 +65,12 @@ CONFIG_INET_XFRM_MODE_BEET=m
 # CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=m
 CONFIG_INET_UDP_DIAG=m
+CONFIG_IPV6=m
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_ILA=m
 CONFIG_IPV6_VTI=m
 CONFIG_IPV6_GRE=m
 CONFIG_NETFILTER=y
@@ -177,6 +179,7 @@ CONFIG_IP_SET_HASH_NETIFACE=m
 CONFIG_IP_SET_LIST_SET=m
 CONFIG_NF_CONNTRACK_IPV4=m
 CONFIG_NFT_CHAIN_ROUTE_IPV4=m
+CONFIG_NFT_DUP_IPV4=m
 CONFIG_NF_TABLES_ARP=m
 CONFIG_NF_LOG_ARP=m
 CONFIG_NFT_CHAIN_NAT_IPV4=m
@@ -204,6 +207,7 @@ CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
 CONFIG_NFT_CHAIN_ROUTE_IPV6=m
+CONFIG_NFT_DUP_IPV6=m
 CONFIG_NFT_CHAIN_NAT_IPV6=m
 CONFIG_NFT_MASQ_IPV6=m
 CONFIG_NFT_REDIR_IPV6=m
@@ -269,6 +273,7 @@ CONFIG_NETLINK_DIAG=m
 CONFIG_MPLS=y
 CONFIG_NET_MPLS_GSO=m
 CONFIG_MPLS_ROUTING=m
+CONFIG_MPLS_IPTUNNEL=m
 # CONFIG_WIRELESS is not set
 # CONFIG_UEVENT_HELPER is not set
 CONFIG_DEVTMPFS=y
@@ -345,6 +350,7 @@ CONFIG_HPLANCE=y
 # CONFIG_NET_VENDOR_SAMSUNG is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
 # CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PPP=m
@@ -497,6 +503,7 @@ CONFIG_TEST_USER_COPY=m
 CONFIG_TEST_BPF=m
 CONFIG_TEST_FIRMWARE=m
 CONFIG_TEST_UDELAY=m
+CONFIG_TEST_STATIC_KEYS=m
 CONFIG_EARLY_PRINTK=y
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_CRYPTO_RSA=m
index b44acacaecf41f43bae326e63318c3c8c7e7d0f8..5a329f77329b155ed5a4dc0f06ca6973c82aae94 100644 (file)
@@ -10,6 +10,7 @@ CONFIG_LOG_BUF_SHIFT=16
 # CONFIG_PID_NS is not set
 # CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_USERFAULTFD=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
@@ -54,7 +55,6 @@ CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_NET_IPVTI=m
 CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE_CORE=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
@@ -64,10 +64,12 @@ CONFIG_INET_XFRM_MODE_BEET=m
 # CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=m
 CONFIG_INET_UDP_DIAG=m
+CONFIG_IPV6=m
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_ILA=m
 CONFIG_IPV6_VTI=m
 CONFIG_IPV6_GRE=m
 CONFIG_NETFILTER=y
@@ -176,6 +178,7 @@ CONFIG_IP_SET_HASH_NETIFACE=m
 CONFIG_IP_SET_LIST_SET=m
 CONFIG_NF_CONNTRACK_IPV4=m
 CONFIG_NFT_CHAIN_ROUTE_IPV4=m
+CONFIG_NFT_DUP_IPV4=m
 CONFIG_NF_TABLES_ARP=m
 CONFIG_NF_LOG_ARP=m
 CONFIG_NFT_CHAIN_NAT_IPV4=m
@@ -203,6 +206,7 @@ CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
 CONFIG_NFT_CHAIN_ROUTE_IPV6=m
+CONFIG_NFT_DUP_IPV6=m
 CONFIG_NFT_CHAIN_NAT_IPV6=m
 CONFIG_NFT_MASQ_IPV6=m
 CONFIG_NFT_REDIR_IPV6=m
@@ -271,6 +275,7 @@ CONFIG_NETLINK_DIAG=m
 CONFIG_MPLS=y
 CONFIG_NET_MPLS_GSO=m
 CONFIG_MPLS_ROUTING=m
+CONFIG_MPLS_IPTUNNEL=m
 # CONFIG_WIRELESS is not set
 # CONFIG_UEVENT_HELPER is not set
 CONFIG_DEVTMPFS=y
@@ -364,6 +369,7 @@ CONFIG_MAC8390=y
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_SMSC is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
 # CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PPP=m
@@ -519,6 +525,7 @@ CONFIG_TEST_USER_COPY=m
 CONFIG_TEST_BPF=m
 CONFIG_TEST_FIRMWARE=m
 CONFIG_TEST_UDELAY=m
+CONFIG_TEST_STATIC_KEYS=m
 CONFIG_EARLY_PRINTK=y
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_CRYPTO_RSA=m
index 8afca3753db1f8f52245f2b4265c35f74268ae5e..83c80d2030ec96aa4740615101422e1fca1884e5 100644 (file)
@@ -10,6 +10,7 @@ CONFIG_LOG_BUF_SHIFT=16
 # CONFIG_PID_NS is not set
 # CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_USERFAULTFD=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
@@ -64,7 +65,6 @@ CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_NET_IPVTI=m
 CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE_CORE=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
@@ -74,10 +74,12 @@ CONFIG_INET_XFRM_MODE_BEET=m
 # CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=m
 CONFIG_INET_UDP_DIAG=m
+CONFIG_IPV6=m
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_ILA=m
 CONFIG_IPV6_VTI=m
 CONFIG_IPV6_GRE=m
 CONFIG_NETFILTER=y
@@ -186,6 +188,7 @@ CONFIG_IP_SET_HASH_NETIFACE=m
 CONFIG_IP_SET_LIST_SET=m
 CONFIG_NF_CONNTRACK_IPV4=m
 CONFIG_NFT_CHAIN_ROUTE_IPV4=m
+CONFIG_NFT_DUP_IPV4=m
 CONFIG_NF_TABLES_ARP=m
 CONFIG_NF_LOG_ARP=m
 CONFIG_NFT_CHAIN_NAT_IPV4=m
@@ -213,6 +216,7 @@ CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
 CONFIG_NFT_CHAIN_ROUTE_IPV6=m
+CONFIG_NFT_DUP_IPV6=m
 CONFIG_NFT_CHAIN_NAT_IPV6=m
 CONFIG_NFT_MASQ_IPV6=m
 CONFIG_NFT_REDIR_IPV6=m
@@ -281,6 +285,7 @@ CONFIG_NETLINK_DIAG=m
 CONFIG_MPLS=y
 CONFIG_NET_MPLS_GSO=m
 CONFIG_MPLS_ROUTING=m
+CONFIG_MPLS_IPTUNNEL=m
 # CONFIG_WIRELESS is not set
 # CONFIG_UEVENT_HELPER is not set
 CONFIG_DEVTMPFS=y
@@ -410,6 +415,7 @@ CONFIG_ZORRO8390=y
 # CONFIG_NET_VENDOR_SEEQ is not set
 CONFIG_SMC91X=y
 # CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
 # CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PLIP=m
@@ -599,6 +605,7 @@ CONFIG_TEST_USER_COPY=m
 CONFIG_TEST_BPF=m
 CONFIG_TEST_FIRMWARE=m
 CONFIG_TEST_UDELAY=m
+CONFIG_TEST_STATIC_KEYS=m
 CONFIG_EARLY_PRINTK=y
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_CRYPTO_RSA=m
index ef00875994d9ac34191f2bd6a572d9c44118ef4d..6cb42c3bf5a280d1a537d515396a463049d4a250 100644 (file)
@@ -10,6 +10,7 @@ CONFIG_LOG_BUF_SHIFT=16
 # CONFIG_PID_NS is not set
 # CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_USERFAULTFD=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
@@ -52,7 +53,6 @@ CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_NET_IPVTI=m
 CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE_CORE=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
@@ -62,10 +62,12 @@ CONFIG_INET_XFRM_MODE_BEET=m
 # CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=m
 CONFIG_INET_UDP_DIAG=m
+CONFIG_IPV6=m
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_ILA=m
 CONFIG_IPV6_VTI=m
 CONFIG_IPV6_GRE=m
 CONFIG_NETFILTER=y
@@ -174,6 +176,7 @@ CONFIG_IP_SET_HASH_NETIFACE=m
 CONFIG_IP_SET_LIST_SET=m
 CONFIG_NF_CONNTRACK_IPV4=m
 CONFIG_NFT_CHAIN_ROUTE_IPV4=m
+CONFIG_NFT_DUP_IPV4=m
 CONFIG_NF_TABLES_ARP=m
 CONFIG_NF_LOG_ARP=m
 CONFIG_NFT_CHAIN_NAT_IPV4=m
@@ -201,6 +204,7 @@ CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
 CONFIG_NFT_CHAIN_ROUTE_IPV6=m
+CONFIG_NFT_DUP_IPV6=m
 CONFIG_NFT_CHAIN_NAT_IPV6=m
 CONFIG_NFT_MASQ_IPV6=m
 CONFIG_NFT_REDIR_IPV6=m
@@ -266,6 +270,7 @@ CONFIG_NETLINK_DIAG=m
 CONFIG_MPLS=y
 CONFIG_NET_MPLS_GSO=m
 CONFIG_MPLS_ROUTING=m
+CONFIG_MPLS_IPTUNNEL=m
 # CONFIG_WIRELESS is not set
 # CONFIG_UEVENT_HELPER is not set
 CONFIG_DEVTMPFS=y
@@ -343,6 +348,7 @@ CONFIG_MVME147_NET=y
 # CONFIG_NET_VENDOR_SAMSUNG is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
 # CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PPP=m
@@ -488,6 +494,7 @@ CONFIG_TEST_USER_COPY=m
 CONFIG_TEST_BPF=m
 CONFIG_TEST_FIRMWARE=m
 CONFIG_TEST_UDELAY=m
+CONFIG_TEST_STATIC_KEYS=m
 CONFIG_EARLY_PRINTK=y
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_CRYPTO_RSA=m
index 387c2bd90ff1490a8a1c1fcb08a11753c8b2b6b1..c7508c30330c43ee32c0f75d7c7c8112f16cdc35 100644 (file)
@@ -10,6 +10,7 @@ CONFIG_LOG_BUF_SHIFT=16
 # CONFIG_PID_NS is not set
 # CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_USERFAULTFD=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
@@ -53,7 +54,6 @@ CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_NET_IPVTI=m
 CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE_CORE=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
@@ -63,10 +63,12 @@ CONFIG_INET_XFRM_MODE_BEET=m
 # CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=m
 CONFIG_INET_UDP_DIAG=m
+CONFIG_IPV6=m
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_ILA=m
 CONFIG_IPV6_VTI=m
 CONFIG_IPV6_GRE=m
 CONFIG_NETFILTER=y
@@ -175,6 +177,7 @@ CONFIG_IP_SET_HASH_NETIFACE=m
 CONFIG_IP_SET_LIST_SET=m
 CONFIG_NF_CONNTRACK_IPV4=m
 CONFIG_NFT_CHAIN_ROUTE_IPV4=m
+CONFIG_NFT_DUP_IPV4=m
 CONFIG_NF_TABLES_ARP=m
 CONFIG_NF_LOG_ARP=m
 CONFIG_NFT_CHAIN_NAT_IPV4=m
@@ -202,6 +205,7 @@ CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
 CONFIG_NFT_CHAIN_ROUTE_IPV6=m
+CONFIG_NFT_DUP_IPV6=m
 CONFIG_NFT_CHAIN_NAT_IPV6=m
 CONFIG_NFT_MASQ_IPV6=m
 CONFIG_NFT_REDIR_IPV6=m
@@ -267,6 +271,7 @@ CONFIG_NETLINK_DIAG=m
 CONFIG_MPLS=y
 CONFIG_NET_MPLS_GSO=m
 CONFIG_MPLS_ROUTING=m
+CONFIG_MPLS_IPTUNNEL=m
 # CONFIG_WIRELESS is not set
 # CONFIG_UEVENT_HELPER is not set
 CONFIG_DEVTMPFS=y
@@ -343,6 +348,7 @@ CONFIG_MVME16x_NET=y
 # CONFIG_NET_VENDOR_SAMSUNG is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
 # CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PPP=m
@@ -488,6 +494,7 @@ CONFIG_TEST_USER_COPY=m
 CONFIG_TEST_BPF=m
 CONFIG_TEST_FIRMWARE=m
 CONFIG_TEST_UDELAY=m
+CONFIG_TEST_STATIC_KEYS=m
 CONFIG_EARLY_PRINTK=y
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_CRYPTO_RSA=m
index 35355c1bc714000d1e3d44b5a429b97fabeac84a..64b71664a3036aa2827984f34005fc2cd044de44 100644 (file)
@@ -10,6 +10,7 @@ CONFIG_LOG_BUF_SHIFT=16
 # CONFIG_PID_NS is not set
 # CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_USERFAULTFD=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
@@ -53,7 +54,6 @@ CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_NET_IPVTI=m
 CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE_CORE=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
@@ -63,10 +63,12 @@ CONFIG_INET_XFRM_MODE_BEET=m
 # CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=m
 CONFIG_INET_UDP_DIAG=m
+CONFIG_IPV6=m
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_ILA=m
 CONFIG_IPV6_VTI=m
 CONFIG_IPV6_GRE=m
 CONFIG_NETFILTER=y
@@ -175,6 +177,7 @@ CONFIG_IP_SET_HASH_NETIFACE=m
 CONFIG_IP_SET_LIST_SET=m
 CONFIG_NF_CONNTRACK_IPV4=m
 CONFIG_NFT_CHAIN_ROUTE_IPV4=m
+CONFIG_NFT_DUP_IPV4=m
 CONFIG_NF_TABLES_ARP=m
 CONFIG_NF_LOG_ARP=m
 CONFIG_NFT_CHAIN_NAT_IPV4=m
@@ -202,6 +205,7 @@ CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
 CONFIG_NFT_CHAIN_ROUTE_IPV6=m
+CONFIG_NFT_DUP_IPV6=m
 CONFIG_NFT_CHAIN_NAT_IPV6=m
 CONFIG_NFT_MASQ_IPV6=m
 CONFIG_NFT_REDIR_IPV6=m
@@ -267,6 +271,7 @@ CONFIG_NETLINK_DIAG=m
 CONFIG_MPLS=y
 CONFIG_NET_MPLS_GSO=m
 CONFIG_MPLS_ROUTING=m
+CONFIG_MPLS_IPTUNNEL=m
 # CONFIG_WIRELESS is not set
 # CONFIG_UEVENT_HELPER is not set
 CONFIG_DEVTMPFS=y
@@ -354,6 +359,7 @@ CONFIG_NE2000=y
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_SMSC is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
 # CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PLIP=m
@@ -510,6 +516,7 @@ CONFIG_TEST_USER_COPY=m
 CONFIG_TEST_BPF=m
 CONFIG_TEST_FIRMWARE=m
 CONFIG_TEST_UDELAY=m
+CONFIG_TEST_STATIC_KEYS=m
 CONFIG_EARLY_PRINTK=y
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_CRYPTO_RSA=m
index 8442d267b877202e5293c0c5178eb340113e69f8..9a4cab78a2ea82ce3043be9c8a5582328774f21b 100644 (file)
@@ -10,6 +10,7 @@ CONFIG_LOG_BUF_SHIFT=16
 # CONFIG_PID_NS is not set
 # CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_USERFAULTFD=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
@@ -50,7 +51,6 @@ CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_NET_IPVTI=m
 CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE_CORE=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
@@ -60,10 +60,12 @@ CONFIG_INET_XFRM_MODE_BEET=m
 # CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=m
 CONFIG_INET_UDP_DIAG=m
+CONFIG_IPV6=m
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_ILA=m
 CONFIG_IPV6_VTI=m
 CONFIG_IPV6_GRE=m
 CONFIG_NETFILTER=y
@@ -172,6 +174,7 @@ CONFIG_IP_SET_HASH_NETIFACE=m
 CONFIG_IP_SET_LIST_SET=m
 CONFIG_NF_CONNTRACK_IPV4=m
 CONFIG_NFT_CHAIN_ROUTE_IPV4=m
+CONFIG_NFT_DUP_IPV4=m
 CONFIG_NF_TABLES_ARP=m
 CONFIG_NF_LOG_ARP=m
 CONFIG_NFT_CHAIN_NAT_IPV4=m
@@ -199,6 +202,7 @@ CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
 CONFIG_NFT_CHAIN_ROUTE_IPV6=m
+CONFIG_NFT_DUP_IPV6=m
 CONFIG_NFT_CHAIN_NAT_IPV6=m
 CONFIG_NFT_MASQ_IPV6=m
 CONFIG_NFT_REDIR_IPV6=m
@@ -264,6 +268,7 @@ CONFIG_NETLINK_DIAG=m
 CONFIG_MPLS=y
 CONFIG_NET_MPLS_GSO=m
 CONFIG_MPLS_ROUTING=m
+CONFIG_MPLS_IPTUNNEL=m
 # CONFIG_WIRELESS is not set
 # CONFIG_UEVENT_HELPER is not set
 CONFIG_DEVTMPFS=y
@@ -341,6 +346,7 @@ CONFIG_SUN3_82586=y
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
 # CONFIG_NET_VENDOR_SUN is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
 # CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PPP=m
@@ -489,6 +495,7 @@ CONFIG_TEST_USER_COPY=m
 CONFIG_TEST_BPF=m
 CONFIG_TEST_FIRMWARE=m
 CONFIG_TEST_UDELAY=m
+CONFIG_TEST_STATIC_KEYS=m
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_CRYPTO_RSA=m
 CONFIG_CRYPTO_MANAGER=y
index 0e1b542e155582a3685340bf0ce8651fcc5d8948..1a2eaac13dbdd540f223aea5c67c660723e3cf54 100644 (file)
@@ -10,6 +10,7 @@ CONFIG_LOG_BUF_SHIFT=16
 # CONFIG_PID_NS is not set
 # CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_USERFAULTFD=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
@@ -50,7 +51,6 @@ CONFIG_NET_IPGRE_DEMUX=m
 CONFIG_NET_IPGRE=m
 CONFIG_NET_IPVTI=m
 CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE_CORE=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
@@ -60,10 +60,12 @@ CONFIG_INET_XFRM_MODE_BEET=m
 # CONFIG_INET_LRO is not set
 CONFIG_INET_DIAG=m
 CONFIG_INET_UDP_DIAG=m
+CONFIG_IPV6=m
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_ILA=m
 CONFIG_IPV6_VTI=m
 CONFIG_IPV6_GRE=m
 CONFIG_NETFILTER=y
@@ -172,6 +174,7 @@ CONFIG_IP_SET_HASH_NETIFACE=m
 CONFIG_IP_SET_LIST_SET=m
 CONFIG_NF_CONNTRACK_IPV4=m
 CONFIG_NFT_CHAIN_ROUTE_IPV4=m
+CONFIG_NFT_DUP_IPV4=m
 CONFIG_NF_TABLES_ARP=m
 CONFIG_NF_LOG_ARP=m
 CONFIG_NFT_CHAIN_NAT_IPV4=m
@@ -199,6 +202,7 @@ CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
 CONFIG_NFT_CHAIN_ROUTE_IPV6=m
+CONFIG_NFT_DUP_IPV6=m
 CONFIG_NFT_CHAIN_NAT_IPV6=m
 CONFIG_NFT_MASQ_IPV6=m
 CONFIG_NFT_REDIR_IPV6=m
@@ -264,6 +268,7 @@ CONFIG_NETLINK_DIAG=m
 CONFIG_MPLS=y
 CONFIG_NET_MPLS_GSO=m
 CONFIG_MPLS_ROUTING=m
+CONFIG_MPLS_IPTUNNEL=m
 # CONFIG_WIRELESS is not set
 # CONFIG_UEVENT_HELPER is not set
 CONFIG_DEVTMPFS=y
@@ -341,6 +346,7 @@ CONFIG_SUN3LANCE=y
 # CONFIG_NET_VENDOR_SAMSUNG is not set
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
 # CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_PPP=m
@@ -489,6 +495,7 @@ CONFIG_TEST_USER_COPY=m
 CONFIG_TEST_BPF=m
 CONFIG_TEST_FIRMWARE=m
 CONFIG_TEST_UDELAY=m
+CONFIG_TEST_STATIC_KEYS=m
 CONFIG_EARLY_PRINTK=y
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_CRYPTO_RSA=m
index 81ca118d58af90da793a8038225c6ec605c2d63a..a644f4a53b94d73fce835168f49ee75e6c10fbc7 100644 (file)
@@ -64,8 +64,7 @@ extern void m68k_setup_auto_interrupt(void (*handler)(unsigned int,
                                                      struct pt_regs *));
 extern void m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt);
 extern void m68k_setup_irq_controller(struct irq_chip *,
-                                     void (*handle)(unsigned int irq,
-                                                    struct irq_desc *desc),
+                                     void (*handle)(struct irq_desc *desc),
                                      unsigned int irq, unsigned int cnt);
 
 extern unsigned int irq_canonicalize(unsigned int irq);
index 5a822bb790f72135862dcc0b7a97296954d73bd9..066e74f666ae95e4c9f58c42010bc857ca6454ca 100644 (file)
@@ -4,4 +4,34 @@
 #define __ALIGN .align 4
 #define __ALIGN_STR ".align 4"
 
+/*
+ * Make sure the compiler doesn't do anything stupid with the
+ * arguments on the stack - they are owned by the *caller*, not
+ * the callee. This just fools gcc into not spilling into them,
+ * and keeps it from doing tailcall recursion and/or using the
+ * stack slots for temporaries, since they are live and "used"
+ * all the way to the end of the function.
+ */
+#define asmlinkage_protect(n, ret, args...) \
+       __asmlinkage_protect##n(ret, ##args)
+#define __asmlinkage_protect_n(ret, args...) \
+       __asm__ __volatile__ ("" : "=r" (ret) : "0" (ret), ##args)
+#define __asmlinkage_protect0(ret) \
+       __asmlinkage_protect_n(ret)
+#define __asmlinkage_protect1(ret, arg1) \
+       __asmlinkage_protect_n(ret, "m" (arg1))
+#define __asmlinkage_protect2(ret, arg1, arg2) \
+       __asmlinkage_protect_n(ret, "m" (arg1), "m" (arg2))
+#define __asmlinkage_protect3(ret, arg1, arg2, arg3) \
+       __asmlinkage_protect_n(ret, "m" (arg1), "m" (arg2), "m" (arg3))
+#define __asmlinkage_protect4(ret, arg1, arg2, arg3, arg4) \
+       __asmlinkage_protect_n(ret, "m" (arg1), "m" (arg2), "m" (arg3), \
+                             "m" (arg4))
+#define __asmlinkage_protect5(ret, arg1, arg2, arg3, arg4, arg5) \
+       __asmlinkage_protect_n(ret, "m" (arg1), "m" (arg2), "m" (arg3), \
+                             "m" (arg4), "m" (arg5))
+#define __asmlinkage_protect6(ret, arg1, arg2, arg3, arg4, arg5, arg6) \
+       __asmlinkage_protect_n(ret, "m" (arg1), "m" (arg2), "m" (arg3), \
+                             "m" (arg4), "m" (arg5), "m" (arg6))
+
 #endif
index fe3fc9ae1b69d0163805c0265c862c1125d53f8e..53c632c85b0377ac9bc07cf9bc09d4dbf6b8941c 100644 (file)
@@ -261,7 +261,7 @@ extern void via_irq_enable(int);
 extern void via_irq_disable(int);
 extern void via_nubus_irq_startup(int irq);
 extern void via_nubus_irq_shutdown(int irq);
-extern void via1_irq(unsigned int irq, struct irq_desc *desc);
+extern void via1_irq(struct irq_desc *desc);
 extern void via1_set_head(int);
 extern int via2_scsi_drq_pending(void);
 
index 244e0dbe45dbeda359e233cde23b4652f0ce13dc..0793a7f174176e6d590ca4d9567a9e3523c42c50 100644 (file)
@@ -4,7 +4,7 @@
 #include <uapi/asm/unistd.h>
 
 
-#define NR_syscalls            356
+#define NR_syscalls            375
 
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_OLD_STAT
index 61fb6cb9d2ae3c66a1c0c6dec1ac95adb83dd810..5e6fae6c275f9b110464cb80bbb47187c2251dcd 100644 (file)
 #define __NR_memfd_create      353
 #define __NR_bpf               354
 #define __NR_execveat          355
+#define __NR_socket            356
+#define __NR_socketpair                357
+#define __NR_bind              358
+#define __NR_connect           359
+#define __NR_listen            360
+#define __NR_accept4           361
+#define __NR_getsockopt                362
+#define __NR_setsockopt                363
+#define __NR_getsockname       364
+#define __NR_getpeername       365
+#define __NR_sendto            366
+#define __NR_sendmsg           367
+#define __NR_recvfrom          368
+#define __NR_recvmsg           369
+#define __NR_shutdown          370
+#define __NR_recvmmsg          371
+#define __NR_sendmmsg          372
+#define __NR_userfaultfd       373
+#define __NR_membarrier                374
 
 #endif /* _UAPI_ASM_M68K_UNISTD_H_ */
index a0ec4303f2c8e57a04fb353178d43b0be6a461fe..5dd0e80042f51107e63e0fcd832f4c46c85b826c 100644 (file)
@@ -376,4 +376,22 @@ ENTRY(sys_call_table)
        .long sys_memfd_create
        .long sys_bpf
        .long sys_execveat              /* 355 */
-
+       .long sys_socket
+       .long sys_socketpair
+       .long sys_bind
+       .long sys_connect
+       .long sys_listen                /* 360 */
+       .long sys_accept4
+       .long sys_getsockopt
+       .long sys_setsockopt
+       .long sys_getsockname
+       .long sys_getpeername           /* 365 */
+       .long sys_sendto
+       .long sys_sendmsg
+       .long sys_recvfrom
+       .long sys_recvmsg
+       .long sys_shutdown              /* 370 */
+       .long sys_recvmmsg
+       .long sys_sendmmsg
+       .long sys_userfaultfd
+       .long sys_membarrier
index 3fe0e43d44f630dafea61dcdaa44835e0e84bbcd..f6f7d42713ec8b95ad7aa19a4be08156cf261697 100644 (file)
@@ -45,7 +45,7 @@ void __init baboon_init(void)
  * Baboon interrupt handler. This works a lot like a VIA.
  */
 
-static void baboon_irq(unsigned int irq, struct irq_desc *desc)
+static void baboon_irq(struct irq_desc *desc)
 {
        int irq_bit, irq_num;
        unsigned char events;
index 191610d97689932ba8413af2ccc27b77e3addc9f..55d6592783f55710d0b23cae075f657252826650 100644 (file)
@@ -63,7 +63,7 @@ void __init oss_nubus_init(void)
  * Handle miscellaneous OSS interrupts.
  */
 
-static void oss_irq(unsigned int __irq, struct irq_desc *desc)
+static void oss_irq(struct irq_desc *desc)
 {
        int events = oss->irq_pending &
                (OSS_IP_IOPSCC | OSS_IP_SCSI | OSS_IP_IOPISM);
@@ -99,7 +99,7 @@ static void oss_irq(unsigned int __irq, struct irq_desc *desc)
  * Unlike the VIA/RBV this is on its own autovector interrupt level.
  */
 
-static void oss_nubus_irq(unsigned int irq, struct irq_desc *desc)
+static void oss_nubus_irq(struct irq_desc *desc)
 {
        int events, irq_bit, i;
 
index 3b9e302e7a37f5fa80336bca8f5af07e131b5fbc..cd38f29955c87421e8142c8d4ca9e065111b57c3 100644 (file)
@@ -113,7 +113,7 @@ void __init psc_init(void)
  * PSC interrupt handler. It's a lot like the VIA interrupt handler.
  */
 
-static void psc_irq(unsigned int __irq, struct irq_desc *desc)
+static void psc_irq(struct irq_desc *desc)
 {
        unsigned int offset = (unsigned int)irq_desc_get_handler_data(desc);
        unsigned int irq = irq_desc_get_irq(desc);
index e198dec868e472e802768c5a9459e498e7623b00..ce56e04386e707350568fd5850a4f44259f033b0 100644 (file)
@@ -446,7 +446,7 @@ void via_nubus_irq_shutdown(int irq)
  * via6522.c :-), disable/pending masks added.
  */
 
-void via1_irq(unsigned int irq, struct irq_desc *desc)
+void via1_irq(struct irq_desc *desc)
 {
        int irq_num;
        unsigned char irq_bit, events;
@@ -467,7 +467,7 @@ void via1_irq(unsigned int irq, struct irq_desc *desc)
        } while (events >= irq_bit);
 }
 
-static void via2_irq(unsigned int irq, struct irq_desc *desc)
+static void via2_irq(struct irq_desc *desc)
 {
        int irq_num;
        unsigned char irq_bit, events;
@@ -493,7 +493,7 @@ static void via2_irq(unsigned int irq, struct irq_desc *desc)
  * VIA2 dispatcher as a fast interrupt handler.
  */
 
-void via_nubus_irq(unsigned int irq, struct irq_desc *desc)
+static void via_nubus_irq(struct irq_desc *desc)
 {
        int slot_irq;
        unsigned char slot_bit, events;
index df31353fd2001dc0e357feafcf975aa6e5537622..29acb89daaaa55f2b1640c3d751233ed034b43b7 100644 (file)
@@ -54,4 +54,5 @@ generic-y += ucontext.h
 generic-y += unaligned.h
 generic-y += user.h
 generic-y += vga.h
+generic-y += word-at-a-time.h
 generic-y += xor.h
index a336094a7a6c943b43dda144b44054d83bb4f54e..3074b64793e6fc9b57e8ac772c8e26274c36d8b6 100644 (file)
@@ -94,13 +94,11 @@ void do_IRQ(int irq, struct pt_regs *regs)
                        "MOV   D0.5,%0\n"
                        "MOV   D1Ar1,%1\n"
                        "MOV   D1RtP,%2\n"
-                       "MOV   D0Ar2,%3\n"
                        "SWAP  A0StP,D0.5\n"
                        "SWAP  PC,D1RtP\n"
                        "MOV   A0StP,D0.5\n"
                        :
-                       : "r" (isp), "r" (irq), "r" (desc->handle_irq),
-                         "r" (desc)
+                       : "r" (isp), "r" (desc), "r" (desc->handle_irq)
                        : "memory", "cc", "D1Ar1", "D0Ar2", "D1Ar3", "D0Ar4",
                          "D1Ar5", "D0Ar6", "D0Re0", "D1Re0", "D0.4", "D1RtP",
                          "D0.5"
index 2f222f355c4bbc69842ccd62f3419b0cbd1732a4..b0ae88c9fed922a4ba95be0498f421d3927eb40e 100644 (file)
@@ -10,3 +10,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += syscalls.h
 generic-y += trace_clock.h
+generic-y += word-at-a-time.h
index 6b8b75266801aaf25fe509985d2a5edd66ed3e8c..ae838ed5fcf2535ca5c047a2837adadc434735cd 100644 (file)
@@ -863,7 +863,14 @@ void pcibios_setup_bus_devices(struct pci_bus *bus)
 
 void pcibios_fixup_bus(struct pci_bus *bus)
 {
-       /* Fixup the bus */
+       /* When called from the generic PCI probe, read PCI<->PCI bridge
+        * bases. This is -not- called when generating the PCI tree from
+        * the OF device-tree.
+        */
+       if (bus->self != NULL)
+               pci_read_bridge_bases(bus);
+
+       /* Now fixup the bus bus */
        pcibios_setup_bus_self(bus);
 
        /* Now fixup devices on that bus */
index 4c496c50edf699a6ed426f4f3d658bd2919cf6db..da9f9220048fceeafe755057c58905ae74e5abd2 100644 (file)
@@ -851,7 +851,7 @@ static struct syscore_ops alchemy_gpic_pmops = {
 
 /* create chained handlers for the 4 IC requests to the MIPS IRQ ctrl */
 #define DISP(name, base, addr)                                               \
-static void au1000_##name##_dispatch(unsigned int irq, struct irq_desc *d)    \
+static void au1000_##name##_dispatch(struct irq_desc *d)                     \
 {                                                                            \
        unsigned long r = __raw_readl((void __iomem *)KSEG1ADDR(addr));       \
        if (likely(r))                                                        \
@@ -865,7 +865,7 @@ DISP(ic0r1, AU1000_INTC0_INT_BASE, AU1000_IC0_PHYS_ADDR + IC_REQ1INT)
 DISP(ic1r0, AU1000_INTC1_INT_BASE, AU1000_IC1_PHYS_ADDR + IC_REQ0INT)
 DISP(ic1r1, AU1000_INTC1_INT_BASE, AU1000_IC1_PHYS_ADDR + IC_REQ1INT)
 
-static void alchemy_gpic_dispatch(unsigned int irq, struct irq_desc *d)
+static void alchemy_gpic_dispatch(struct irq_desc *d)
 {
        int i = __raw_readl(AU1300_GPIC_ADDR + AU1300_GPIC_PRIENC);
        generic_handle_irq(ALCHEMY_GPIC_INT_BASE + i);
index 324ad72d7c3622414280af50ab579e5dd107f3eb..faeddf119fd4247ea4ad5b0c87c611b466ef58a1 100644 (file)
@@ -86,7 +86,7 @@ EXPORT_SYMBOL_GPL(bcsr_mod);
 /*
  * DB1200/PB1200 CPLD IRQ muxer
  */
-static void bcsr_csc_handler(unsigned int irq, struct irq_desc *d)
+static void bcsr_csc_handler(struct irq_desc *d)
 {
        unsigned short bisr = __raw_readw(bcsr_virt + BCSR_REG_INTSTAT);
        struct irq_chip *chip = irq_desc_get_chip(d);
index ec9a371f1e62c49b823bdac3b86d101804796da3..8da996142d6a04c5336549c65a8b578142dbd783 100644 (file)
@@ -69,7 +69,7 @@ static struct irqaction ar2315_ahb_err_interrupt  = {
        .name           = "ar2315-ahb-error",
 };
 
-static void ar2315_misc_irq_handler(unsigned irq, struct irq_desc *desc)
+static void ar2315_misc_irq_handler(struct irq_desc *desc)
 {
        u32 pending = ar2315_rst_reg_read(AR2315_ISR) &
                      ar2315_rst_reg_read(AR2315_IMR);
index e63e38fa488033499cdf005df028d15e9b616139..acd55a9cffe3ecce5a7c6b03dab67c8adcc8b8d1 100644 (file)
@@ -73,7 +73,7 @@ static struct irqaction ar5312_ahb_err_interrupt  = {
        .name    = "ar5312-ahb-error",
 };
 
-static void ar5312_misc_irq_handler(unsigned irq, struct irq_desc *desc)
+static void ar5312_misc_irq_handler(struct irq_desc *desc)
 {
        u32 pending = ar5312_rst_reg_read(AR5312_ISR) &
                      ar5312_rst_reg_read(AR5312_IMR);
index 807132b838b24914d072c6ed81a0f86b2e57d56a..eeb3953ed8ac8d8051ccbe3df9af8270915329b3 100644 (file)
@@ -26,7 +26,7 @@
 #include "common.h"
 #include "machtypes.h"
 
-static void ath79_misc_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void ath79_misc_irq_handler(struct irq_desc *desc)
 {
        void __iomem *base = ath79_reset_base;
        u32 pending;
@@ -119,7 +119,7 @@ static void __init ath79_misc_irq_init(void)
        irq_set_chained_handler(ATH79_CPU_IRQ(6), ath79_misc_irq_handler);
 }
 
-static void ar934x_ip2_irq_dispatch(unsigned int irq, struct irq_desc *desc)
+static void ar934x_ip2_irq_dispatch(struct irq_desc *desc)
 {
        u32 status;
 
@@ -148,7 +148,7 @@ static void ar934x_ip2_irq_init(void)
        irq_set_chained_handler(ATH79_CPU_IRQ(2), ar934x_ip2_irq_dispatch);
 }
 
-static void qca955x_ip2_irq_dispatch(unsigned int irq, struct irq_desc *desc)
+static void qca955x_ip2_irq_dispatch(struct irq_desc *desc)
 {
        u32 status;
 
@@ -171,7 +171,7 @@ static void qca955x_ip2_irq_dispatch(unsigned int irq, struct irq_desc *desc)
        }
 }
 
-static void qca955x_ip3_irq_dispatch(unsigned int irq, struct irq_desc *desc)
+static void qca955x_ip3_irq_dispatch(struct irq_desc *desc)
 {
        u32 status;
 
@@ -293,8 +293,26 @@ static int __init ath79_misc_intc_of_init(
 
        return 0;
 }
-IRQCHIP_DECLARE(ath79_misc_intc, "qca,ar7100-misc-intc",
-               ath79_misc_intc_of_init);
+
+static int __init ar7100_misc_intc_of_init(
+       struct device_node *node, struct device_node *parent)
+{
+       ath79_misc_irq_chip.irq_mask_ack = ar71xx_misc_irq_mask;
+       return ath79_misc_intc_of_init(node, parent);
+}
+
+IRQCHIP_DECLARE(ar7100_misc_intc, "qca,ar7100-misc-intc",
+               ar7100_misc_intc_of_init);
+
+static int __init ar7240_misc_intc_of_init(
+       struct device_node *node, struct device_node *parent)
+{
+       ath79_misc_irq_chip.irq_ack = ar724x_misc_irq_ack;
+       return ath79_misc_intc_of_init(node, parent);
+}
+
+IRQCHIP_DECLARE(ar7240_misc_intc, "qca,ar7240-misc-intc",
+               ar7240_misc_intc_of_init);
 
 static int __init ar79_cpu_intc_of_init(
        struct device_node *node, struct device_node *parent)
index ad448e41e3bd58c633d49afa5b2d24723c1881a9..232385441e468729ca0f70c6acebbb1be62eadd0 100644 (file)
 #include <bcm63xx_dev_spi.h>
 #include <bcm63xx_regs.h>
 
-/*
- * register offsets
- */
-static const unsigned long bcm6348_regs_spi[] = {
-       __GEN_SPI_REGS_TABLE(6348)
-};
-
-static const unsigned long bcm6358_regs_spi[] = {
-       __GEN_SPI_REGS_TABLE(6358)
-};
-
-const unsigned long *bcm63xx_regs_spi;
-EXPORT_SYMBOL(bcm63xx_regs_spi);
-
-static __init void bcm63xx_spi_regs_init(void)
-{
-       if (BCMCPU_IS_6338() || BCMCPU_IS_6348())
-               bcm63xx_regs_spi = bcm6348_regs_spi;
-       if (BCMCPU_IS_3368() || BCMCPU_IS_6358() ||
-               BCMCPU_IS_6362() || BCMCPU_IS_6368())
-               bcm63xx_regs_spi = bcm6358_regs_spi;
-}
-
 static struct resource spi_resources[] = {
        {
                .start          = -1, /* filled at runtime */
@@ -53,19 +30,10 @@ static struct resource spi_resources[] = {
        },
 };
 
-static struct bcm63xx_spi_pdata spi_pdata = {
-       .bus_num                = 0,
-       .num_chipselect         = 8,
-};
-
 static struct platform_device bcm63xx_spi_device = {
-       .name           = "bcm63xx-spi",
        .id             = -1,
        .num_resources  = ARRAY_SIZE(spi_resources),
        .resource       = spi_resources,
-       .dev            = {
-               .platform_data = &spi_pdata,
-       },
 };
 
 int __init bcm63xx_spi_register(void)
@@ -78,21 +46,15 @@ int __init bcm63xx_spi_register(void)
        spi_resources[1].start = bcm63xx_get_irq_number(IRQ_SPI);
 
        if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) {
+               bcm63xx_spi_device.name = "bcm6348-spi",
                spi_resources[0].end += BCM_6348_RSET_SPI_SIZE - 1;
-               spi_pdata.fifo_size = SPI_6348_MSG_DATA_SIZE;
-               spi_pdata.msg_type_shift = SPI_6348_MSG_TYPE_SHIFT;
-               spi_pdata.msg_ctl_width = SPI_6348_MSG_CTL_WIDTH;
        }
 
        if (BCMCPU_IS_3368() || BCMCPU_IS_6358() || BCMCPU_IS_6362() ||
                BCMCPU_IS_6368()) {
+               bcm63xx_spi_device.name = "bcm6358-spi",
                spi_resources[0].end += BCM_6358_RSET_SPI_SIZE - 1;
-               spi_pdata.fifo_size = SPI_6358_MSG_DATA_SIZE;
-               spi_pdata.msg_type_shift = SPI_6358_MSG_TYPE_SHIFT;
-               spi_pdata.msg_ctl_width = SPI_6358_MSG_CTL_WIDTH;
        }
 
-       bcm63xx_spi_regs_init();
-
        return platform_device_register(&bcm63xx_spi_device);
 }
index f26c3c661cca9eae9051f2f822a8ef61fd8c63a0..0352bc8d56b316588dbca209462700c4ffa03aa3 100644 (file)
@@ -2221,7 +2221,7 @@ static irqreturn_t octeon_irq_cib_handler(int my_irq, void *data)
                        if (irqd_get_trigger_type(irq_data) &
                                IRQ_TYPE_EDGE_BOTH)
                                cvmx_write_csr(host_data->raw_reg, 1ull << i);
-                       generic_handle_irq_desc(irq, desc);
+                       generic_handle_irq_desc(desc);
                }
        }
 
index 89a628455bc253b01c2cc7b9f3cc2a6d9a426493..bd634259eab9d6b0f7d1b8e746d0b11c01f0950d 100644 (file)
@@ -933,7 +933,7 @@ void __init plat_mem_setup(void)
        while ((boot_mem_map.nr_map < BOOT_MEM_MAP_MAX)
                && (total < MAX_MEMORY)) {
                memory = cvmx_bootmem_phy_alloc(mem_alloc_size,
-                                               __pa_symbol(&__init_end), -1,
+                                               __pa_symbol(&_end), -1,
                                                0x100000,
                                                CVMX_BOOTMEM_FLAG_NO_LOCKING);
                if (memory >= 0) {
index 40ec4ca3f946a9238afa6e0edd25c0440f86a36b..c7fe4d01e79c61bbaee58aa25b9b50bf5b9a380e 100644 (file)
@@ -17,4 +17,5 @@ generic-y += segment.h
 generic-y += serial.h
 generic-y += trace_clock.h
 generic-y += user.h
+generic-y += word-at-a-time.h
 generic-y += xor.h
index 9801ac9826554ca0d8ab2e27e21ad6305f18da67..fe67f12ac2393b23705b4a094bbf8c3b7cc77166 100644 (file)
@@ -20,6 +20,9 @@
 #ifndef cpu_has_tlb
 #define cpu_has_tlb            (cpu_data[0].options & MIPS_CPU_TLB)
 #endif
+#ifndef cpu_has_ftlb
+#define cpu_has_ftlb           (cpu_data[0].options & MIPS_CPU_FTLB)
+#endif
 #ifndef cpu_has_tlbinv
 #define cpu_has_tlbinv         (cpu_data[0].options & MIPS_CPU_TLBINV)
 #endif
index cd89e9855775276ea7c3a185d9e61b3702f06b6f..82ad15f11049284c2f347fc66b68ea5091fb810d 100644 (file)
@@ -385,6 +385,7 @@ enum cpu_type_enum {
 #define MIPS_CPU_CDMM          0x4000000000ull /* CPU has Common Device Memory Map */
 #define MIPS_CPU_BP_GHIST      0x8000000000ull /* R12K+ Branch Prediction Global History */
 #define MIPS_CPU_SP            0x10000000000ull /* Small (1KB) page support */
+#define MIPS_CPU_FTLB          0x20000000000ull /* CPU has Fixed-page-size TLB */
 
 /*
  * CPU ASE encodings
index 9e777cd42b67190a5dce5ac11553a3de05e4375e..d10fd80dbb7e96b898d2230c2d0f5112d02c3bc1 100644 (file)
@@ -256,6 +256,7 @@ static inline void __iomem * __ioremap_mode(phys_addr_t offset, unsigned long si
  */
 #define ioremap_nocache(offset, size)                                  \
        __ioremap_mode((offset), (size), _CACHE_UNCACHED)
+#define ioremap_uc ioremap_nocache
 
 /*
  * ioremap_cachable -  map bus memory into CPU space
index e8c8d9d0c45fe7c3600ba39a44e7090ba0827a04..5a1a882e0a75dec0796dc30557d4a72341875002 100644 (file)
@@ -61,6 +61,7 @@
 #define KVM_PRIVATE_MEM_SLOTS  0
 
 #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
+#define KVM_HALT_POLL_NS_DEFAULT 500000
 
 
 
@@ -128,6 +129,7 @@ struct kvm_vcpu_stat {
        u32 msa_disabled_exits;
        u32 flush_dcache_exits;
        u32 halt_successful_poll;
+       u32 halt_attempted_poll;
        u32 halt_wakeup;
 };
 
index b02891f9caaf1d8ffecf14b0e0fa7be5b7fb33c8..21d9607c80d7deaa1ef2174c0dde62bda9985bde 100644 (file)
@@ -65,6 +65,15 @@ static inline void write_maar_pair(unsigned idx, phys_addr_t lower,
        back_to_back_c0_hazard();
 }
 
+/**
+ * maar_init() - initialise MAARs
+ *
+ * Performs initialisation of MAARs for the current CPU, making use of the
+ * platforms implementation of platform_maar_init where necessary and
+ * duplicating the setup it provides on secondary CPUs.
+ */
+extern void maar_init(void);
+
 /**
  * struct maar_config - MAAR configuration data
  * @lower:     The lowest address that the MAAR pair will affect. Must be
index 25737655d1415a96bc913c96f5229ab21e120f24..dd299548860d1619d70070799224c8b3758bd75b 100644 (file)
@@ -7,48 +7,4 @@
 
 int __init bcm63xx_spi_register(void);
 
-struct bcm63xx_spi_pdata {
-       unsigned int    fifo_size;
-       unsigned int    msg_type_shift;
-       unsigned int    msg_ctl_width;
-       int             bus_num;
-       int             num_chipselect;
-};
-
-enum bcm63xx_regs_spi {
-       SPI_CMD,
-       SPI_INT_STATUS,
-       SPI_INT_MASK_ST,
-       SPI_INT_MASK,
-       SPI_ST,
-       SPI_CLK_CFG,
-       SPI_FILL_BYTE,
-       SPI_MSG_TAIL,
-       SPI_RX_TAIL,
-       SPI_MSG_CTL,
-       SPI_MSG_DATA,
-       SPI_RX_DATA,
-};
-
-#define __GEN_SPI_REGS_TABLE(__cpu)                                    \
-       [SPI_CMD]               = SPI_## __cpu ##_CMD,                  \
-       [SPI_INT_STATUS]        = SPI_## __cpu ##_INT_STATUS,           \
-       [SPI_INT_MASK_ST]       = SPI_## __cpu ##_INT_MASK_ST,          \
-       [SPI_INT_MASK]          = SPI_## __cpu ##_INT_MASK,             \
-       [SPI_ST]                = SPI_## __cpu ##_ST,                   \
-       [SPI_CLK_CFG]           = SPI_## __cpu ##_CLK_CFG,              \
-       [SPI_FILL_BYTE]         = SPI_## __cpu ##_FILL_BYTE,            \
-       [SPI_MSG_TAIL]          = SPI_## __cpu ##_MSG_TAIL,             \
-       [SPI_RX_TAIL]           = SPI_## __cpu ##_RX_TAIL,              \
-       [SPI_MSG_CTL]           = SPI_## __cpu ##_MSG_CTL,              \
-       [SPI_MSG_DATA]          = SPI_## __cpu ##_MSG_DATA,             \
-       [SPI_RX_DATA]           = SPI_## __cpu ##_RX_DATA,
-
-static inline unsigned long bcm63xx_spireg(enum bcm63xx_regs_spi reg)
-{
-       extern const unsigned long *bcm63xx_regs_spi;
-
-       return bcm63xx_regs_spi[reg];
-}
-
 #endif /* BCM63XX_DEV_SPI_H */
index d75b75e78ebb4749355f95a1709202b9f2d069af..1f1927ab42690b284257faa8991f4cff31a3264d 100644 (file)
@@ -194,6 +194,7 @@ BUILD_CM_RW(reg3_mask,              MIPS_CM_GCB_OFS + 0xc8)
 BUILD_CM_R_(gic_status,                MIPS_CM_GCB_OFS + 0xd0)
 BUILD_CM_R_(cpc_status,                MIPS_CM_GCB_OFS + 0xf0)
 BUILD_CM_RW(l2_config,         MIPS_CM_GCB_OFS + 0x130)
+BUILD_CM_RW(sys_config2,       MIPS_CM_GCB_OFS + 0x150)
 
 /* Core Local & Core Other register accessor functions */
 BUILD_CM_Cx_RW(reset_release,  0x00)
@@ -316,6 +317,10 @@ BUILD_CM_Cx_R_(tcid_8_priority,    0x80)
 #define CM_GCR_L2_CONFIG_ASSOC_SHF             0
 #define CM_GCR_L2_CONFIG_ASSOC_MSK             (_ULCAST_(0xff) << 0)
 
+/* GCR_SYS_CONFIG2 register fields */
+#define CM_GCR_SYS_CONFIG2_MAXVPW_SHF          0
+#define CM_GCR_SYS_CONFIG2_MAXVPW_MSK          (_ULCAST_(0xf) << 0)
+
 /* GCR_Cx_COHERENCE register fields */
 #define CM_GCR_Cx_COHERENCE_COHDOMAINEN_SHF    0
 #define CM_GCR_Cx_COHERENCE_COHDOMAINEN_MSK    (_ULCAST_(0xff) << 0)
@@ -405,4 +410,38 @@ static inline int mips_cm_revision(void)
        return read_gcr_rev();
 }
 
+/**
+ * mips_cm_max_vp_width() - return the width in bits of VP indices
+ *
+ * Return: the width, in bits, of VP indices in fields that combine core & VP
+ * indices.
+ */
+static inline unsigned int mips_cm_max_vp_width(void)
+{
+       extern int smp_num_siblings;
+
+       if (mips_cm_revision() >= CM_REV_CM3)
+               return read_gcr_sys_config2() & CM_GCR_SYS_CONFIG2_MAXVPW_MSK;
+
+       return smp_num_siblings;
+}
+
+/**
+ * mips_cm_vp_id() - calculate the hardware VP ID for a CPU
+ * @cpu: the CPU whose VP ID to calculate
+ *
+ * Hardware such as the GIC uses identifiers for VPs which may not match the
+ * CPU numbers used by Linux. This function calculates the hardware VP
+ * identifier corresponding to a given CPU.
+ *
+ * Return: the VP ID for the CPU.
+ */
+static inline unsigned int mips_cm_vp_id(unsigned int cpu)
+{
+       unsigned int core = cpu_data[cpu].core;
+       unsigned int vp = cpu_vpe_id(&cpu_data[cpu]);
+
+       return (core * mips_cm_max_vp_width()) + vp;
+}
+
 #endif /* __MIPS_ASM_MIPS_CM_H__ */
index d3cd8eac81e3a76baf455dd95e881cfd9c72eed9..c64781cf649f86b4ca4eec0fee38ba4c4da523e7 100644 (file)
 
 /* Bits specific to the MIPS32/64 PRA. */
 #define MIPS_CONF_MT           (_ULCAST_(7) <<  7)
+#define MIPS_CONF_MT_TLB       (_ULCAST_(1) <<  7)
+#define MIPS_CONF_MT_FTLB      (_ULCAST_(4) <<  7)
 #define MIPS_CONF_AR           (_ULCAST_(7) << 10)
 #define MIPS_CONF_AT           (_ULCAST_(3) << 13)
 #define MIPS_CONF_M            (_ULCAST_(1) << 31)
index 2a4c128277e45400fa4061bff15a17a1e10fc442..be52c2125d7101e37b805aef738ffa252c03d341 100644 (file)
@@ -57,8 +57,8 @@
 #include <asm/mach-netlogic/multi-node.h>
 
 struct irq_desc;
-void nlm_smp_function_ipi_handler(unsigned int irq, struct irq_desc *desc);
-void nlm_smp_resched_ipi_handler(unsigned int irq, struct irq_desc *desc);
+void nlm_smp_function_ipi_handler(struct irq_desc *desc);
+void nlm_smp_resched_ipi_handler(struct irq_desc *desc);
 void nlm_smp_irq_init(int hwcpuid);
 void nlm_boot_secondary_cpus(void);
 int nlm_wakeup_secondary_cpus(void);
index c4ddc4f0d2dcb11c7aa55167434d72e7990e083a..23cd9b118c9e4f8f8fd43031dd67dcee8e610af8 100644 (file)
 
 #define __SWAB_64_THRU_32__
 
-#if (defined(__mips_isa_rev) && (__mips_isa_rev >= 2)) ||              \
-    defined(_MIPS_ARCH_LOONGSON3A)
+#if !defined(__mips16) &&                                      \
+       ((defined(__mips_isa_rev) && (__mips_isa_rev >= 2)) ||  \
+        defined(_MIPS_ARCH_LOONGSON3A))
 
-static inline __attribute__((nomips16)) __attribute_const__
-               __u16 __arch_swab16(__u16 x)
+static inline __attribute_const__ __u16 __arch_swab16(__u16 x)
 {
        __asm__(
        "       .set    push                    \n"
        "       .set    arch=mips32r2           \n"
-       "       .set    nomips16                \n"
        "       wsbh    %0, %1                  \n"
        "       .set    pop                     \n"
        : "=r" (x)
@@ -32,13 +31,11 @@ static inline __attribute__((nomips16)) __attribute_const__
 }
 #define __arch_swab16 __arch_swab16
 
-static inline __attribute__((nomips16)) __attribute_const__
-               __u32 __arch_swab32(__u32 x)
+static inline __attribute_const__ __u32 __arch_swab32(__u32 x)
 {
        __asm__(
        "       .set    push                    \n"
        "       .set    arch=mips32r2           \n"
-       "       .set    nomips16                \n"
        "       wsbh    %0, %1                  \n"
        "       rotr    %0, %0, 16              \n"
        "       .set    pop                     \n"
@@ -54,13 +51,11 @@ static inline __attribute__((nomips16)) __attribute_const__
  * 64-bit kernel on r2 CPUs.
  */
 #ifdef __mips64
-static inline __attribute__((nomips16)) __attribute_const__
-               __u64 __arch_swab64(__u64 x)
+static inline __attribute_const__ __u64 __arch_swab64(__u64 x)
 {
        __asm__(
        "       .set    push                    \n"
        "       .set    arch=mips64r2           \n"
-       "       .set    nomips16                \n"
        "       dsbh    %0, %1                  \n"
        "       dshd    %0, %0                  \n"
        "       .set    pop                     \n"
@@ -71,5 +66,5 @@ static inline __attribute__((nomips16)) __attribute_const__
 }
 #define __arch_swab64 __arch_swab64
 #endif /* __mips64 */
-#endif /* MIPS R2 or newer or Loongson 3A */
+#endif /* (not __mips16) and (MIPS R2 or newer or Loongson 3A) */
 #endif /* _ASM_SWAB_H */
index c03088f9f514e7c21f7ae0e185f8be0456af372b..cfabadb135d9fe94912080ea41ca761e6f1eca08 100644 (file)
 #define __NR_memfd_create              (__NR_Linux + 354)
 #define __NR_bpf                       (__NR_Linux + 355)
 #define __NR_execveat                  (__NR_Linux + 356)
+#define __NR_userfaultfd               (__NR_Linux + 357)
+#define __NR_membarrier                        (__NR_Linux + 358)
 
 /*
  * Offset of the last Linux o32 flavoured syscall
  */
-#define __NR_Linux_syscalls            356
+#define __NR_Linux_syscalls            358
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
 
 #define __NR_O32_Linux                 4000
-#define __NR_O32_Linux_syscalls                356
+#define __NR_O32_Linux_syscalls                358
 
 #if _MIPS_SIM == _MIPS_SIM_ABI64
 
 #define __NR_memfd_create              (__NR_Linux + 314)
 #define __NR_bpf                       (__NR_Linux + 315)
 #define __NR_execveat                  (__NR_Linux + 316)
+#define __NR_userfaultfd               (__NR_Linux + 317)
+#define __NR_membarrier                        (__NR_Linux + 318)
 
 /*
  * Offset of the last Linux 64-bit flavoured syscall
  */
-#define __NR_Linux_syscalls            316
+#define __NR_Linux_syscalls            318
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
 
 #define __NR_64_Linux                  5000
-#define __NR_64_Linux_syscalls         316
+#define __NR_64_Linux_syscalls         318
 
 #if _MIPS_SIM == _MIPS_SIM_NABI32
 
 #define __NR_memfd_create              (__NR_Linux + 318)
 #define __NR_bpf                       (__NR_Linux + 319)
 #define __NR_execveat                  (__NR_Linux + 320)
+#define __NR_userfaultfd               (__NR_Linux + 321)
+#define __NR_membarrier                        (__NR_Linux + 322)
 
 /*
  * Offset of the last N32 flavoured syscall
  */
-#define __NR_Linux_syscalls            320
+#define __NR_Linux_syscalls            322
 
 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
 
 #define __NR_N32_Linux                 6000
-#define __NR_N32_Linux_syscalls                320
+#define __NR_N32_Linux_syscalls                322
 
 #endif /* _UAPI_ASM_UNISTD_H */
index 4e62bf85d0b0f910cc56c726167cb933b35045d0..459cb017306c21eb63259b8cb0a406c65080cc8b 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/power/jz4740-battery.h>
 #include <linux/power/gpio-charger.h>
 
+#include <asm/mach-jz4740/gpio.h>
 #include <asm/mach-jz4740/jz4740_fb.h>
 #include <asm/mach-jz4740/jz4740_mmc.h>
 #include <asm/mach-jz4740/jz4740_nand.h>
index 6cd69fdaa1c5f95f9ce06ab31b1177c73a7f650f..8c6d76c9b2d69bf6603e32598e3b8d74cba15bf6 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/seq_file.h>
 
 #include <asm/mach-jz4740/base.h>
+#include <asm/mach-jz4740/gpio.h>
 
 #define JZ4740_GPIO_BASE_A (32*0)
 #define JZ4740_GPIO_BASE_B (32*1)
@@ -291,7 +292,7 @@ static void jz_gpio_check_trigger_both(struct jz_gpio_chip *chip, unsigned int i
        writel(mask, reg);
 }
 
-static void jz_gpio_irq_demux_handler(unsigned int irq, struct irq_desc *desc)
+static void jz_gpio_irq_demux_handler(struct irq_desc *desc)
 {
        uint32_t flag;
        unsigned int gpio_irq;
index 9f71c06aebf6313c4a0b2bac9b1bbdc6228cee31..209ded16806bf5a295ff202258f5b7ff42070940 100644 (file)
@@ -39,6 +39,7 @@
         mfc0   \dest, CP0_CONFIG, 3
        andi    \dest, \dest, MIPS_CONF3_MT
        beqz    \dest, \nomt
+        nop
        .endm
 
 .section .text.cps-vec
@@ -223,10 +224,9 @@ LEAF(excep_ejtag)
        END(excep_ejtag)
 
 LEAF(mips_cps_core_init)
-#ifdef CONFIG_MIPS_MT
+#ifdef CONFIG_MIPS_MT_SMP
        /* Check that the core implements the MT ASE */
        has_mt  t0, 3f
-        nop
 
        .set    push
        .set    mips64r2
@@ -310,8 +310,9 @@ LEAF(mips_cps_boot_vpes)
        PTR_ADDU t0, t0, t1
 
        /* Calculate this VPEs ID. If the core doesn't support MT use 0 */
+       li      t9, 0
+#ifdef CONFIG_MIPS_MT_SMP
        has_mt  ta2, 1f
-        li     t9, 0
 
        /* Find the number of VPEs present in the core */
        mfc0    t1, CP0_MVPCONF0
@@ -330,6 +331,7 @@ LEAF(mips_cps_boot_vpes)
        /* Retrieve the VPE ID from EBase.CPUNum */
        mfc0    t9, $15, 1
        and     t9, t9, t1
+#endif
 
 1:     /* Calculate a pointer to this VPEs struct vpe_boot_config */
        li      t1, VPEBOOTCFG_SIZE
@@ -337,7 +339,7 @@ LEAF(mips_cps_boot_vpes)
        PTR_L   ta3, COREBOOTCFG_VPECONFIG(t0)
        PTR_ADDU v0, v0, ta3
 
-#ifdef CONFIG_MIPS_MT
+#ifdef CONFIG_MIPS_MT_SMP
 
        /* If the core doesn't support MT then return */
        bnez    ta2, 1f
@@ -451,7 +453,7 @@ LEAF(mips_cps_boot_vpes)
 
 2:     .set    pop
 
-#endif /* CONFIG_MIPS_MT */
+#endif /* CONFIG_MIPS_MT_SMP */
 
        /* Return */
        jr      ra
index 571a8e6ea5bd0048a840bc539135f27c32fec621..09a51d091941be3aa75ae37b53b386714a6d3db5 100644 (file)
@@ -410,16 +410,18 @@ static int set_ftlb_enable(struct cpuinfo_mips *c, int enable)
 static inline unsigned int decode_config0(struct cpuinfo_mips *c)
 {
        unsigned int config0;
-       int isa;
+       int isa, mt;
 
        config0 = read_c0_config();
 
        /*
         * Look for Standard TLB or Dual VTLB and FTLB
         */
-       if ((((config0 & MIPS_CONF_MT) >> 7) == 1) ||
-           (((config0 & MIPS_CONF_MT) >> 7) == 4))
+       mt = config0 & MIPS_CONF_MT;
+       if (mt == MIPS_CONF_MT_TLB)
                c->options |= MIPS_CPU_TLB;
+       else if (mt == MIPS_CONF_MT_FTLB)
+               c->options |= MIPS_CPU_TLB | MIPS_CPU_FTLB;
 
        isa = (config0 & MIPS_CONF_AT) >> 13;
        switch (isa) {
@@ -559,15 +561,18 @@ static inline unsigned int decode_config4(struct cpuinfo_mips *c)
        if (cpu_has_tlb) {
                if (((config4 & MIPS_CONF4_IE) >> 29) == 2)
                        c->options |= MIPS_CPU_TLBINV;
+
                /*
-                * This is a bit ugly. R6 has dropped that field from
-                * config4 and the only valid configuration is VTLB+FTLB so
-                * set a good value for mmuextdef for that case.
+                * R6 has dropped the MMUExtDef field from config4.
+                * On R6 the fields always describe the FTLB, and only if it is
+                * present according to Config.MT.
                 */
-               if (cpu_has_mips_r6)
+               if (!cpu_has_mips_r6)
+                       mmuextdef = config4 & MIPS_CONF4_MMUEXTDEF;
+               else if (cpu_has_ftlb)
                        mmuextdef = MIPS_CONF4_MMUEXTDEF_VTLBSIZEEXT;
                else
-                       mmuextdef = config4 & MIPS_CONF4_MMUEXTDEF;
+                       mmuextdef = 0;
 
                switch (mmuextdef) {
                case MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT:
index 423ae83af1fb7043a1daff5d06a079658446de5a..3375745b91980013d76ad2e7d9cd632d31b26af9 100644 (file)
@@ -18,7 +18,7 @@
        .set pop
 /*
  * task_struct *resume(task_struct *prev, task_struct *next,
- *                    struct thread_info *next_ti, int usedfpu)
+ *                    struct thread_info *next_ti)
  */
        .align  7
        LEAF(resume)
        cpu_save_nonscratch a0
        LONG_S  ra, THREAD_REG31(a0)
 
-       /*
-        * check if we need to save FPU registers
-        */
-       .set push
-       .set noreorder
-       beqz    a3, 1f
-        PTR_L  t3, TASK_THREAD_INFO(a0)
-       .set pop
-
-       /*
-        * clear saved user stack CU1 bit
-        */
-       LONG_L  t0, ST_OFF(t3)
-       li      t1, ~ST0_CU1
-       and     t0, t0, t1
-       LONG_S  t0, ST_OFF(t3)
-
-       .set push
-       .set arch=mips64r2
-       fpu_save_double a0 t0 t1                # c0_status passed in t0
-                                               # clobbers t1
-       .set pop
-1:
-
 #if CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0
        /* Check if we need to store CVMSEG state */
        dmfc0   t0, $11,7       /* CvmMemCtl */
index 5087a4b72e6b9a4ae12fc8acdb6f7f8f318784c5..ac27ef7d4d0ebd8be86798d8191e32c720263625 100644 (file)
  */
 #define ST_OFF (_THREAD_SIZE - 32 - PT_SIZE + PT_STATUS)
 
-/*
- * FPU context is saved iff the process has used it's FPU in the current
- * time slice as indicated by TIF_USEDFPU.  In any case, the CU1 bit for user
- * space STATUS register should be 0, so that a process *always* starts its
- * userland with FPU disabled after each context switch.
- *
- * FPU will be enabled as soon as the process accesses FPU again, through
- * do_cpu() trap.
- */
-
 /*
  * task_struct *resume(task_struct *prev, task_struct *next,
- *                    struct thread_info *next_ti, int usedfpu)
+ *                    struct thread_info *next_ti)
  */
 LEAF(resume)
        mfc0    t1, CP0_STATUS
@@ -50,22 +40,6 @@ LEAF(resume)
        cpu_save_nonscratch a0
        sw      ra, THREAD_REG31(a0)
 
-       beqz    a3, 1f
-
-       PTR_L   t3, TASK_THREAD_INFO(a0)
-
-       /*
-        * clear saved user stack CU1 bit
-        */
-       lw      t0, ST_OFF(t3)
-       li      t1, ~ST0_CU1
-       and     t0, t0, t1
-       sw      t0, ST_OFF(t3)
-
-       fpu_save_single a0, t0                  # clobbers t0
-
-1:
-
 #if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
        PTR_LA  t8, __stack_chk_guard
        LONG_L  t9, TASK_STACK_CANARY(a1)
index 4cc13508d967c4076e0b720b120487281003ed72..65a74e4f0f456d1de9d29ed83a62e1bcc6e644fc 100644 (file)
@@ -36,16 +36,8 @@ NESTED(handle_sys, PT_SIZE, sp)
        lw      t1, PT_EPC(sp)          # skip syscall on return
 
        subu    v0, v0, __NR_O32_Linux  # check syscall number
-       sltiu   t0, v0, __NR_O32_Linux_syscalls + 1
        addiu   t1, 4                   # skip to next instruction
        sw      t1, PT_EPC(sp)
-       beqz    t0, illegal_syscall
-
-       sll     t0, v0, 2
-       la      t1, sys_call_table
-       addu    t1, t0
-       lw      t2, (t1)                # syscall routine
-       beqz    t2, illegal_syscall
 
        sw      a3, PT_R26(sp)          # save a3 for syscall restarting
 
@@ -96,6 +88,16 @@ loads_done:
        li      t1, _TIF_WORK_SYSCALL_ENTRY
        and     t0, t1
        bnez    t0, syscall_trace_entry # -> yes
+syscall_common:
+       sltiu   t0, v0, __NR_O32_Linux_syscalls + 1
+       beqz    t0, illegal_syscall
+
+       sll     t0, v0, 2
+       la      t1, sys_call_table
+       addu    t1, t0
+       lw      t2, (t1)                # syscall routine
+
+       beqz    t2, illegal_syscall
 
        jalr    t2                      # Do The Real Thing (TM)
 
@@ -116,7 +118,7 @@ o32_syscall_exit:
 
 syscall_trace_entry:
        SAVE_STATIC
-       move    s0, t2
+       move    s0, v0
        move    a0, sp
 
        /*
@@ -129,27 +131,18 @@ syscall_trace_entry:
 
 1:     jal     syscall_trace_enter
 
-       bltz    v0, 2f                  # seccomp failed? Skip syscall
+       bltz    v0, 1f                  # seccomp failed? Skip syscall
+
+       move    v0, s0                  # restore syscall
 
-       move    t0, s0
        RESTORE_STATIC
        lw      a0, PT_R4(sp)           # Restore argument registers
        lw      a1, PT_R5(sp)
        lw      a2, PT_R6(sp)
        lw      a3, PT_R7(sp)
-       jalr    t0
-
-       li      t0, -EMAXERRNO - 1      # error?
-       sltu    t0, t0, v0
-       sw      t0, PT_R7(sp)           # set error flag
-       beqz    t0, 1f
-
-       lw      t1, PT_R2(sp)           # syscall number
-       negu    v0                      # error
-       sw      t1, PT_R0(sp)           # save it for syscall restarting
-1:     sw      v0, PT_R2(sp)           # result
+       j       syscall_common
 
-2:     j       syscall_exit
+1:     j       syscall_exit
 
 /* ------------------------------------------------------------------------ */
 
@@ -599,3 +592,5 @@ EXPORT(sys_call_table)
        PTR     sys_memfd_create
        PTR     sys_bpf                         /* 4355 */
        PTR     sys_execveat
+       PTR     sys_userfaultfd
+       PTR     sys_membarrier
index a6f6b762c47a4c5a2d395e13a1d564964595abe1..e732981cf99fde26181f1db3bcb65ebd86ea4a0d 100644 (file)
@@ -39,18 +39,11 @@ NESTED(handle_sys64, PT_SIZE, sp)
        .set    at
 #endif
 
-       dsubu   t0, v0, __NR_64_Linux   # check syscall number
-       sltiu   t0, t0, __NR_64_Linux_syscalls + 1
 #if !defined(CONFIG_MIPS32_O32) && !defined(CONFIG_MIPS32_N32)
        ld      t1, PT_EPC(sp)          # skip syscall on return
        daddiu  t1, 4                   # skip to next instruction
        sd      t1, PT_EPC(sp)
 #endif
-       beqz    t0, illegal_syscall
-
-       dsll    t0, v0, 3               # offset into table
-       ld      t2, (sys_call_table - (__NR_64_Linux * 8))(t0)
-                                       # syscall routine
 
        sd      a3, PT_R26(sp)          # save a3 for syscall restarting
 
@@ -59,6 +52,17 @@ NESTED(handle_sys64, PT_SIZE, sp)
        and     t0, t1, t0
        bnez    t0, syscall_trace_entry
 
+syscall_common:
+       dsubu   t2, v0, __NR_64_Linux
+       sltiu   t0, t2, __NR_64_Linux_syscalls + 1
+       beqz    t0, illegal_syscall
+
+       dsll    t0, t2, 3               # offset into table
+       dla     t2, sys_call_table
+       daddu   t0, t2, t0
+       ld      t2, (t0)                # syscall routine
+       beqz    t2, illegal_syscall
+
        jalr    t2                      # Do The Real Thing (TM)
 
        li      t0, -EMAXERRNO - 1      # error?
@@ -78,14 +82,14 @@ n64_syscall_exit:
 
 syscall_trace_entry:
        SAVE_STATIC
-       move    s0, t2
+       move    s0, v0
        move    a0, sp
        move    a1, v0
        jal     syscall_trace_enter
 
-       bltz    v0, 2f                  # seccomp failed? Skip syscall
+       bltz    v0, 1f                  # seccomp failed? Skip syscall
 
-       move    t0, s0
+       move    v0, s0
        RESTORE_STATIC
        ld      a0, PT_R4(sp)           # Restore argument registers
        ld      a1, PT_R5(sp)
@@ -93,19 +97,9 @@ syscall_trace_entry:
        ld      a3, PT_R7(sp)
        ld      a4, PT_R8(sp)
        ld      a5, PT_R9(sp)
-       jalr    t0
-
-       li      t0, -EMAXERRNO - 1      # error?
-       sltu    t0, t0, v0
-       sd      t0, PT_R7(sp)           # set error flag
-       beqz    t0, 1f
-
-       ld      t1, PT_R2(sp)           # syscall number
-       dnegu   v0                      # error
-       sd      t1, PT_R0(sp)           # save it for syscall restarting
-1:     sd      v0, PT_R2(sp)           # result
+       j       syscall_common
 
-2:     j       syscall_exit
+1:     j       syscall_exit
 
 illegal_syscall:
        /* This also isn't a 64-bit syscall, throw an error.  */
@@ -436,4 +430,6 @@ EXPORT(sys_call_table)
        PTR     sys_memfd_create
        PTR     sys_bpf                         /* 5315 */
        PTR     sys_execveat
+       PTR     sys_userfaultfd
+       PTR     sys_membarrier
        .size   sys_call_table,.-sys_call_table
index 4b2010654c463158b7dee80194de736195c04595..c794843975845df2e0a9d9c0c0fd14dad1ed17ec 100644 (file)
@@ -52,6 +52,7 @@ NESTED(handle_sysn32, PT_SIZE, sp)
        and     t0, t1, t0
        bnez    t0, n32_syscall_trace_entry
 
+syscall_common:
        jalr    t2                      # Do The Real Thing (TM)
 
        li      t0, -EMAXERRNO - 1      # error?
@@ -75,9 +76,9 @@ n32_syscall_trace_entry:
        move    a1, v0
        jal     syscall_trace_enter
 
-       bltz    v0, 2f                  # seccomp failed? Skip syscall
+       bltz    v0, 1f                  # seccomp failed? Skip syscall
 
-       move    t0, s0
+       move    t2, s0
        RESTORE_STATIC
        ld      a0, PT_R4(sp)           # Restore argument registers
        ld      a1, PT_R5(sp)
@@ -85,19 +86,9 @@ n32_syscall_trace_entry:
        ld      a3, PT_R7(sp)
        ld      a4, PT_R8(sp)
        ld      a5, PT_R9(sp)
-       jalr    t0
+       j       syscall_common
 
-       li      t0, -EMAXERRNO - 1      # error?
-       sltu    t0, t0, v0
-       sd      t0, PT_R7(sp)           # set error flag
-       beqz    t0, 1f
-
-       ld      t1, PT_R2(sp)           # syscall number
-       dnegu   v0                      # error
-       sd      t1, PT_R0(sp)           # save it for syscall restarting
-1:     sd      v0, PT_R2(sp)           # result
-
-2:     j       syscall_exit
+1:     j       syscall_exit
 
 not_n32_scall:
        /* This is not an n32 compatibility syscall, pass it on to
@@ -429,4 +420,6 @@ EXPORT(sysn32_call_table)
        PTR     sys_memfd_create
        PTR     sys_bpf
        PTR     compat_sys_execveat             /* 6320 */
+       PTR     sys_userfaultfd
+       PTR     sys_membarrier
        .size   sysn32_call_table,.-sysn32_call_table
index f543ff4feef99f8c4ce02554f4dd54da1752b6de..6369cfd390c6330269b05eb095020dafa6cdc048 100644 (file)
@@ -87,6 +87,7 @@ loads_done:
        and     t0, t1, t0
        bnez    t0, trace_a_syscall
 
+syscall_common:
        jalr    t2                      # Do The Real Thing (TM)
 
        li      t0, -EMAXERRNO - 1      # error?
@@ -130,9 +131,9 @@ trace_a_syscall:
 
 1:     jal     syscall_trace_enter
 
-       bltz    v0, 2f                  # seccomp failed? Skip syscall
+       bltz    v0, 1f                  # seccomp failed? Skip syscall
 
-       move    t0, s0
+       move    t2, s0
        RESTORE_STATIC
        ld      a0, PT_R4(sp)           # Restore argument registers
        ld      a1, PT_R5(sp)
@@ -142,19 +143,9 @@ trace_a_syscall:
        ld      a5, PT_R9(sp)
        ld      a6, PT_R10(sp)
        ld      a7, PT_R11(sp)          # For indirect syscalls
-       jalr    t0
+       j       syscall_common
 
-       li      t0, -EMAXERRNO - 1      # error?
-       sltu    t0, t0, v0
-       sd      t0, PT_R7(sp)           # set error flag
-       beqz    t0, 1f
-
-       ld      t1, PT_R2(sp)           # syscall number
-       dnegu   v0                      # error
-       sd      t1, PT_R0(sp)           # save it for syscall restarting
-1:     sd      v0, PT_R2(sp)           # result
-
-2:     j       syscall_exit
+1:     j       syscall_exit
 
 /* ------------------------------------------------------------------------ */
 
@@ -584,4 +575,6 @@ EXPORT(sys32_call_table)
        PTR     sys_memfd_create
        PTR     sys_bpf                         /* 4355 */
        PTR     compat_sys_execveat
+       PTR     sys_userfaultfd
+       PTR     sys_membarrier
        .size   sys32_call_table,.-sys32_call_table
index 35b8316002f8420d863696cdf31255d1311ead4b..479515109e5badec96942ee594e3a450ab011f11 100644 (file)
@@ -338,7 +338,7 @@ static void __init bootmem_init(void)
                if (end <= reserved_end)
                        continue;
 #ifdef CONFIG_BLK_DEV_INITRD
-               /* mapstart should be after initrd_end */
+               /* Skip zones before initrd and initrd itself */
                if (initrd_end && end <= (unsigned long)PFN_UP(__pa(initrd_end)))
                        continue;
 #endif
@@ -371,6 +371,14 @@ static void __init bootmem_init(void)
                max_low_pfn = PFN_DOWN(HIGHMEM_START);
        }
 
+#ifdef CONFIG_BLK_DEV_INITRD
+       /*
+        * mapstart should be after initrd_end
+        */
+       if (initrd_end)
+               mapstart = max(mapstart, (unsigned long)PFN_UP(__pa(initrd_end)));
+#endif
+
        /*
         * Initialize the boot-time allocator with low memory only.
         */
index a31896c33716d424bb30397c17b29af07c6728bb..bd4385a8e6e86f7fbb9ca6d988f5eee155b9a8c7 100644 (file)
@@ -42,6 +42,7 @@
 #include <asm/mmu_context.h>
 #include <asm/time.h>
 #include <asm/setup.h>
+#include <asm/maar.h>
 
 cpumask_t cpu_callin_map;              /* Bitmask of started secondaries */
 
@@ -157,6 +158,7 @@ asmlinkage void start_secondary(void)
        mips_clockevent_init();
        mp_ops->init_secondary();
        cpu_report();
+       maar_init();
 
        /*
         * XXX parity protection should be folded in here when it's converted
index cd4c129ce7434d60fc6af74bb6b764b536de4dda..49ff3bfc007e534529d0f61d21b6fddd6578d145 100644 (file)
@@ -55,6 +55,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
        { "msa_disabled", VCPU_STAT(msa_disabled_exits), KVM_STAT_VCPU },
        { "flush_dcache", VCPU_STAT(flush_dcache_exits), KVM_STAT_VCPU },
        { "halt_successful_poll", VCPU_STAT(halt_successful_poll), KVM_STAT_VCPU },
+       { "halt_attempted_poll", VCPU_STAT(halt_attempted_poll), KVM_STAT_VCPU },
        { "halt_wakeup",  VCPU_STAT(halt_wakeup),        KVM_STAT_VCPU },
        {NULL}
 };
index f6c44dd332e2a388d28e5882a0c47e84ed3ca3f9..d6d07ad56180fa7438595994833aef5e60628350 100644 (file)
@@ -64,6 +64,9 @@ void __init prom_init_env(void)
        }
        if (memsize == 0)
                memsize = 256;
+
+       loongson_sysconf.nr_uarts = 1;
+
        pr_info("memsize=%u, highmemsize=%u\n", memsize, highmemsize);
 #else
        struct boot_params *boot_p;
index a914dc1cb6d1bc339cf44cc0c5aeac887a2e5f74..d8117be729a20ee26d2df8bb42a6f58b9670f513 100644 (file)
@@ -100,7 +100,7 @@ static gfp_t massage_gfp_flags(const struct device *dev, gfp_t gfp)
        else
 #endif
 #if defined(CONFIG_ZONE_DMA) && !defined(CONFIG_ZONE_DMA32)
-            if (dev->coherent_dma_mask < DMA_BIT_MASK(64))
+            if (dev->coherent_dma_mask < DMA_BIT_MASK(sizeof(phys_addr_t) * 8))
                dma_flag = __GFP_DMA;
        else
 #endif
index 66d0f49c5bec4bab02d8e2e194570527d9ccd4e8..8770e619185eb034b317ce3de837c5185ba05511 100644 (file)
@@ -44,6 +44,7 @@
 #include <asm/pgalloc.h>
 #include <asm/tlb.h>
 #include <asm/fixmap.h>
+#include <asm/maar.h>
 
 /*
  * We have up to 8 empty zeroed pages so we can map one of the right colour
@@ -252,6 +253,119 @@ void __init fixrange_init(unsigned long start, unsigned long end,
 #endif
 }
 
+unsigned __weak platform_maar_init(unsigned num_pairs)
+{
+       struct maar_config cfg[BOOT_MEM_MAP_MAX];
+       unsigned i, num_configured, num_cfg = 0;
+       phys_addr_t skip;
+
+       for (i = 0; i < boot_mem_map.nr_map; i++) {
+               switch (boot_mem_map.map[i].type) {
+               case BOOT_MEM_RAM:
+               case BOOT_MEM_INIT_RAM:
+                       break;
+               default:
+                       continue;
+               }
+
+               skip = 0x10000 - (boot_mem_map.map[i].addr & 0xffff);
+
+               cfg[num_cfg].lower = boot_mem_map.map[i].addr;
+               cfg[num_cfg].lower += skip;
+
+               cfg[num_cfg].upper = cfg[num_cfg].lower;
+               cfg[num_cfg].upper += boot_mem_map.map[i].size - 1;
+               cfg[num_cfg].upper -= skip;
+
+               cfg[num_cfg].attrs = MIPS_MAAR_S;
+               num_cfg++;
+       }
+
+       num_configured = maar_config(cfg, num_cfg, num_pairs);
+       if (num_configured < num_cfg)
+               pr_warn("Not enough MAAR pairs (%u) for all bootmem regions (%u)\n",
+                       num_pairs, num_cfg);
+
+       return num_configured;
+}
+
+void maar_init(void)
+{
+       unsigned num_maars, used, i;
+       phys_addr_t lower, upper, attr;
+       static struct {
+               struct maar_config cfgs[3];
+               unsigned used;
+       } recorded = { { { 0 } }, 0 };
+
+       if (!cpu_has_maar)
+               return;
+
+       /* Detect the number of MAARs */
+       write_c0_maari(~0);
+       back_to_back_c0_hazard();
+       num_maars = read_c0_maari() + 1;
+
+       /* MAARs should be in pairs */
+       WARN_ON(num_maars % 2);
+
+       /* Set MAARs using values we recorded already */
+       if (recorded.used) {
+               used = maar_config(recorded.cfgs, recorded.used, num_maars / 2);
+               BUG_ON(used != recorded.used);
+       } else {
+               /* Configure the required MAARs */
+               used = platform_maar_init(num_maars / 2);
+       }
+
+       /* Disable any further MAARs */
+       for (i = (used * 2); i < num_maars; i++) {
+               write_c0_maari(i);
+               back_to_back_c0_hazard();
+               write_c0_maar(0);
+               back_to_back_c0_hazard();
+       }
+
+       if (recorded.used)
+               return;
+
+       pr_info("MAAR configuration:\n");
+       for (i = 0; i < num_maars; i += 2) {
+               write_c0_maari(i);
+               back_to_back_c0_hazard();
+               upper = read_c0_maar();
+
+               write_c0_maari(i + 1);
+               back_to_back_c0_hazard();
+               lower = read_c0_maar();
+
+               attr = lower & upper;
+               lower = (lower & MIPS_MAAR_ADDR) << 4;
+               upper = ((upper & MIPS_MAAR_ADDR) << 4) | 0xffff;
+
+               pr_info("  [%d]: ", i / 2);
+               if (!(attr & MIPS_MAAR_V)) {
+                       pr_cont("disabled\n");
+                       continue;
+               }
+
+               pr_cont("%pa-%pa", &lower, &upper);
+
+               if (attr & MIPS_MAAR_S)
+                       pr_cont(" speculate");
+
+               pr_cont("\n");
+
+               /* Record the setup for use on secondary CPUs */
+               if (used <= ARRAY_SIZE(recorded.cfgs)) {
+                       recorded.cfgs[recorded.used].lower = lower;
+                       recorded.cfgs[recorded.used].upper = upper;
+                       recorded.cfgs[recorded.used].attrs = attr;
+                       recorded.used++;
+               }
+       }
+}
+
 #ifndef CONFIG_NEED_MULTIPLE_NODES
 int page_is_ram(unsigned long pagenr)
 {
@@ -334,69 +448,6 @@ static inline void mem_init_free_highmem(void)
 #endif
 }
 
-unsigned __weak platform_maar_init(unsigned num_pairs)
-{
-       struct maar_config cfg[BOOT_MEM_MAP_MAX];
-       unsigned i, num_configured, num_cfg = 0;
-       phys_addr_t skip;
-
-       for (i = 0; i < boot_mem_map.nr_map; i++) {
-               switch (boot_mem_map.map[i].type) {
-               case BOOT_MEM_RAM:
-               case BOOT_MEM_INIT_RAM:
-                       break;
-               default:
-                       continue;
-               }
-
-               skip = 0x10000 - (boot_mem_map.map[i].addr & 0xffff);
-
-               cfg[num_cfg].lower = boot_mem_map.map[i].addr;
-               cfg[num_cfg].lower += skip;
-
-               cfg[num_cfg].upper = cfg[num_cfg].lower;
-               cfg[num_cfg].upper += boot_mem_map.map[i].size - 1;
-               cfg[num_cfg].upper -= skip;
-
-               cfg[num_cfg].attrs = MIPS_MAAR_S;
-               num_cfg++;
-       }
-
-       num_configured = maar_config(cfg, num_cfg, num_pairs);
-       if (num_configured < num_cfg)
-               pr_warn("Not enough MAAR pairs (%u) for all bootmem regions (%u)\n",
-                       num_pairs, num_cfg);
-
-       return num_configured;
-}
-
-static void maar_init(void)
-{
-       unsigned num_maars, used, i;
-
-       if (!cpu_has_maar)
-               return;
-
-       /* Detect the number of MAARs */
-       write_c0_maari(~0);
-       back_to_back_c0_hazard();
-       num_maars = read_c0_maari() + 1;
-
-       /* MAARs should be in pairs */
-       WARN_ON(num_maars % 2);
-
-       /* Configure the required MAARs */
-       used = platform_maar_init(num_maars / 2);
-
-       /* Disable any further MAARs */
-       for (i = (used * 2); i < num_maars; i++) {
-               write_c0_maari(i);
-               back_to_back_c0_hazard();
-               write_c0_maar(0);
-               back_to_back_c0_hazard();
-       }
-}
-
 void __init mem_init(void)
 {
 #ifdef CONFIG_HIGHMEM
index e92726099be0e40d4a7c1e0903eac239c1ad2497..5d2e0c8d29c0bd0003bae3f7337edbcab5a403c4 100644 (file)
 
 LEAF(sk_load_word)
        is_offset_negative(word)
-       .globl sk_load_word_positive
-sk_load_word_positive:
+FEXPORT(sk_load_word_positive)
        is_offset_in_header(4, word)
        /* Offset within header boundaries */
        PTR_ADDU t1, $r_skb_data, offset
+       .set    reorder
        lw      $r_A, 0(t1)
+       .set    noreorder
 #ifdef CONFIG_CPU_LITTLE_ENDIAN
+# if defined(__mips_isa_rev) && (__mips_isa_rev >= 2)
        wsbh    t0, $r_A
        rotr    $r_A, t0, 16
+# else
+       sll     t0, $r_A, 24
+       srl     t1, $r_A, 24
+       srl     t2, $r_A, 8
+       or      t0, t0, t1
+       andi    t2, t2, 0xff00
+       andi    t1, $r_A, 0xff00
+       or      t0, t0, t2
+       sll     t1, t1, 8
+       or      $r_A, t0, t1
+# endif
 #endif
        jr      $r_ra
         move   $r_ret, zero
@@ -73,15 +86,24 @@ sk_load_word_positive:
 
 LEAF(sk_load_half)
        is_offset_negative(half)
-       .globl sk_load_half_positive
-sk_load_half_positive:
+FEXPORT(sk_load_half_positive)
        is_offset_in_header(2, half)
        /* Offset within header boundaries */
        PTR_ADDU t1, $r_skb_data, offset
+       .set    reorder
        lh      $r_A, 0(t1)
+       .set    noreorder
 #ifdef CONFIG_CPU_LITTLE_ENDIAN
+# if defined(__mips_isa_rev) && (__mips_isa_rev >= 2)
        wsbh    t0, $r_A
        seh     $r_A, t0
+# else
+       sll     t0, $r_A, 24
+       andi    t1, $r_A, 0xff00
+       sra     t0, t0, 16
+       srl     t1, t1, 8
+       or      $r_A, t0, t1
+# endif
 #endif
        jr      $r_ra
         move   $r_ret, zero
@@ -89,8 +111,7 @@ sk_load_half_positive:
 
 LEAF(sk_load_byte)
        is_offset_negative(byte)
-       .globl sk_load_byte_positive
-sk_load_byte_positive:
+FEXPORT(sk_load_byte_positive)
        is_offset_in_header(1, byte)
        /* Offset within header boundaries */
        PTR_ADDU t1, $r_skb_data, offset
@@ -148,23 +169,47 @@ sk_load_byte_positive:
 NESTED(bpf_slow_path_word, (6 * SZREG), $r_sp)
        bpf_slow_path_common(4)
 #ifdef CONFIG_CPU_LITTLE_ENDIAN
+# if defined(__mips_isa_rev) && (__mips_isa_rev >= 2)
        wsbh    t0, $r_s0
        jr      $r_ra
         rotr   $r_A, t0, 16
-#endif
+# else
+       sll     t0, $r_s0, 24
+       srl     t1, $r_s0, 24
+       srl     t2, $r_s0, 8
+       or      t0, t0, t1
+       andi    t2, t2, 0xff00
+       andi    t1, $r_s0, 0xff00
+       or      t0, t0, t2
+       sll     t1, t1, 8
+       jr      $r_ra
+        or     $r_A, t0, t1
+# endif
+#else
        jr      $r_ra
-       move    $r_A, $r_s0
+        move   $r_A, $r_s0
+#endif
 
        END(bpf_slow_path_word)
 
 NESTED(bpf_slow_path_half, (6 * SZREG), $r_sp)
        bpf_slow_path_common(2)
 #ifdef CONFIG_CPU_LITTLE_ENDIAN
+# if defined(__mips_isa_rev) && (__mips_isa_rev >= 2)
        jr      $r_ra
         wsbh   $r_A, $r_s0
-#endif
+# else
+       sll     t0, $r_s0, 8
+       andi    t1, $r_s0, 0xff00
+       andi    t0, t0, 0xff00
+       srl     t1, t1, 8
+       jr      $r_ra
+        or     $r_A, t0, t1
+# endif
+#else
        jr      $r_ra
         move   $r_A, $r_s0
+#endif
 
        END(bpf_slow_path_half)
 
index 0136b4f9c9cde0e4cfa95c8a58d441093d3e8009..10d86d54880ab8541eecf01f8d1f0dd2b3d6ee18 100644 (file)
@@ -82,7 +82,7 @@ void nlm_send_ipi_mask(const struct cpumask *mask, unsigned int action)
 }
 
 /* IRQ_IPI_SMP_FUNCTION Handler */
-void nlm_smp_function_ipi_handler(unsigned int __irq, struct irq_desc *desc)
+void nlm_smp_function_ipi_handler(struct irq_desc *desc)
 {
        unsigned int irq = irq_desc_get_irq(desc);
        clear_c0_eimr(irq);
@@ -92,7 +92,7 @@ void nlm_smp_function_ipi_handler(unsigned int __irq, struct irq_desc *desc)
 }
 
 /* IRQ_IPI_SMP_RESCHEDULE  handler */
-void nlm_smp_resched_ipi_handler(unsigned int __irq, struct irq_desc *desc)
+void nlm_smp_resched_ipi_handler(struct irq_desc *desc)
 {
        unsigned int irq = irq_desc_get_irq(desc);
        clear_c0_eimr(irq);
index f8d0acb4f973635ff323585ce4e5a2166c081a3a..b4fa6413c4e52fbdf71c3ec62126577f1ff8f67a 100644 (file)
@@ -318,7 +318,7 @@ static int ar2315_pci_host_setup(struct ar2315_pci_ctrl *apc)
        return 0;
 }
 
-static void ar2315_pci_irq_handler(unsigned irq, struct irq_desc *desc)
+static void ar2315_pci_irq_handler(struct irq_desc *desc)
 {
        struct ar2315_pci_ctrl *apc = irq_desc_get_handler_data(desc);
        u32 pending = ar2315_pci_reg_read(apc, AR2315_PCI_ISR) &
index ad35a5e6a56c5b4ca978f702a8786b1dcd998fa3..7db963deec737747de9f2e7dedcdf049a93a6115 100644 (file)
@@ -226,7 +226,7 @@ static struct pci_ops ar71xx_pci_ops = {
        .write  = ar71xx_pci_write_config,
 };
 
-static void ar71xx_pci_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void ar71xx_pci_irq_handler(struct irq_desc *desc)
 {
        struct ar71xx_pci_controller *apc;
        void __iomem *base = ath79_reset_base;
index 907d11dd921b3da9b2f540b4ae14eab897a70588..2013dad700dfa9c38c7618067c8fb78fbd0f7350 100644 (file)
@@ -225,7 +225,7 @@ static struct pci_ops ar724x_pci_ops = {
        .write  = ar724x_pci_write,
 };
 
-static void ar724x_pci_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void ar724x_pci_irq_handler(struct irq_desc *desc)
 {
        struct ar724x_pci_controller *apc;
        void __iomem *base;
index 53c8efaf15723c882952a0bcc5572c18f7a9e049..ed6732f9aa874c2557a93de78e9cb1c816320af1 100644 (file)
@@ -129,7 +129,7 @@ static void rt3883_pci_write_cfg32(struct rt3883_pci_controller *rpc,
        rt3883_pci_w32(rpc, val, RT3883_PCI_REG_CFGDATA);
 }
 
-static void rt3883_pci_irq_handler(unsigned int __irq, struct irq_desc *desc)
+static void rt3883_pci_irq_handler(struct irq_desc *desc)
 {
        struct rt3883_pci_controller *rpc;
        u32 pending;
index c6996cf67a5c83e91e465d7d03e25c3ff7d3c89d..b8a0bf5766f2efb64380ae3dedddca3b4782da03 100644 (file)
@@ -311,6 +311,12 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
 
 void pcibios_fixup_bus(struct pci_bus *bus)
 {
+       struct pci_dev *dev = bus->self;
+
+       if (pci_has_flag(PCI_PROBE_ONLY) && dev &&
+           (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
+               pci_read_bridge_bases(bus);
+       }
 }
 
 EXPORT_SYMBOL(PCIBIOS_MIN_IO);
index 8c624a8b9ea29f5611abceb531de09c865e46b7c..4cf77f358395d4bd92d6527ab41578fefa3691d6 100644 (file)
@@ -96,7 +96,7 @@ unsigned int get_c0_compare_int(void)
        return CP0_LEGACY_COMPARE_IRQ;
 }
 
-static void ralink_intc_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void ralink_intc_irq_handler(struct irq_desc *desc)
 {
        u32 pending = rt_intc_r32(INTC_REG_STATUS0);
 
index 6edb9ee6128ebc4d45de622afdf118f0bf5d12ee..1c8dd0f5cd5d1567126f42b67112b5b0f91962a8 100644 (file)
@@ -9,3 +9,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
+generic-y += word-at-a-time.h
index deaa893efba5969a92aed92e6c230f2e00658e6f..3dfe2d31c67b20971701cac89565af0531dec878 100644 (file)
@@ -324,6 +324,7 @@ void pcibios_fixup_bus(struct pci_bus *bus)
        struct pci_dev *dev;
 
        if (bus->self) {
+               pci_read_bridge_bases(bus);
                pcibios_fixup_bridge_resources(bus->self);
        }
 
index 914864eb5a25daf87688f1565b33700b289be0bf..d63330e88379dcc591e29e645b5363f063122f9d 100644 (file)
@@ -61,4 +61,5 @@ generic-y += types.h
 generic-y += unaligned.h
 generic-y += user.h
 generic-y += vga.h
+generic-y += word-at-a-time.h
 generic-y += xor.h
index 73eddda53b8ed014369d1576a5d8ddb7bbeabaab..4eec430d8fa86d7c197c2230285986c692198115 100644 (file)
@@ -28,6 +28,9 @@ BOOTCFLAGS    += -m64
 endif
 ifdef CONFIG_CPU_BIG_ENDIAN
 BOOTCFLAGS     += -mbig-endian
+else
+BOOTCFLAGS     += -mlittle-endian
+BOOTCFLAGS     += $(call cc-option,-mabi=elfv2)
 endif
 
 BOOTAFLAGS     := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc
index 6bc0ee4b1070a83de003d1c74ec64f818bd3dacb..2c041b535a64ed58d3be2aa79916f94308190b92 100644 (file)
@@ -111,7 +111,7 @@ CONFIG_SCSI_QLA_FC=m
 CONFIG_SCSI_QLA_ISCSI=m
 CONFIG_SCSI_LPFC=m
 CONFIG_SCSI_VIRTIO=m
-CONFIG_SCSI_DH=m
+CONFIG_SCSI_DH=y
 CONFIG_SCSI_DH_RDAC=m
 CONFIG_SCSI_DH_ALUA=m
 CONFIG_ATA=y
index 7991f37e5fe2a174fd3284a4fb1b5e72d2ab267a..36871a4bfa54293b2e70851ea1aa4c1a379dd1dd 100644 (file)
@@ -114,7 +114,7 @@ CONFIG_SCSI_QLA_FC=m
 CONFIG_SCSI_QLA_ISCSI=m
 CONFIG_SCSI_LPFC=m
 CONFIG_SCSI_VIRTIO=m
-CONFIG_SCSI_DH=m
+CONFIG_SCSI_DH=y
 CONFIG_SCSI_DH_RDAC=m
 CONFIG_SCSI_DH_ALUA=m
 CONFIG_ATA=y
index 0dc42c5082b74a1d4fee5709e21100ee0ec8a2df..5f8229e24fe6523a73ef2335a5f480e5f3983911 100644 (file)
@@ -3,7 +3,6 @@
 
 #ifdef __KERNEL__
 
-#include <asm/reg.h>
 
 /* bytes per L1 cache line */
 #if defined(CONFIG_8xx) || defined(CONFIG_403GCX)
@@ -40,12 +39,6 @@ struct ppc64_caches {
 };
 
 extern struct ppc64_caches ppc64_caches;
-
-static inline void logmpp(u64 x)
-{
-       asm volatile(PPC_LOGMPP(R1) : : "r" (x));
-}
-
 #endif /* __powerpc64__ && ! __ASSEMBLY__ */
 
 #if defined(__ASSEMBLY__)
index 98eebbf663405c59ebcc3174d8619773f9813ac1..887c259556dff8e6a2f534ec38355d77a90fbeda 100644 (file)
@@ -44,6 +44,7 @@
 #ifdef CONFIG_KVM_MMIO
 #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
 #endif
+#define KVM_HALT_POLL_NS_DEFAULT 500000
 
 /* These values are internal and can be increased later */
 #define KVM_NR_IRQCHIPS          1
@@ -108,6 +109,7 @@ struct kvm_vcpu_stat {
        u32 dec_exits;
        u32 ext_intr_exits;
        u32 halt_successful_poll;
+       u32 halt_attempted_poll;
        u32 halt_wakeup;
        u32 dbell_exits;
        u32 gdbell_exits;
@@ -295,8 +297,6 @@ struct kvmppc_vcore {
        u32 arch_compat;
        ulong pcr;
        ulong dpdes;            /* doorbell state (POWER8) */
-       void *mpp_buffer; /* Micro Partition Prefetch buffer */
-       bool mpp_buffer_is_valid;
        ulong conferring_threads;
 };
 
index cab6753f1be56e3f1810be80d50cf94524eaa04b..3f191f573d4f1f487b5e417ddd55eaed8d49951d 100644 (file)
@@ -61,8 +61,13 @@ struct machdep_calls {
                                               unsigned long addr,
                                               unsigned char *hpte_slot_array,
                                               int psize, int ssize, int local);
-       /* special for kexec, to be called in real mode, linear mapping is
-        * destroyed as well */
+       /*
+        * Special for kexec.
+        * To be called in real mode with interrupts disabled. No locks are
+        * taken as such, concurrent access on pre POWER5 hardware could result
+        * in a deadlock.
+        * The linear mapping is destroyed as well.
+        */
        void            (*hpte_clear_all)(void);
 
        void __iomem *  (*ioremap)(phys_addr_t addr, unsigned long size,
index 790f5d1d9a4624d6f17bdde78706be7240d29ad2..7ab04fc59e2462917501a7f6a1b8727be3685163 100644 (file)
 #define PPC_INST_ISEL                  0x7c00001e
 #define PPC_INST_ISEL_MASK             0xfc00003e
 #define PPC_INST_LDARX                 0x7c0000a8
-#define PPC_INST_LOGMPP                        0x7c0007e4
 #define PPC_INST_LSWI                  0x7c0004aa
 #define PPC_INST_LSWX                  0x7c00042a
 #define PPC_INST_LWARX                 0x7c000028
 #define __PPC_EH(eh)   0
 #endif
 
-/* POWER8 Micro Partition Prefetch (MPP) parameters */
-/* Address mask is common for LOGMPP instruction and MPPR SPR */
-#define PPC_MPPE_ADDRESS_MASK 0xffffffffc000ULL
-
-/* Bits 60 and 61 of MPP SPR should be set to one of the following */
-/* Aborting the fetch is indeed setting 00 in the table size bits */
-#define PPC_MPPR_FETCH_ABORT (0x0ULL << 60)
-#define PPC_MPPR_FETCH_WHOLE_TABLE (0x2ULL << 60)
-
-/* Bits 54 and 55 of register for LOGMPP instruction should be set to: */
-#define PPC_LOGMPP_LOG_L2 (0x02ULL << 54)
-#define PPC_LOGMPP_LOG_L2L3 (0x01ULL << 54)
-#define PPC_LOGMPP_LOG_ABORT (0x03ULL << 54)
-
 /* Deal with instructions that older assemblers aren't aware of */
 #define        PPC_DCBAL(a, b)         stringify_in_c(.long PPC_INST_DCBAL | \
                                        __PPC_RA(a) | __PPC_RB(b))
 #define PPC_LDARX(t, a, b, eh) stringify_in_c(.long PPC_INST_LDARX | \
                                        ___PPC_RT(t) | ___PPC_RA(a) | \
                                        ___PPC_RB(b) | __PPC_EH(eh))
-#define PPC_LOGMPP(b)          stringify_in_c(.long PPC_INST_LOGMPP | \
-                                       __PPC_RB(b))
 #define PPC_LWARX(t, a, b, eh) stringify_in_c(.long PPC_INST_LWARX | \
                                        ___PPC_RT(t) | ___PPC_RA(a) | \
                                        ___PPC_RB(b) | __PPC_EH(eh))
index 25784cc959a072a9dc50d0b596f28d0d3f56cc59..1e155ca6d33cf906affd34bf05e6be6409356892 100644 (file)
@@ -59,14 +59,14 @@ enum qe_ic_grp_id {
 
 #ifdef CONFIG_QUICC_ENGINE
 void qe_ic_init(struct device_node *node, unsigned int flags,
-               void (*low_handler)(unsigned int irq, struct irq_desc *desc),
-               void (*high_handler)(unsigned int irq, struct irq_desc *desc));
+               void (*low_handler)(struct irq_desc *desc),
+               void (*high_handler)(struct irq_desc *desc));
 unsigned int qe_ic_get_low_irq(struct qe_ic *qe_ic);
 unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic);
 #else
 static inline void qe_ic_init(struct device_node *node, unsigned int flags,
-               void (*low_handler)(unsigned int irq, struct irq_desc *desc),
-               void (*high_handler)(unsigned int irq, struct irq_desc *desc))
+               void (*low_handler)(struct irq_desc *desc),
+               void (*high_handler)(struct irq_desc *desc))
 {}
 static inline unsigned int qe_ic_get_low_irq(struct qe_ic *qe_ic)
 { return 0; }
@@ -78,8 +78,7 @@ void qe_ic_set_highest_priority(unsigned int virq, int high);
 int qe_ic_set_priority(unsigned int virq, unsigned int priority);
 int qe_ic_set_high_priority(unsigned int virq, unsigned int priority, int high);
 
-static inline void qe_ic_cascade_low_ipic(unsigned int irq,
-                                         struct irq_desc *desc)
+static inline void qe_ic_cascade_low_ipic(struct irq_desc *desc)
 {
        struct qe_ic *qe_ic = irq_desc_get_handler_data(desc);
        unsigned int cascade_irq = qe_ic_get_low_irq(qe_ic);
@@ -88,8 +87,7 @@ static inline void qe_ic_cascade_low_ipic(unsigned int irq,
                generic_handle_irq(cascade_irq);
 }
 
-static inline void qe_ic_cascade_high_ipic(unsigned int irq,
-                                          struct irq_desc *desc)
+static inline void qe_ic_cascade_high_ipic(struct irq_desc *desc)
 {
        struct qe_ic *qe_ic = irq_desc_get_handler_data(desc);
        unsigned int cascade_irq = qe_ic_get_high_irq(qe_ic);
@@ -98,8 +96,7 @@ static inline void qe_ic_cascade_high_ipic(unsigned int irq,
                generic_handle_irq(cascade_irq);
 }
 
-static inline void qe_ic_cascade_low_mpic(unsigned int irq,
-                                         struct irq_desc *desc)
+static inline void qe_ic_cascade_low_mpic(struct irq_desc *desc)
 {
        struct qe_ic *qe_ic = irq_desc_get_handler_data(desc);
        unsigned int cascade_irq = qe_ic_get_low_irq(qe_ic);
@@ -111,8 +108,7 @@ static inline void qe_ic_cascade_low_mpic(unsigned int irq,
        chip->irq_eoi(&desc->irq_data);
 }
 
-static inline void qe_ic_cascade_high_mpic(unsigned int irq,
-                                          struct irq_desc *desc)
+static inline void qe_ic_cascade_high_mpic(struct irq_desc *desc)
 {
        struct qe_ic *qe_ic = irq_desc_get_handler_data(desc);
        unsigned int cascade_irq = qe_ic_get_high_irq(qe_ic);
@@ -124,8 +120,7 @@ static inline void qe_ic_cascade_high_mpic(unsigned int irq,
        chip->irq_eoi(&desc->irq_data);
 }
 
-static inline void qe_ic_cascade_muxed_mpic(unsigned int irq,
-                                           struct irq_desc *desc)
+static inline void qe_ic_cascade_muxed_mpic(struct irq_desc *desc)
 {
        struct qe_ic *qe_ic = irq_desc_get_handler_data(desc);
        unsigned int cascade_irq;
index aa1cc5f015eeee564e2c1c83f295acb7d0c523d8..a908ada8e0a5353f5fce19af6ad3e59779ce2e0e 100644 (file)
 #define   CTRL_TE      0x00c00000      /* thread enable */
 #define   CTRL_RUNLATCH        0x1
 #define SPRN_DAWR      0xB4
-#define SPRN_MPPR      0xB8    /* Micro Partition Prefetch Register */
 #define SPRN_RPR       0xBA    /* Relative Priority Register */
 #define SPRN_CIABR     0xBB
 #define   CIABR_PRIV           0x3
index 71f2b3f02cf8848425b26d92e6bd6f650ce726f8..126d0c4f9b7ddc9b98a90564180d24191204875a 100644 (file)
@@ -368,3 +368,5 @@ SYSCALL_SPU(memfd_create)
 SYSCALL_SPU(bpf)
 COMPAT_SYS(execveat)
 PPC64ONLY(switch_endian)
+SYSCALL_SPU(userfaultfd)
+SYSCALL_SPU(membarrier)
index 5653d7cc3e2404f35443682e6252b46e66103f09..ae59d5b672b0b9f8f9b8c6907e19ea5d14fd11e7 100644 (file)
@@ -39,7 +39,7 @@
 
 extern int tsi108_setup_pci(struct device_node *dev, u32 cfg_phys, int primary);
 extern void tsi108_pci_int_init(struct device_node *node);
-extern void tsi108_irq_cascade(unsigned int irq, struct irq_desc *desc);
+extern void tsi108_irq_cascade(struct irq_desc *desc);
 extern void tsi108_clear_pci_cfg_error(void);
 
 #endif                         /*  _ASM_POWERPC_TSI108_PCI_H */
index f4f8b667d75be5614bd8f706b5573e21cdd9a685..13411be86041ced7c5e81921f93ec50d21c1afdc 100644 (file)
@@ -12,7 +12,7 @@
 #include <uapi/asm/unistd.h>
 
 
-#define __NR_syscalls          364
+#define __NR_syscalls          366
 
 #define __NR__exit __NR_exit
 #define NR_syscalls    __NR_syscalls
index 5b3a903adae6d761effa550a802ed5d6a2aeb656..e4396a7d0f7cf5627a92ea8c07756aba6bc52c7a 100644 (file)
@@ -40,6 +40,11 @@ static inline bool has_zero(unsigned long val, unsigned long *data, const struct
        return (val + c->high_bits) & ~rhs;
 }
 
+static inline unsigned long zero_bytemask(unsigned long mask)
+{
+       return ~1ul << __fls(mask);
+}
+
 #else
 
 #ifdef CONFIG_64BIT
index e4aa173dae62361e3823f3eda242b2802cdd5da1..6337738018aad4768c1276079ab89562d186fc70 100644 (file)
 #define __NR_bpf               361
 #define __NR_execveat          362
 #define __NR_switch_endian     363
+#define __NR_userfaultfd       364
+#define __NR_membarrier                365
 
 #endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */
index 59503ed98e5fcd5bdb783b23a074eadf4ac3fafa..3f1472a78f393434e2b77df6ab2e24587566befe 100644 (file)
@@ -303,7 +303,7 @@ int dma_set_coherent_mask(struct device *dev, u64 mask)
        dev->coherent_dma_mask = mask;
        return 0;
 }
-EXPORT_SYMBOL_GPL(dma_set_coherent_mask);
+EXPORT_SYMBOL(dma_set_coherent_mask);
 
 #define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16)
 
index 45096033d37bf7082bfe80dd7a25c782a4b1943a..290559df1e8b305d941ab52d7022a818b92ee8b8 100644 (file)
@@ -441,7 +441,7 @@ void migrate_irqs(void)
 
                chip = irq_data_get_irq_chip(data);
 
-               cpumask_and(mask, data->affinity, map);
+               cpumask_and(mask, irq_data_get_affinity_mask(data), map);
                if (cpumask_any(mask) >= nr_cpu_ids) {
                        pr_warn("Breaking affinity for irq %i\n", irq);
                        cpumask_copy(mask, map);
index a1d0632d97c69ff5f5ad2e8ccc2a53487c5d8d14..7587b2ae5f779d6b8c97cb48e8325db0770f42b4 100644 (file)
@@ -1032,7 +1032,13 @@ void pcibios_set_master(struct pci_dev *dev)
 
 void pcibios_fixup_bus(struct pci_bus *bus)
 {
-       /* Fixup the bus */
+       /* When called from the generic PCI probe, read PCI<->PCI bridge
+        * bases. This is -not- called when generating the PCI tree from
+        * the OF device-tree.
+        */
+       pci_read_bridge_bases(bus);
+
+       /* Now fixup the bus bus */
        pcibios_setup_bus_self(bus);
 
        /* Now fixup devices on that bus */
index 84bf934cf74874eab39926b292c6fa7534829d24..5a753fae8265ae8fc2f9e2e99152c0192fd62b9d 100644 (file)
@@ -1043,6 +1043,9 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
+       if (!rtas.entry)
+               return -EINVAL;
+
        if (copy_from_user(&args, uargs, 3 * sizeof(u32)) != 0)
                return -EFAULT;
 
index bb02e9f6944e264f52e13d3f4cc1ea51beaccce2..ad8c9db61237223c3b807e3a9afed1487c44af1e 100644 (file)
@@ -38,6 +38,7 @@
 #include <asm/udbg.h>
 #include <asm/mmu_context.h>
 #include <asm/epapr_hcalls.h>
+#include <asm/code-patching.h>
 
 #define DBG(fmt...)
 
@@ -109,6 +110,8 @@ notrace unsigned long __init early_init(unsigned long dt_ptr)
  * This is called very early on the boot process, after a minimal
  * MMU environment has been set up but before MMU_init is called.
  */
+extern unsigned int memset_nocache_branch; /* Insn to be replaced by NOP */
+
 notrace void __init machine_init(u64 dt_ptr)
 {
        lockdep_init();
@@ -116,6 +119,9 @@ notrace void __init machine_init(u64 dt_ptr)
        /* Enable early debugging if any specified (see udbg.h) */
        udbg_early_init();
 
+       patch_instruction((unsigned int *)&memcpy, PPC_INST_NOP);
+       patch_instruction(&memset_nocache_branch, PPC_INST_NOP);
+
        /* Do some early initialization based on the flat device tree */
        early_init_devtree(__va(dt_ptr));
 
index d75bf325f54a17ebf4e19dda7a85eed271e4f3ed..099c79d8c160fd59c2d0e28217c1348f03c08cbf 100644 (file)
@@ -53,6 +53,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
        { "ext_intr",    VCPU_STAT(ext_intr_exits) },
        { "queue_intr",  VCPU_STAT(queue_intr) },
        { "halt_successful_poll", VCPU_STAT(halt_successful_poll), },
+       { "halt_attempted_poll", VCPU_STAT(halt_attempted_poll), },
        { "halt_wakeup", VCPU_STAT(halt_wakeup) },
        { "pf_storage",  VCPU_STAT(pf_storage) },
        { "sp_storage",  VCPU_STAT(sp_storage) },
@@ -828,12 +829,15 @@ int kvmppc_h_logical_ci_load(struct kvm_vcpu *vcpu)
        unsigned long size = kvmppc_get_gpr(vcpu, 4);
        unsigned long addr = kvmppc_get_gpr(vcpu, 5);
        u64 buf;
+       int srcu_idx;
        int ret;
 
        if (!is_power_of_2(size) || (size > sizeof(buf)))
                return H_TOO_HARD;
 
+       srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
        ret = kvm_io_bus_read(vcpu, KVM_MMIO_BUS, addr, size, &buf);
+       srcu_read_unlock(&vcpu->kvm->srcu, srcu_idx);
        if (ret != 0)
                return H_TOO_HARD;
 
@@ -868,6 +872,7 @@ int kvmppc_h_logical_ci_store(struct kvm_vcpu *vcpu)
        unsigned long addr = kvmppc_get_gpr(vcpu, 5);
        unsigned long val = kvmppc_get_gpr(vcpu, 6);
        u64 buf;
+       int srcu_idx;
        int ret;
 
        switch (size) {
@@ -891,7 +896,9 @@ int kvmppc_h_logical_ci_store(struct kvm_vcpu *vcpu)
                return H_TOO_HARD;
        }
 
+       srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
        ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, addr, size, &buf);
+       srcu_read_unlock(&vcpu->kvm->srcu, srcu_idx);
        if (ret != 0)
                return H_TOO_HARD;
 
index 9754e6815e521c80d6b8cadfe9123ab24b97c014..9c26c5a96ea2bc0ea9d2286f4995b2d629be9003 100644 (file)
@@ -36,7 +36,6 @@
 
 #include <asm/reg.h>
 #include <asm/cputable.h>
-#include <asm/cache.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 #include <asm/uaccess.h>
 
 static DECLARE_BITMAP(default_enabled_hcalls, MAX_HCALL_OPCODE/4 + 1);
 
-#if defined(CONFIG_PPC_64K_PAGES)
-#define MPP_BUFFER_ORDER       0
-#elif defined(CONFIG_PPC_4K_PAGES)
-#define MPP_BUFFER_ORDER       3
-#endif
-
 static int dynamic_mt_modes = 6;
 module_param(dynamic_mt_modes, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(dynamic_mt_modes, "Set of allowed dynamic micro-threading modes: 0 (= none), 2, 4, or 6 (= 2 or 4)");
@@ -1455,13 +1448,6 @@ static struct kvmppc_vcore *kvmppc_vcore_create(struct kvm *kvm, int core)
        vcore->kvm = kvm;
        INIT_LIST_HEAD(&vcore->preempt_list);
 
-       vcore->mpp_buffer_is_valid = false;
-
-       if (cpu_has_feature(CPU_FTR_ARCH_207S))
-               vcore->mpp_buffer = (void *)__get_free_pages(
-                       GFP_KERNEL|__GFP_ZERO,
-                       MPP_BUFFER_ORDER);
-
        return vcore;
 }
 
@@ -1894,33 +1880,6 @@ static int on_primary_thread(void)
        return 1;
 }
 
-static void kvmppc_start_saving_l2_cache(struct kvmppc_vcore *vc)
-{
-       phys_addr_t phy_addr, mpp_addr;
-
-       phy_addr = (phys_addr_t)virt_to_phys(vc->mpp_buffer);
-       mpp_addr = phy_addr & PPC_MPPE_ADDRESS_MASK;
-
-       mtspr(SPRN_MPPR, mpp_addr | PPC_MPPR_FETCH_ABORT);
-       logmpp(mpp_addr | PPC_LOGMPP_LOG_L2);
-
-       vc->mpp_buffer_is_valid = true;
-}
-
-static void kvmppc_start_restoring_l2_cache(const struct kvmppc_vcore *vc)
-{
-       phys_addr_t phy_addr, mpp_addr;
-
-       phy_addr = virt_to_phys(vc->mpp_buffer);
-       mpp_addr = phy_addr & PPC_MPPE_ADDRESS_MASK;
-
-       /* We must abort any in-progress save operations to ensure
-        * the table is valid so that prefetch engine knows when to
-        * stop prefetching. */
-       logmpp(mpp_addr | PPC_LOGMPP_LOG_ABORT);
-       mtspr(SPRN_MPPR, mpp_addr | PPC_MPPR_FETCH_WHOLE_TABLE);
-}
-
 /*
  * A list of virtual cores for each physical CPU.
  * These are vcores that could run but their runner VCPU tasks are
@@ -2471,14 +2430,8 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
 
        srcu_idx = srcu_read_lock(&vc->kvm->srcu);
 
-       if (vc->mpp_buffer_is_valid)
-               kvmppc_start_restoring_l2_cache(vc);
-
        __kvmppc_vcore_entry();
 
-       if (vc->mpp_buffer)
-               kvmppc_start_saving_l2_cache(vc);
-
        srcu_read_unlock(&vc->kvm->srcu, srcu_idx);
 
        spin_lock(&vc->lock);
@@ -2692,9 +2645,13 @@ static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 
        while (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE &&
               (vc->vcore_state == VCORE_RUNNING ||
-               vc->vcore_state == VCORE_EXITING))
+               vc->vcore_state == VCORE_EXITING ||
+               vc->vcore_state == VCORE_PIGGYBACK))
                kvmppc_wait_for_exec(vc, vcpu, TASK_UNINTERRUPTIBLE);
 
+       if (vc->vcore_state == VCORE_PREEMPT && vc->runner == NULL)
+               kvmppc_vcore_end_preempt(vc);
+
        if (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE) {
                kvmppc_remove_runnable(vc, vcpu);
                vcpu->stat.signal_exits++;
@@ -3069,14 +3026,8 @@ static void kvmppc_free_vcores(struct kvm *kvm)
 {
        long int i;
 
-       for (i = 0; i < KVM_MAX_VCORES; ++i) {
-               if (kvm->arch.vcores[i] && kvm->arch.vcores[i]->mpp_buffer) {
-                       struct kvmppc_vcore *vc = kvm->arch.vcores[i];
-                       free_pages((unsigned long)vc->mpp_buffer,
-                                  MPP_BUFFER_ORDER);
-               }
+       for (i = 0; i < KVM_MAX_VCORES; ++i)
                kfree(kvm->arch.vcores[i]);
-       }
        kvm->arch.online_vcores = 0;
 }
 
index 2273dcacef39fe9e2257303a18121116044694c6..b98889e9851d07ce28de0e648b44686984b20d0a 100644 (file)
@@ -1257,6 +1257,7 @@ mc_cont:
        bl      kvmhv_accumulate_time
 #endif
 
+       mr      r3, r12
        /* Increment exit count, poke other threads to exit */
        bl      kvmhv_commence_exit
        nop
index ae458f0fd061efea7cdd569c1bdb32970503659c..fd5875179e5c0e6738a1e7867a75f05cbe1fa0c8 100644 (file)
@@ -63,6 +63,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
        { "dec",        VCPU_STAT(dec_exits) },
        { "ext_intr",   VCPU_STAT(ext_intr_exits) },
        { "halt_successful_poll", VCPU_STAT(halt_successful_poll) },
+       { "halt_attempted_poll", VCPU_STAT(halt_attempted_poll) },
        { "halt_wakeup", VCPU_STAT(halt_wakeup) },
        { "doorbell", VCPU_STAT(dbell_exits) },
        { "guest doorbell", VCPU_STAT(gdbell_exits) },
index 2ef50c6294709674ad69167b14ac8a5bede4631e..c44df2dbedd52f5a2726443afe5a9296326b3778 100644 (file)
@@ -73,6 +73,10 @@ CACHELINE_MASK = (L1_CACHE_BYTES-1)
  * Use dcbz on the complete cache lines in the destination
  * to set them to zero.  This requires that the destination
  * area is cacheable.  -- paulus
+ *
+ * During early init, cache might not be active yet, so dcbz cannot be used.
+ * We therefore skip the optimised bloc that uses dcbz. This jump is
+ * replaced by a nop once cache is active. This is done in machine_init()
  */
 _GLOBAL(memset)
        rlwimi  r4,r4,8,16,23
@@ -88,6 +92,8 @@ _GLOBAL(memset)
        subf    r6,r0,r6
        cmplwi  0,r4,0
        bne     2f      /* Use normal procedure if r4 is not zero */
+_GLOBAL(memset_nocache_branch)
+       b       2f      /* Skip optimised bloc until cache is enabled */
 
        clrlwi  r7,r6,32-LG_CACHELINE_BYTES
        add     r8,r7,r5
@@ -128,6 +134,10 @@ _GLOBAL(memset)
  * the destination area is cacheable.
  * We only use this version if the source and dest don't overlap.
  * -- paulus.
+ *
+ * During early init, cache might not be active yet, so dcbz cannot be used.
+ * We therefore jump to generic_memcpy which doesn't use dcbz. This jump is
+ * replaced by a nop once cache is active. This is done in machine_init()
  */
 _GLOBAL(memmove)
        cmplw   0,r3,r4
@@ -135,6 +145,7 @@ _GLOBAL(memmove)
        /* fall through */
 
 _GLOBAL(memcpy)
+       b       generic_memcpy
        add     r7,r3,r5                /* test if the src & dst overlap */
        add     r8,r4,r5
        cmplw   0,r4,r7
index 13befa35d8a8ecdd31611aadb42c6be206ba743e..c8822af10a587389999473171db475eb5462714b 100644 (file)
@@ -582,13 +582,21 @@ static void hpte_decode(struct hash_pte *hpte, unsigned long slot,
  * be when they isi), and we are the only one left.  We rely on our kernel
  * mapping being 0xC0's and the hardware ignoring those two real bits.
  *
+ * This must be called with interrupts disabled.
+ *
+ * Taking the native_tlbie_lock is unsafe here due to the possibility of
+ * lockdep being on. On pre POWER5 hardware, not taking the lock could
+ * cause deadlock. POWER5 and newer not taking the lock is fine. This only
+ * gets called during boot before secondary CPUs have come up and during
+ * crashdump and all bets are off anyway.
+ *
  * TODO: add batching support when enabled.  remember, no dynamic memory here,
  * athough there is the control page available...
  */
 static void native_hpte_clear(void)
 {
        unsigned long vpn = 0;
-       unsigned long slot, slots, flags;
+       unsigned long slot, slots;
        struct hash_pte *hptep = htab_address;
        unsigned long hpte_v;
        unsigned long pteg_count;
@@ -596,13 +604,6 @@ static void native_hpte_clear(void)
 
        pteg_count = htab_hash_mask + 1;
 
-       local_irq_save(flags);
-
-       /* we take the tlbie lock and hold it.  Some hardware will
-        * deadlock if we try to tlbie from two processors at once.
-        */
-       raw_spin_lock(&native_tlbie_lock);
-
        slots = pteg_count * HPTES_PER_GROUP;
 
        for (slot = 0; slot < slots; slot++, hptep++) {
@@ -614,8 +615,8 @@ static void native_hpte_clear(void)
                hpte_v = be64_to_cpu(hptep->v);
 
                /*
-                * Call __tlbie() here rather than tlbie() since we
-                * already hold the native_tlbie_lock.
+                * Call __tlbie() here rather than tlbie() since we can't take the
+                * native_tlbie_lock.
                 */
                if (hpte_v & HPTE_V_VALID) {
                        hpte_decode(hptep, slot, &psize, &apsize, &ssize, &vpn);
@@ -625,8 +626,6 @@ static void native_hpte_clear(void)
        }
 
        asm volatile("eieio; tlbsync; ptesync":::"memory");
-       raw_spin_unlock(&native_tlbie_lock);
-       local_irq_restore(flags);
 }
 
 /*
index 43dafb9d6a46f6c75bb4e4095426c3a1d8a824bd..4d87122cf6a725805d3de6bdf46cc44b9d3f91ef 100644 (file)
@@ -85,7 +85,6 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid,
        BUG_ON(index >= 4096);
 
        vpn = hpt_vpn(ea, vsid, ssize);
-       hash = hpt_hash(vpn, shift, ssize);
        hpte_slot_array = get_hpte_slot_array(pmdp);
        if (psize == MMU_PAGE_4K) {
                /*
@@ -101,6 +100,7 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid,
        valid = hpte_valid(hpte_slot_array, index);
        if (valid) {
                /* update the hpte bits */
+               hash = hpt_hash(vpn, shift, ssize);
                hidx =  hpte_hash_index(hpte_slot_array, index);
                if (hidx & _PTEIDX_SECONDARY)
                        hash = ~hash;
@@ -126,6 +126,7 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid,
        if (!valid) {
                unsigned long hpte_group;
 
+               hash = hpt_hash(vpn, shift, ssize);
                /* insert new entry */
                pa = pmd_pfn(__pmd(old_pmd)) << PAGE_SHIFT;
                new_pmd |= _PAGE_HASHPTE;
index 11090ab4bf59a38f2b78074fd8b7a9e10467656d..0035d146df73a2e2d2ed23c89d0a6b2f36cc667a 100644 (file)
@@ -104,9 +104,10 @@ cpld_pic_get_irq(int offset, u8 ignore, u8 __iomem *statusp,
        return irq_linear_revmap(cpld_pic_host, cpld_irq);
 }
 
-static void
-cpld_pic_cascade(unsigned int irq, struct irq_desc *desc)
+static void cpld_pic_cascade(struct irq_desc *desc)
 {
+       unsigned int irq;
+
        irq = cpld_pic_get_irq(0, PCI_IGNORE, &cpld_regs->pci_status,
                &cpld_regs->pci_mask);
        if (irq != NO_IRQ) {
index 32cae33c4266b990d2dc88d89cc6d6df8ae9a9df..8fb95480fd733c1dbe9fed18612fc999833356c5 100644 (file)
@@ -80,7 +80,7 @@ static struct irq_chip media5200_irq_chip = {
        .irq_mask_ack = media5200_irq_mask,
 };
 
-void media5200_irq_cascade(unsigned int virq, struct irq_desc *desc)
+static void media5200_irq_cascade(struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_desc_get_chip(desc);
        int sub_virq, val;
index 63016621aff8af4807b37ed7af2a7ee078755e4b..78ac19aefa4dd27ac9495d1649bd7ad401107db4 100644 (file)
@@ -191,7 +191,7 @@ static struct irq_chip mpc52xx_gpt_irq_chip = {
        .irq_set_type = mpc52xx_gpt_irq_set_type,
 };
 
-void mpc52xx_gpt_irq_cascade(unsigned int virq, struct irq_desc *desc)
+static void mpc52xx_gpt_irq_cascade(struct irq_desc *desc)
 {
        struct mpc52xx_gpt_priv *gpt = irq_desc_get_handler_data(desc);
        int sub_virq;
index 2944bc84b9d6fc790bc2b3ece7878cdf1ff208ba..4fe2074c88cb94bbb67927a485ec6c17ea27277a 100644 (file)
@@ -196,7 +196,7 @@ static int mpc52xx_extirq_set_type(struct irq_data *d, unsigned int flow_type)
        ctrl_reg |= (type << (22 - (l2irq * 2)));
        out_be32(&intr->ctrl, ctrl_reg);
 
-       __irq_set_handler_locked(d->irq, handler);
+       irq_set_handler_locked(d, handler);
 
        return 0;
 }
index 74861a7fb807d8c2441f3cce86c5921e8c4787f5..60e89fc9c753549e01648cbd95a45a7889221428 100644 (file)
@@ -78,7 +78,7 @@ static struct irq_chip pq2ads_pci_ic = {
        .irq_disable = pq2ads_pci_mask_irq
 };
 
-static void pq2ads_pci_irq_demux(unsigned int irq, struct irq_desc *desc)
+static void pq2ads_pci_irq_demux(struct irq_desc *desc)
 {
        struct pq2ads_pci_pic *priv = irq_desc_get_handler_data(desc);
        u32 stat, mask, pend;
index 7bfb9b184dd4bbc87670fe84a7d34e5fd14bff87..23791de7b688f91aa4b87770a1c5ae40931137a4 100644 (file)
@@ -49,7 +49,7 @@ int __init mpc85xx_common_publish_devices(void)
        return of_platform_bus_probe(NULL, mpc85xx_common_ids, NULL);
 }
 #ifdef CONFIG_CPM2
-static void cpm2_cascade(unsigned int irq, struct irq_desc *desc)
+static void cpm2_cascade(struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_desc_get_chip(desc);
        int cascade_irq;
index b0753e2220862cb1585fefa23aee64889390b4d3..5ac70de3e48ace4d756f4f84157f909fa4f9aa7c 100644 (file)
@@ -192,8 +192,7 @@ void mpc85xx_cds_fixup_bus(struct pci_bus *bus)
 }
 
 #ifdef CONFIG_PPC_I8259
-static void mpc85xx_8259_cascade_handler(unsigned int irq,
-                                        struct irq_desc *desc)
+static void mpc85xx_8259_cascade_handler(struct irq_desc *desc)
 {
        unsigned int cascade_irq = i8259_irq();
 
@@ -202,7 +201,7 @@ static void mpc85xx_8259_cascade_handler(unsigned int irq,
                generic_handle_irq(cascade_irq);
 
        /* check for any interrupts from the shared IRQ line */
-       handle_fasteoi_irq(irq, desc);
+       handle_fasteoi_irq(desc);
 }
 
 static irqreturn_t mpc85xx_8259_cascade_action(int irq, void *dev_id)
index ffdf02121a7cb9ecf51d888cf26126a621faa4c4..f858306dba6aa517f3078f26cbd6b62861b3886c 100644 (file)
@@ -46,7 +46,7 @@
 #endif
 
 #ifdef CONFIG_PPC_I8259
-static void mpc85xx_8259_cascade(unsigned int irq, struct irq_desc *desc)
+static void mpc85xx_8259_cascade(struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_desc_get_chip(desc);
        unsigned int cascade_irq = i8259_irq();
index 55a9682b9529168a56e949779646ef8208693c89..b02d6a5bb03574a6f1967439d13e2ab4aa70b692 100644 (file)
@@ -91,9 +91,10 @@ static inline unsigned int socrates_fpga_pic_get_irq(unsigned int irq)
                        (irq_hw_number_t)i);
 }
 
-void socrates_fpga_pic_cascade(unsigned int irq, struct irq_desc *desc)
+static void socrates_fpga_pic_cascade(struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_desc_get_chip(desc);
+       unsigned int irq = irq_desc_get_irq(desc);
        unsigned int cascade_irq;
 
        /*
index d5b98c0f958aed8c65a112b53f91effc329d5125..845defa1fd19d7e991b1d9ebe30e4fb893763d93 100644 (file)
@@ -17,7 +17,7 @@
 #include <asm/i8259.h>
 
 #ifdef CONFIG_PPC_I8259
-static void mpc86xx_8259_cascade(unsigned int irq, struct irq_desc *desc)
+static void mpc86xx_8259_cascade(struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_desc_get_chip(desc);
        unsigned int cascade_irq = i8259_irq();
index d3037747031d6f55b46da885ec2b173d84a1a276..c289fc77b4ba6c979b3a46b2776b4dc5bbc8bc87 100644 (file)
@@ -214,7 +214,7 @@ void mpc8xx_restart(char *cmd)
        panic("Restart failed\n");
 }
 
-static void cpm_cascade(unsigned int irq, struct irq_desc *desc)
+static void cpm_cascade(struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_desc_get_chip(desc);
        int cascade_irq = cpm_get_irq();
index 306888acb737a0d94a11fc70497b93e7c173e55d..e0e68a1c0d3c20dd5d618e62cdccba2e429af475 100644 (file)
@@ -93,7 +93,7 @@ static void msic_dcr_write(struct axon_msic *msic, unsigned int dcr_n, u32 val)
        dcr_write(msic->dcr_host, dcr_n, val);
 }
 
-static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc)
+static void axon_msi_cascade(struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_desc_get_chip(desc);
        struct axon_msic *msic = irq_desc_get_handler_data(desc);
index a15f1efc295f936d3de64bb17a62d76c86778a1c..9f609fc8d331fc1579216a6283ee281d181fb0b9 100644 (file)
@@ -99,11 +99,12 @@ static void iic_ioexc_eoi(struct irq_data *d)
 {
 }
 
-static void iic_ioexc_cascade(unsigned int irq, struct irq_desc *desc)
+static void iic_ioexc_cascade(struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_desc_get_chip(desc);
        struct cbe_iic_regs __iomem *node_iic =
                (void __iomem *)irq_desc_get_handler_data(desc);
+       unsigned int irq = irq_desc_get_irq(desc);
        unsigned int base = (irq & 0xffffff00) | IIC_IRQ_TYPE_IOEXC;
        unsigned long bits, ack;
        int cascade;
index 1f72f4ab6353cdcee1c2cae3d2f7d01a694a903d..9d27de62dc62755c4800d46bcc8b4409a81a5115 100644 (file)
@@ -199,7 +199,7 @@ static const struct irq_domain_ops spider_host_ops = {
        .xlate = spider_host_xlate,
 };
 
-static void spider_irq_cascade(unsigned int irq, struct irq_desc *desc)
+static void spider_irq_cascade(struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_desc_get_chip(desc);
        struct spider_pic *pic = irq_desc_get_handler_data(desc);
index 15ebc4e8a151695d6b8dbc6130fd82e4d5860b0d..987d1b8d68e3dba186bbceda54631ecdd4c48136 100644 (file)
@@ -363,7 +363,7 @@ void __init chrp_setup_arch(void)
        if (ppc_md.progress) ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0x0);
 }
 
-static void chrp_8259_cascade(unsigned int irq, struct irq_desc *desc)
+static void chrp_8259_cascade(struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_desc_get_chip(desc);
        unsigned int cascade_irq = i8259_irq();
index 9dd154d6f89a9205aa33eff33930e2cb0efc3397..9b7975706bfc7a5538ac24a9ae74ed661ff390f9 100644 (file)
@@ -120,8 +120,7 @@ static unsigned int __hlwd_pic_get_irq(struct irq_domain *h)
        return irq_linear_revmap(h, irq);
 }
 
-static void hlwd_pic_irq_cascade(unsigned int cascade_virq,
-                                     struct irq_desc *desc)
+static void hlwd_pic_irq_cascade(struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_desc_get_chip(desc);
        struct irq_domain *irq_domain = irq_desc_get_handler_data(desc);
index 1613303177e64e6b3b60830c90b6be50a56e01a7..8f65aa3747f5afefbc91c558884b10ad282c3ab3 100644 (file)
@@ -42,7 +42,7 @@
 static phys_addr_t pci_membase;
 static u_char *restart;
 
-static void mvme5100_8259_cascade(unsigned int irq, struct irq_desc *desc)
+static void mvme5100_8259_cascade(struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_desc_get_chip(desc);
        unsigned int cascade_irq = i8259_irq();
index e66ef19433387854820e91a2b515d737fd7fd270..b304a9fe55cc410e2bcbd9693a84bce1d2bf5365 100644 (file)
@@ -63,6 +63,7 @@ static struct irq_chip mpic_pasemi_msi_chip = {
 static void pasemi_msi_teardown_msi_irqs(struct pci_dev *pdev)
 {
        struct msi_desc *entry;
+       irq_hw_number_t hwirq;
 
        pr_debug("pasemi_msi_teardown_msi_irqs, pdev %p\n", pdev);
 
@@ -70,10 +71,10 @@ static void pasemi_msi_teardown_msi_irqs(struct pci_dev *pdev)
                if (entry->irq == NO_IRQ)
                        continue;
 
+               hwirq = virq_to_hw(entry->irq);
                irq_set_msi_desc(entry->irq, NULL);
-               msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap,
-                                      virq_to_hw(entry->irq), ALLOC_CHUNK);
                irq_dispose_mapping(entry->irq);
+               msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap, hwirq, ALLOC_CHUNK);
        }
 
        return;
index 230f3a7cdea45f8d160797fe55eb7b154c9c9dba..4296d55e88f30afa7cb91fd54d06e6b2a532d577 100644 (file)
@@ -487,9 +487,12 @@ int opal_machine_check(struct pt_regs *regs)
         *    PRD component would have already got notified about this
         *    error through other channels.
         *
-        * In any case, let us just fall through. We anyway heading
-        * down to panic path.
+        * If hardware marked this as an unrecoverable MCE, we are
+        * going to panic anyway. Even if it didn't, it's not safe to
+        * continue at this point, so we should explicitly panic.
         */
+
+       panic("PowerNV Unrecovered Machine Check");
        return 0;
 }
 
index 2927cd5c830309fed2b5d2a696b5a83767f0f444..414fd1a00fda85b243dcb2839a4929b09be4a52c 100644 (file)
@@ -2049,9 +2049,23 @@ static long pnv_pci_ioda2_setup_default_config(struct pnv_ioda_pe *pe)
        struct iommu_table *tbl = NULL;
        long rc;
 
+       /*
+        * crashkernel= specifies the kdump kernel's maximum memory at
+        * some offset and there is no guaranteed the result is a power
+        * of 2, which will cause errors later.
+        */
+       const u64 max_memory = __rounddown_pow_of_two(memory_hotplug_max());
+
+       /*
+        * In memory constrained environments, e.g. kdump kernel, the
+        * DMA window can be larger than available memory, which will
+        * cause errors later.
+        */
+       const u64 window_size = min((u64)pe->table_group.tce32_size, max_memory);
+
        rc = pnv_pci_ioda2_create_table(&pe->table_group, 0,
                        IOMMU_PAGE_SHIFT_4K,
-                       pe->table_group.tce32_size,
+                       window_size,
                        POWERNV_IOMMU_DEFAULT_LEVELS, &tbl);
        if (rc) {
                pe_err(pe, "Failed to create 32-bit TCE table, err %ld",
index 9b2480b265c00b59e9290b8e5979ac4c9cb7aa0a..f2dd7723424034a0626c28ca2cc9762f79123984 100644 (file)
@@ -99,6 +99,7 @@ void pnv_teardown_msi_irqs(struct pci_dev *pdev)
        struct pci_controller *hose = pci_bus_to_host(pdev->bus);
        struct pnv_phb *phb = hose->private_data;
        struct msi_desc *entry;
+       irq_hw_number_t hwirq;
 
        if (WARN_ON(!phb))
                return;
@@ -106,10 +107,10 @@ void pnv_teardown_msi_irqs(struct pci_dev *pdev)
        for_each_pci_msi_entry(entry, pdev) {
                if (entry->irq == NO_IRQ)
                        continue;
+               hwirq = virq_to_hw(entry->irq);
                irq_set_msi_desc(entry->irq, NULL);
-               msi_bitmap_free_hwirqs(&phb->msi_bmp,
-                       virq_to_hw(entry->irq) - phb->msi_base, 1);
                irq_dispose_mapping(entry->irq);
+               msi_bitmap_free_hwirqs(&phb->msi_bmp, hwirq - phb->msi_base, 1);
        }
 }
 #endif /* CONFIG_PCI_MSI */
index 8f70ba681a78b91e6755e3e123c3dc784857e3c6..ca264833ee64d5c7a55035c66c21454d7b4d0b14 100644 (file)
@@ -171,7 +171,26 @@ static void pnv_smp_cpu_kill_self(void)
         * so clear LPCR:PECE1. We keep PECE2 enabled.
         */
        mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) & ~(u64)LPCR_PECE1);
+
+       /*
+        * Hard-disable interrupts, and then clear irq_happened flags
+        * that we can safely ignore while off-line, since they
+        * are for things for which we do no processing when off-line
+        * (or in the case of HMI, all the processing we need to do
+        * is done in lower-level real-mode code).
+        */
+       hard_irq_disable();
+       local_paca->irq_happened &= ~(PACA_IRQ_DEC | PACA_IRQ_HMI);
+
        while (!generic_check_cpu_restart(cpu)) {
+               /*
+                * Clear IPI flag, since we don't handle IPIs while
+                * offline, except for those when changing micro-threading
+                * mode, which are handled explicitly below, and those
+                * for coming online, which are handled via
+                * generic_check_cpu_restart() calls.
+                */
+               kvmppc_set_host_ipi(cpu, 0);
 
                ppc64_runlatch_off();
 
@@ -196,20 +215,20 @@ static void pnv_smp_cpu_kill_self(void)
                 * having finished executing in a KVM guest, then srr1
                 * contains 0.
                 */
-               if ((srr1 & wmask) == SRR1_WAKEEE) {
+               if (((srr1 & wmask) == SRR1_WAKEEE) ||
+                   (local_paca->irq_happened & PACA_IRQ_EE)) {
                        icp_native_flush_interrupt();
-                       local_paca->irq_happened &= PACA_IRQ_HARD_DIS;
-                       smp_mb();
                } else if ((srr1 & wmask) == SRR1_WAKEHDBELL) {
                        unsigned long msg = PPC_DBELL_TYPE(PPC_DBELL_SERVER);
                        asm volatile(PPC_MSGCLR(%0) : : "r" (msg));
-                       kvmppc_set_host_ipi(cpu, 0);
                }
+               local_paca->irq_happened &= ~(PACA_IRQ_EE | PACA_IRQ_DBELL);
+               smp_mb();
 
                if (cpu_core_split_required())
                        continue;
 
-               if (!generic_check_cpu_restart(cpu))
+               if (srr1 && !generic_check_cpu_restart(cpu))
                        DBG("CPU%d Unexpected exit while offline !\n", cpu);
        }
        mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) | LPCR_PECE1);
index 09787139834ddd8bd01fbce0448ca34297a1cd5c..3db53e8aff9279cfe761ac9f43926559e347eaf4 100644 (file)
@@ -194,11 +194,6 @@ static const struct os_area_db_id os_area_db_id_rtc_diff = {
        .key = OS_AREA_DB_KEY_RTC_DIFF
 };
 
-static const struct os_area_db_id os_area_db_id_video_mode = {
-       .owner = OS_AREA_DB_OWNER_LINUX,
-       .key = OS_AREA_DB_KEY_VIDEO_MODE
-};
-
 #define SECONDS_FROM_1970_TO_2000 946684800LL
 
 /**
index 47d9cebe7159edb2d5d72a3167a89d928dbaa5dc..db17827eb7465a38a3dee939a7a1e68ce13a1c58 100644 (file)
@@ -422,8 +422,10 @@ static ssize_t dlpar_cpu_probe(const char *buf, size_t count)
 
        dn = dlpar_configure_connector(cpu_to_be32(drc_index), parent);
        of_node_put(parent);
-       if (!dn)
+       if (!dn) {
+               dlpar_release_drc(drc_index);
                return -EINVAL;
+       }
 
        rc = dlpar_attach_node(dn);
        if (rc) {
index 39a74fad3e04526eb73222d51a6bf4812c64b034..9a83eb71b0300adb44f99aee93c0f9f790a4471a 100644 (file)
@@ -111,7 +111,7 @@ static void __init fwnmi_init(void)
                fwnmi_active = 1;
 }
 
-static void pseries_8259_cascade(unsigned int irq, struct irq_desc *desc)
+static void pseries_8259_cascade(struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_desc_get_chip(desc);
        unsigned int cascade_irq = i8259_irq();
index a11bd1d433adf7e749ad7e3008f7327bdff29110..9e86074719a96e2f3c47b4a1f69f453483e61f8f 100644 (file)
@@ -155,9 +155,9 @@ static int cpm2_set_irq_type(struct irq_data *d, unsigned int flow_type)
 
        irqd_set_trigger_type(d, flow_type);
        if (flow_type & IRQ_TYPE_LEVEL_LOW)
-               __irq_set_handler_locked(d->irq, handle_level_irq);
+               irq_set_handler_locked(d, handle_level_irq);
        else
-               __irq_set_handler_locked(d->irq, handle_edge_irq);
+               irq_set_handler_locked(d, handle_edge_irq);
 
        /* internal IRQ senses are LEVEL_LOW
         * EXT IRQ and Port C IRQ senses are programmable
index 5916da1856a78d924230ede7353ed84a8b1fa8a0..48a576aa47b92455e97a3f437b5cc18b6007f91a 100644 (file)
@@ -128,15 +128,16 @@ static void fsl_teardown_msi_irqs(struct pci_dev *pdev)
 {
        struct msi_desc *entry;
        struct fsl_msi *msi_data;
+       irq_hw_number_t hwirq;
 
        for_each_pci_msi_entry(entry, pdev) {
                if (entry->irq == NO_IRQ)
                        continue;
+               hwirq = virq_to_hw(entry->irq);
                msi_data = irq_get_chip_data(entry->irq);
                irq_set_msi_desc(entry->irq, NULL);
-               msi_bitmap_free_hwirqs(&msi_data->bitmap,
-                                      virq_to_hw(entry->irq), 1);
                irq_dispose_mapping(entry->irq);
+               msi_bitmap_free_hwirqs(&msi_data->bitmap, hwirq, 1);
        }
 
        return;
index 2bcb78bb3a15b4ea8043b78b892224d01ef2050f..d57b77573068aa7ca966a27334422a3c7ba00be9 100644 (file)
@@ -91,7 +91,7 @@ static int gef_pic_cascade_irq;
  * should be masked out.
  */
 
-void gef_pic_cascade(unsigned int irq, struct irq_desc *desc)
+static void gef_pic_cascade(struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_desc_get_chip(desc);
        unsigned int cascade_irq;
index 908dbd9826b6e15bf0fa8e916116ea0c568a44c7..5bf7e4b81e36c9edf60f0c9f8edae47a47f80179 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef __GEF_PIC_H__
 #define __GEF_PIC_H__
 
-
-void gef_pic_cascade(unsigned int, struct irq_desc *);
 unsigned int gef_pic_get_irq(void);
 void gef_pic_init(struct device_node *);
 
index 6b2b689148104a25003fba7380af676f2a85e055..b1297ab1599b46ef24457ec890b28b69ba4dc0bf 100644 (file)
@@ -624,10 +624,10 @@ static int ipic_set_irq_type(struct irq_data *d, unsigned int flow_type)
 
        irqd_set_trigger_type(d, flow_type);
        if (flow_type & IRQ_TYPE_LEVEL_LOW)  {
-               __irq_set_handler_locked(d->irq, handle_level_irq);
+               irq_set_handler_locked(d, handle_level_irq);
                d->chip = &ipic_level_irq_chip;
        } else {
-               __irq_set_handler_locked(d->irq, handle_edge_irq);
+               irq_set_handler_locked(d, handle_edge_irq);
                d->chip = &ipic_edge_irq_chip;
        }
 
index d93a78be43469cfe5fe7f481bdf5ceb99114e11b..9a423975853ae36a3f60b452a9bbef4dc1060985 100644 (file)
@@ -55,7 +55,7 @@ static int mpc8xx_set_irq_type(struct irq_data *d, unsigned int flow_type)
                unsigned int siel = in_be32(&siu_reg->sc_siel);
                siel |= mpc8xx_irqd_to_bit(d);
                out_be32(&siu_reg->sc_siel, siel);
-               __irq_set_handler_locked(d->irq, handle_edge_irq);
+               irq_set_handler_locked(d, handle_edge_irq);
        }
        return 0;
 }
index 97a8ae8f94dd5d3fe77753c4546c6c7ab6329a49..537e5db85a060518928ee812cdab8dd00a311b06 100644 (file)
@@ -1181,7 +1181,7 @@ static int mpic_host_xlate(struct irq_domain *h, struct device_node *ct,
 }
 
 /* IRQ handler for a secondary MPIC cascaded from another IRQ controller */
-static void mpic_cascade(unsigned int irq, struct irq_desc *desc)
+static void mpic_cascade(struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_desc_get_chip(desc);
        struct mpic *mpic = irq_desc_get_handler_data(desc);
index 70fbd5694a8bcd3c171bc9615edf14e86cdde7b1..2cbc7e29b85ff1301360ab3f9c379837a471d122 100644 (file)
@@ -107,15 +107,16 @@ static u64 find_u4_magic_addr(struct pci_dev *pdev, unsigned int hwirq)
 static void u3msi_teardown_msi_irqs(struct pci_dev *pdev)
 {
        struct msi_desc *entry;
+       irq_hw_number_t hwirq;
 
        for_each_pci_msi_entry(entry, pdev) {
                if (entry->irq == NO_IRQ)
                        continue;
 
+               hwirq = virq_to_hw(entry->irq);
                irq_set_msi_desc(entry->irq, NULL);
-               msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap,
-                                      virq_to_hw(entry->irq), 1);
                irq_dispose_mapping(entry->irq);
+               msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap, hwirq, 1);
        }
 
        return;
index 24d0470c1698fb2bbbe81008e575ca54a35c33ce..8fb8061350431ad8bea7b17df85a530f3c006e53 100644 (file)
@@ -124,16 +124,17 @@ void ppc4xx_teardown_msi_irqs(struct pci_dev *dev)
 {
        struct msi_desc *entry;
        struct ppc4xx_msi *msi_data = &ppc4xx_msi;
+       irq_hw_number_t hwirq;
 
        dev_dbg(&dev->dev, "PCIE-MSI: tearing down msi irqs\n");
 
        for_each_pci_msi_entry(entry, dev) {
                if (entry->irq == NO_IRQ)
                        continue;
+               hwirq = virq_to_hw(entry->irq);
                irq_set_msi_desc(entry->irq, NULL);
-               msi_bitmap_free_hwirqs(&msi_data->bitmap,
-                               virq_to_hw(entry->irq), 1);
                irq_dispose_mapping(entry->irq);
+               msi_bitmap_free_hwirqs(&msi_data->bitmap, hwirq, 1);
        }
 }
 
index 47b352e4bc743f532aa637d9d18daf7319207f92..fbcc1f855a7f2ea15937d02f0b0cb4305af5034a 100644 (file)
@@ -311,8 +311,8 @@ unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic)
 }
 
 void __init qe_ic_init(struct device_node *node, unsigned int flags,
-               void (*low_handler)(unsigned int irq, struct irq_desc *desc),
-               void (*high_handler)(unsigned int irq, struct irq_desc *desc))
+                      void (*low_handler)(struct irq_desc *desc),
+                      void (*high_handler)(struct irq_desc *desc))
 {
        struct qe_ic *qe_ic;
        struct resource res;
index 57b54476e74721eabccf3f15f130c6e2f40c81eb..379de955aae378441b2220d5b329e8b00d881ef4 100644 (file)
@@ -428,7 +428,7 @@ void __init tsi108_pci_int_init(struct device_node *node)
        init_pci_source();
 }
 
-void tsi108_irq_cascade(unsigned int irq, struct irq_desc *desc)
+void tsi108_irq_cascade(struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_desc_get_chip(desc);
        unsigned int cascade_irq = get_pci_source();
index d77345338671c1d63b5a98d3258885d9d3aa2b98..6893d8f236df8903120cf8331d9a33f3444f051f 100644 (file)
@@ -194,7 +194,7 @@ static const struct irq_domain_ops uic_host_ops = {
        .xlate  = irq_domain_xlate_twocell,
 };
 
-void uic_irq_cascade(unsigned int virq, struct irq_desc *desc)
+static void uic_irq_cascade(struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_desc_get_chip(desc);
        struct irq_data *idata = irq_desc_get_irq_data(desc);
index 11ac964d51752f3ce4c55a9953b02e0ee9936e08..27c936c080a66ffb5523931ac74d6c4c3a01849d 100644 (file)
@@ -54,7 +54,7 @@ static void ics_opal_unmask_irq(struct irq_data *d)
        if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS)
                return;
 
-       server = xics_get_irq_server(d->irq, d->affinity, 0);
+       server = xics_get_irq_server(d->irq, irq_data_get_affinity_mask(d), 0);
        server = ics_opal_mangle_server(server);
 
        rc = opal_set_xive(hw_irq, server, DEFAULT_PRIORITY);
index d1c625c4cc5a4081686f2c83f7d2f0a51dbdd53e..3854dd41558d2697e73f9d72f9dffb27327952a8 100644 (file)
@@ -47,7 +47,7 @@ static void ics_rtas_unmask_irq(struct irq_data *d)
        if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS)
                return;
 
-       server = xics_get_irq_server(d->irq, d->affinity, 0);
+       server = xics_get_irq_server(d->irq, irq_data_get_affinity_mask(d), 0);
 
        call_status = rtas_call(ibm_set_xive, 3, 1, NULL, hw_irq, server,
                                DEFAULT_PRIORITY);
index 43b8b275bc5c50e778e79f9695f9ffb85a266328..0f52d79557967c85cb5510be3cd4fea5ad3dc6db 100644 (file)
@@ -222,7 +222,7 @@ int xilinx_intc_get_irq(void)
 /*
  * Support code for cascading to 8259 interrupt controllers
  */
-static void xilinx_i8259_cascade(unsigned int irq, struct irq_desc *desc)
+static void xilinx_i8259_cascade(struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_desc_get_chip(desc);
        unsigned int cascade_irq = i8259_irq();
index d4788111c16171135422a0ef29e23e2eb866236d..fac6ac9790fad18efc2f587757068f87ca7765fd 100644 (file)
@@ -10,7 +10,7 @@ targets += misc.o piggy.o sizes.h head.o
 
 KBUILD_CFLAGS := -m64 -D__KERNEL__ $(LINUX_INCLUDE) -O2
 KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING
-KBUILD_CFLAGS += $(cflags-y) -fno-delete-null-pointer-checks
+KBUILD_CFLAGS += $(cflags-y) -fno-delete-null-pointer-checks -msoft-float
 KBUILD_CFLAGS += $(call cc-option,-mpacked-stack)
 KBUILD_CFLAGS += $(call cc-option,-ffreestanding)
 
index 0c98f1508542c9f900ee2bed1394413b8d5d8d88..ed7da281df66743f0badff631c9183bf318ec9b7 100644 (file)
@@ -381,7 +381,7 @@ CONFIG_ISCSI_TCP=m
 CONFIG_SCSI_DEBUG=m
 CONFIG_ZFCP=y
 CONFIG_SCSI_VIRTIO=m
-CONFIG_SCSI_DH=m
+CONFIG_SCSI_DH=y
 CONFIG_SCSI_DH_RDAC=m
 CONFIG_SCSI_DH_HP_SW=m
 CONFIG_SCSI_DH_EMC=m
index 82083e1fbdc4c6cc9f4ad6a2c0cfbfbcd3af1210..9858b14cde1edccdcda3a217446f547641d98944 100644 (file)
@@ -377,7 +377,7 @@ CONFIG_ISCSI_TCP=m
 CONFIG_SCSI_DEBUG=m
 CONFIG_ZFCP=y
 CONFIG_SCSI_VIRTIO=m
-CONFIG_SCSI_DH=m
+CONFIG_SCSI_DH=y
 CONFIG_SCSI_DH_RDAC=m
 CONFIG_SCSI_DH_HP_SW=m
 CONFIG_SCSI_DH_EMC=m
index c05c9e0821e3bcd956b929c591e41b5445ac9565..7f14f80717d4975161a696dd2e803d4ee87011d6 100644 (file)
@@ -377,7 +377,7 @@ CONFIG_ISCSI_TCP=m
 CONFIG_SCSI_DEBUG=m
 CONFIG_ZFCP=y
 CONFIG_SCSI_VIRTIO=m
-CONFIG_SCSI_DH=m
+CONFIG_SCSI_DH=y
 CONFIG_SCSI_DH_RDAC=m
 CONFIG_SCSI_DH_HP_SW=m
 CONFIG_SCSI_DH_EMC=m
index 1b0184a0f7f213d4557337a18cc5b39adfdd494c..92805d6041735bf0fa71df21650ff673bdc1fb80 100644 (file)
@@ -1,7 +1,6 @@
 # CONFIG_SWAP is not set
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
-CONFIG_RCU_FAST_NO_HZ=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_COMPAT_BRK is not set
@@ -54,10 +53,6 @@ CONFIG_RAW_DRIVER=y
 # CONFIG_MONWRITER is not set
 # CONFIG_S390_VMUR is not set
 # CONFIG_HID is not set
-CONFIG_MEMSTICK=y
-CONFIG_MEMSTICK_DEBUG=y
-CONFIG_MEMSTICK_UNSAFE_RESUME=y
-CONFIG_MSPRO_BLOCK=y
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
index 5ad26dd94d77e83fedeba5c7f71c8eba0ff2ab29..9043d2e1e2ae0b3c01a7b6588bed848f44dd92ff 100644 (file)
@@ -6,3 +6,4 @@ generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
+generic-y += word-at-a-time.h
index 3d012e071647970ce14ee2eb566649ada4b000e6..8ced426091e10106bcc675c85d291943b130d72a 100644 (file)
@@ -35,6 +35,7 @@
  */
 #define KVM_NR_IRQCHIPS 1
 #define KVM_IRQCHIP_NUM_PINS 4096
+#define KVM_HALT_POLL_NS_DEFAULT 0
 
 #define SIGP_CTRL_C            0x80
 #define SIGP_CTRL_SCN_MASK     0x3f
@@ -210,6 +211,7 @@ struct kvm_vcpu_stat {
        u32 exit_validity;
        u32 exit_instruction;
        u32 halt_successful_poll;
+       u32 halt_attempted_poll;
        u32 halt_wakeup;
        u32 instruction_lctl;
        u32 instruction_lctlg;
index 2a0efc63b9e5afb29cb2e6edd109dd9848353b27..dc19ee0c92aaa693d2ad3b8c4c614b3e0e427de7 100644 (file)
@@ -19,7 +19,7 @@ int numa_pfn_to_nid(unsigned long pfn);
 int __node_distance(int a, int b);
 void numa_update_cpu_topology(void);
 
-extern cpumask_var_t node_to_cpumask_map[MAX_NUMNODES];
+extern cpumask_t node_to_cpumask_map[MAX_NUMNODES];
 extern int numa_debug_enabled;
 
 #else
index 27ebde643933a908c1ebb2a75ff723d8d43a65f6..94fc55fc72ce88a18eb73d3f43d5a7895ac6cd9c 100644 (file)
@@ -68,7 +68,7 @@ static inline int cpu_to_node(int cpu)
 #define cpumask_of_node cpumask_of_node
 static inline const struct cpumask *cpumask_of_node(int node)
 {
-       return node_to_cpumask_map[node];
+       return &node_to_cpumask_map[node];
 }
 
 /*
index 525cef73b0859379b8789a5d7fec105edc4ce451..02613bad8bbba4cc4a6e2de3dcc07846946536bf 100644 (file)
@@ -8,28 +8,8 @@
 
 #include <uapi/asm/unistd.h>
 
-
 #define __IGNORE_time
 
-/* Ignore system calls that are also reachable via sys_socketcall */
-#define __IGNORE_recvmmsg
-#define __IGNORE_sendmmsg
-#define __IGNORE_socket
-#define __IGNORE_socketpair
-#define __IGNORE_bind
-#define __IGNORE_connect
-#define __IGNORE_listen
-#define __IGNORE_accept4
-#define __IGNORE_getsockopt
-#define __IGNORE_setsockopt
-#define __IGNORE_getsockname
-#define __IGNORE_getpeername
-#define __IGNORE_sendto
-#define __IGNORE_sendmsg
-#define __IGNORE_recvfrom
-#define __IGNORE_recvmsg
-#define __IGNORE_shutdown
-
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_SYS_ALARM
 #define __ARCH_WANT_SYS_GETHOSTNAME
index 59d2bb4e2d0cf0802618d40b88afdaba08c8c963..a848adba1504a1c9b758d55ef3b44ee07bc74471 100644 (file)
 #define __NR_s390_pci_mmio_write       352
 #define __NR_s390_pci_mmio_read                353
 #define __NR_execveat          354
-#define NR_syscalls 355
+#define __NR_userfaultfd       355
+#define __NR_membarrier                356
+#define __NR_recvmmsg          357
+#define __NR_sendmmsg          358
+#define __NR_socket            359
+#define __NR_socketpair                360
+#define __NR_bind              361
+#define __NR_connect           362
+#define __NR_listen            363
+#define __NR_accept4           364
+#define __NR_getsockopt                365
+#define __NR_setsockopt                366
+#define __NR_getsockname       367
+#define __NR_getpeername       368
+#define __NR_sendto            369
+#define __NR_sendmsg           370
+#define __NR_recvfrom          371
+#define __NR_recvmsg           372
+#define __NR_shutdown          373
+#define NR_syscalls 374
 
 /* 
  * There are some system calls that are not present on 64 bit, some
index 48c9af7a76831ea63ef6ef92760df02f15c1188c..3aeeb1b562c00ff9c7afe559452fdc2c06457116 100644 (file)
@@ -176,6 +176,7 @@ int main(void)
        DEFINE(__LC_PASTE, offsetof(struct _lowcore, paste));
        DEFINE(__LC_FP_CREG_SAVE_AREA, offsetof(struct _lowcore, fpt_creg_save_area));
        DEFINE(__LC_LAST_BREAK, offsetof(struct _lowcore, breaking_event_addr));
+       DEFINE(__LC_PERCPU_OFFSET, offsetof(struct _lowcore, percpu_offset));
        DEFINE(__LC_VDSO_PER_CPU, offsetof(struct _lowcore, vdso_per_cpu_data));
        DEFINE(__LC_GMAP, offsetof(struct _lowcore, gmap));
        DEFINE(__LC_PGM_TDB, offsetof(struct _lowcore, pgm_tdb));
index eb4664238613a0c7db83e7910ae065a9b584e95b..e0f9d270b30f31a8bbcc50c6bd8b39e225edee0d 100644 (file)
@@ -48,6 +48,19 @@ typedef struct
        struct ucontext32 uc;
 } rt_sigframe32;
 
+static inline void sigset_to_sigset32(unsigned long *set64,
+                                     compat_sigset_word *set32)
+{
+       set32[0] = (compat_sigset_word) set64[0];
+       set32[1] = (compat_sigset_word)(set64[0] >> 32);
+}
+
+static inline void sigset32_to_sigset(compat_sigset_word *set32,
+                                     unsigned long *set64)
+{
+       set64[0] = (unsigned long) set32[0] | ((unsigned long) set32[1] << 32);
+}
+
 int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
 {
        int err;
@@ -281,10 +294,12 @@ COMPAT_SYSCALL_DEFINE0(sigreturn)
 {
        struct pt_regs *regs = task_pt_regs(current);
        sigframe32 __user *frame = (sigframe32 __user *)regs->gprs[15];
+       compat_sigset_t cset;
        sigset_t set;
 
-       if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE32))
+       if (__copy_from_user(&cset.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE32))
                goto badframe;
+       sigset32_to_sigset(cset.sig, set.sig);
        set_current_blocked(&set);
        save_fpu_regs();
        if (restore_sigregs32(regs, &frame->sregs))
@@ -302,10 +317,12 @@ COMPAT_SYSCALL_DEFINE0(rt_sigreturn)
 {
        struct pt_regs *regs = task_pt_regs(current);
        rt_sigframe32 __user *frame = (rt_sigframe32 __user *)regs->gprs[15];
+       compat_sigset_t cset;
        sigset_t set;
 
-       if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+       if (__copy_from_user(&cset, &frame->uc.uc_sigmask, sizeof(cset)))
                goto badframe;
+       sigset32_to_sigset(cset.sig, set.sig);
        set_current_blocked(&set);
        if (compat_restore_altstack(&frame->uc.uc_stack))
                goto badframe;
@@ -377,7 +394,7 @@ static int setup_frame32(struct ksignal *ksig, sigset_t *set,
                return -EFAULT;
 
        /* Create struct sigcontext32 on the signal stack */
-       memcpy(&sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE32);
+       sigset_to_sigset32(set->sig, sc.oldmask);
        sc.sregs = (__u32)(unsigned long __force) &frame->sregs;
        if (__copy_to_user(&frame->sc, &sc, sizeof(frame->sc)))
                return -EFAULT;
@@ -438,6 +455,7 @@ static int setup_frame32(struct ksignal *ksig, sigset_t *set,
 static int setup_rt_frame32(struct ksignal *ksig, sigset_t *set,
                            struct pt_regs *regs)
 {
+       compat_sigset_t cset;
        rt_sigframe32 __user *frame;
        unsigned long restorer;
        size_t frame_size;
@@ -485,11 +503,12 @@ static int setup_rt_frame32(struct ksignal *ksig, sigset_t *set,
        store_sigregs();
 
        /* Create ucontext on the signal stack. */
+       sigset_to_sigset32(set->sig, cset.sig);
        if (__put_user(uc_flags, &frame->uc.uc_flags) ||
            __put_user(0, &frame->uc.uc_link) ||
            __compat_save_altstack(&frame->uc.uc_stack, regs->gprs[15]) ||
            save_sigregs32(regs, &frame->uc.uc_mcontext) ||
-           __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)) ||
+           __copy_to_user(&frame->uc.uc_sigmask, &cset, sizeof(cset)) ||
            save_sigregs_ext32(regs, &frame->uc.uc_mcontext_ext))
                return -EFAULT;
 
index f8498dde67b1a3d27a76f78ccc574355ab5b6509..09f194052df35f712cff3fe8f44639df9de6c9e1 100644 (file)
  * the regular system call wrappers.
  */
 #define COMPAT_SYSCALL_WRAPx(x, name, ...)                                     \
-       asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));              \
-       asmlinkage long compat_sys##name(__MAP(x,__SC_COMPAT_TYPE,__VA_ARGS__));\
-       asmlinkage long compat_sys##name(__MAP(x,__SC_COMPAT_TYPE,__VA_ARGS__)) \
-       {                                                                       \
-               return sys##name(__MAP(x,__SC_COMPAT_CAST,__VA_ARGS__));        \
-       }
+asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));                     \
+asmlinkage long notrace compat_sys##name(__MAP(x,__SC_COMPAT_TYPE,__VA_ARGS__));\
+asmlinkage long notrace compat_sys##name(__MAP(x,__SC_COMPAT_TYPE,__VA_ARGS__))        \
+{                                                                              \
+       return sys##name(__MAP(x,__SC_COMPAT_CAST,__VA_ARGS__));                \
+}
 
-COMPAT_SYSCALL_WRAP1(exit, int, error_code);
-COMPAT_SYSCALL_WRAP1(close, unsigned int, fd);
 COMPAT_SYSCALL_WRAP2(creat, const char __user *, pathname, umode_t, mode);
 COMPAT_SYSCALL_WRAP2(link, const char __user *, oldname, const char __user *, newname);
 COMPAT_SYSCALL_WRAP1(unlink, const char __user *, pathname);
@@ -68,23 +66,16 @@ COMPAT_SYSCALL_WRAP1(chdir, const char __user *, filename);
 COMPAT_SYSCALL_WRAP3(mknod, const char __user *, filename, umode_t, mode, unsigned, dev);
 COMPAT_SYSCALL_WRAP2(chmod, const char __user *, filename, umode_t, mode);
 COMPAT_SYSCALL_WRAP1(oldumount, char __user *, name);
-COMPAT_SYSCALL_WRAP1(alarm, unsigned int, seconds);
 COMPAT_SYSCALL_WRAP2(access, const char __user *, filename, int, mode);
-COMPAT_SYSCALL_WRAP1(nice, int, increment);
-COMPAT_SYSCALL_WRAP2(kill, int, pid, int, sig);
 COMPAT_SYSCALL_WRAP2(rename, const char __user *, oldname, const char __user *, newname);
 COMPAT_SYSCALL_WRAP2(mkdir, const char __user *, pathname, umode_t, mode);
 COMPAT_SYSCALL_WRAP1(rmdir, const char __user *, pathname);
-COMPAT_SYSCALL_WRAP1(dup, unsigned int, fildes);
 COMPAT_SYSCALL_WRAP1(pipe, int __user *, fildes);
 COMPAT_SYSCALL_WRAP1(brk, unsigned long, brk);
 COMPAT_SYSCALL_WRAP2(signal, int, sig, __sighandler_t, handler);
 COMPAT_SYSCALL_WRAP1(acct, const char __user *, name);
 COMPAT_SYSCALL_WRAP2(umount, char __user *, name, int, flags);
-COMPAT_SYSCALL_WRAP2(setpgid, pid_t, pid, pid_t, pgid);
-COMPAT_SYSCALL_WRAP1(umask, int, mask);
 COMPAT_SYSCALL_WRAP1(chroot, const char __user *, filename);
-COMPAT_SYSCALL_WRAP2(dup2, unsigned int, oldfd, unsigned int, newfd);
 COMPAT_SYSCALL_WRAP3(sigsuspend, int, unused1, int, unused2, old_sigset_t, mask);
 COMPAT_SYSCALL_WRAP2(sethostname, char __user *, name, int, len);
 COMPAT_SYSCALL_WRAP2(symlink, const char __user *, old, const char __user *, new);
@@ -93,37 +84,23 @@ COMPAT_SYSCALL_WRAP1(uselib, const char __user *, library);
 COMPAT_SYSCALL_WRAP2(swapon, const char __user *, specialfile, int, swap_flags);
 COMPAT_SYSCALL_WRAP4(reboot, int, magic1, int, magic2, unsigned int, cmd, void __user *, arg);
 COMPAT_SYSCALL_WRAP2(munmap, unsigned long, addr, size_t, len);
-COMPAT_SYSCALL_WRAP2(fchmod, unsigned int, fd, umode_t, mode);
-COMPAT_SYSCALL_WRAP2(getpriority, int, which, int, who);
-COMPAT_SYSCALL_WRAP3(setpriority, int, which, int, who, int, niceval);
 COMPAT_SYSCALL_WRAP3(syslog, int, type, char __user *, buf, int, len);
 COMPAT_SYSCALL_WRAP1(swapoff, const char __user *, specialfile);
-COMPAT_SYSCALL_WRAP1(fsync, unsigned int, fd);
 COMPAT_SYSCALL_WRAP2(setdomainname, char __user *, name, int, len);
 COMPAT_SYSCALL_WRAP1(newuname, struct new_utsname __user *, name);
 COMPAT_SYSCALL_WRAP3(mprotect, unsigned long, start, size_t, len, unsigned long, prot);
 COMPAT_SYSCALL_WRAP3(init_module, void __user *, umod, unsigned long, len, const char __user *, uargs);
 COMPAT_SYSCALL_WRAP2(delete_module, const char __user *, name_user, unsigned int, flags);
 COMPAT_SYSCALL_WRAP4(quotactl, unsigned int, cmd, const char __user *, special, qid_t, id, void __user *, addr);
-COMPAT_SYSCALL_WRAP1(getpgid, pid_t, pid);
-COMPAT_SYSCALL_WRAP1(fchdir, unsigned int, fd);
 COMPAT_SYSCALL_WRAP2(bdflush, int, func, long, data);
 COMPAT_SYSCALL_WRAP3(sysfs, int, option, unsigned long, arg1, unsigned long, arg2);
-COMPAT_SYSCALL_WRAP1(s390_personality, unsigned int, personality);
 COMPAT_SYSCALL_WRAP5(llseek, unsigned int, fd, unsigned long, high, unsigned long, low, loff_t __user *, result, unsigned int, whence);
-COMPAT_SYSCALL_WRAP2(flock, unsigned int, fd, unsigned int, cmd);
 COMPAT_SYSCALL_WRAP3(msync, unsigned long, start, size_t, len, int, flags);
-COMPAT_SYSCALL_WRAP1(getsid, pid_t, pid);
-COMPAT_SYSCALL_WRAP1(fdatasync, unsigned int, fd);
 COMPAT_SYSCALL_WRAP2(mlock, unsigned long, start, size_t, len);
 COMPAT_SYSCALL_WRAP2(munlock, unsigned long, start, size_t, len);
-COMPAT_SYSCALL_WRAP1(mlockall, int, flags);
 COMPAT_SYSCALL_WRAP2(sched_setparam, pid_t, pid, struct sched_param __user *, param);
 COMPAT_SYSCALL_WRAP2(sched_getparam, pid_t, pid, struct sched_param __user *, param);
 COMPAT_SYSCALL_WRAP3(sched_setscheduler, pid_t, pid, int, policy, struct sched_param __user *, param);
-COMPAT_SYSCALL_WRAP1(sched_getscheduler, pid_t, pid);
-COMPAT_SYSCALL_WRAP1(sched_get_priority_max, int, policy);
-COMPAT_SYSCALL_WRAP1(sched_get_priority_min, int, policy);
 COMPAT_SYSCALL_WRAP5(mremap, unsigned long, addr, unsigned long, old_len, unsigned long, new_len, unsigned long, flags, unsigned long, new_addr);
 COMPAT_SYSCALL_WRAP3(poll, struct pollfd __user *, ufds, unsigned int, nfds, int, timeout);
 COMPAT_SYSCALL_WRAP5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, unsigned long, arg4, unsigned long, arg5);
@@ -131,20 +108,11 @@ COMPAT_SYSCALL_WRAP2(getcwd, char __user *, buf, unsigned long, size);
 COMPAT_SYSCALL_WRAP2(capget, cap_user_header_t, header, cap_user_data_t, dataptr);
 COMPAT_SYSCALL_WRAP2(capset, cap_user_header_t, header, const cap_user_data_t, data);
 COMPAT_SYSCALL_WRAP3(lchown, const char __user *, filename, uid_t, user, gid_t, group);
-COMPAT_SYSCALL_WRAP2(setreuid, uid_t, ruid, uid_t, euid);
-COMPAT_SYSCALL_WRAP2(setregid, gid_t, rgid, gid_t, egid);
 COMPAT_SYSCALL_WRAP2(getgroups, int, gidsetsize, gid_t __user *, grouplist);
 COMPAT_SYSCALL_WRAP2(setgroups, int, gidsetsize, gid_t __user *, grouplist);
-COMPAT_SYSCALL_WRAP3(fchown, unsigned int, fd, uid_t, user, gid_t, group);
-COMPAT_SYSCALL_WRAP3(setresuid, uid_t, ruid, uid_t, euid, uid_t, suid);
 COMPAT_SYSCALL_WRAP3(getresuid, uid_t __user *, ruid, uid_t __user *, euid, uid_t __user *, suid);
-COMPAT_SYSCALL_WRAP3(setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid);
 COMPAT_SYSCALL_WRAP3(getresgid, gid_t __user *, rgid, gid_t __user *, egid, gid_t __user *, sgid);
 COMPAT_SYSCALL_WRAP3(chown, const char __user *, filename, uid_t, user, gid_t, group);
-COMPAT_SYSCALL_WRAP1(setuid, uid_t, uid);
-COMPAT_SYSCALL_WRAP1(setgid, gid_t, gid);
-COMPAT_SYSCALL_WRAP1(setfsuid, uid_t, uid);
-COMPAT_SYSCALL_WRAP1(setfsgid, gid_t, gid);
 COMPAT_SYSCALL_WRAP2(pivot_root, const char __user *, new_root, const char __user *, put_old);
 COMPAT_SYSCALL_WRAP3(mincore, unsigned long, start, size_t, len, unsigned char __user *, vec);
 COMPAT_SYSCALL_WRAP3(madvise, unsigned long, start, size_t, len, int, behavior);
@@ -161,23 +129,16 @@ COMPAT_SYSCALL_WRAP3(flistxattr, int, fd, char __user *, list, size_t, size);
 COMPAT_SYSCALL_WRAP2(removexattr, const char __user *, path, const char __user *, name);
 COMPAT_SYSCALL_WRAP2(lremovexattr, const char __user *, path, const char __user *, name);
 COMPAT_SYSCALL_WRAP2(fremovexattr, int, fd, const char __user *, name);
-COMPAT_SYSCALL_WRAP1(exit_group, int, error_code);
 COMPAT_SYSCALL_WRAP1(set_tid_address, int __user *, tidptr);
-COMPAT_SYSCALL_WRAP1(epoll_create, int, size);
 COMPAT_SYSCALL_WRAP4(epoll_ctl, int, epfd, int, op, int, fd, struct epoll_event __user *, event);
 COMPAT_SYSCALL_WRAP4(epoll_wait, int, epfd, struct epoll_event __user *, events, int, maxevents, int, timeout);
-COMPAT_SYSCALL_WRAP1(timer_getoverrun, timer_t, timer_id);
-COMPAT_SYSCALL_WRAP1(timer_delete, compat_timer_t, compat_timer_id);
 COMPAT_SYSCALL_WRAP1(io_destroy, aio_context_t, ctx);
 COMPAT_SYSCALL_WRAP3(io_cancel, aio_context_t, ctx_id, struct iocb __user *, iocb, struct io_event __user *, result);
 COMPAT_SYSCALL_WRAP1(mq_unlink, const char __user *, name);
 COMPAT_SYSCALL_WRAP5(add_key, const char __user *, tp, const char __user *, dsc, const void __user *, pld, size_t, len, key_serial_t, id);
 COMPAT_SYSCALL_WRAP4(request_key, const char __user *, tp, const char __user *, dsc, const char __user *, info, key_serial_t, id);
 COMPAT_SYSCALL_WRAP5(remap_file_pages, unsigned long, start, unsigned long, size, unsigned long, prot, unsigned long, pgoff, unsigned long, flags);
-COMPAT_SYSCALL_WRAP3(ioprio_set, int, which, int, who, int, ioprio);
-COMPAT_SYSCALL_WRAP2(ioprio_get, int, which, int, who);
 COMPAT_SYSCALL_WRAP3(inotify_add_watch, int, fd, const char __user *, path, u32, mask);
-COMPAT_SYSCALL_WRAP2(inotify_rm_watch, int, fd, __s32, wd);
 COMPAT_SYSCALL_WRAP3(mkdirat, int, dfd, const char __user *, pathname, umode_t, mode);
 COMPAT_SYSCALL_WRAP4(mknodat, int, dfd, const char __user *, filename, umode_t, mode, unsigned, dev);
 COMPAT_SYSCALL_WRAP5(fchownat, int, dfd, const char __user *, filename, uid_t, user, gid_t, group, int, flag);
@@ -192,23 +153,11 @@ COMPAT_SYSCALL_WRAP1(unshare, unsigned long, unshare_flags);
 COMPAT_SYSCALL_WRAP6(splice, int, fd_in, loff_t __user *, off_in, int, fd_out, loff_t __user *, off_out, size_t, len, unsigned int, flags);
 COMPAT_SYSCALL_WRAP4(tee, int, fdin, int, fdout, size_t, len, unsigned int, flags);
 COMPAT_SYSCALL_WRAP3(getcpu, unsigned __user *, cpu, unsigned __user *, node, struct getcpu_cache __user *, cache);
-COMPAT_SYSCALL_WRAP1(eventfd, unsigned int, count);
-COMPAT_SYSCALL_WRAP2(timerfd_create, int, clockid, int, flags);
-COMPAT_SYSCALL_WRAP2(eventfd2, unsigned int, count, int, flags);
-COMPAT_SYSCALL_WRAP1(inotify_init1, int, flags);
 COMPAT_SYSCALL_WRAP2(pipe2, int __user *, fildes, int, flags);
-COMPAT_SYSCALL_WRAP3(dup3, unsigned int, oldfd, unsigned int, newfd, int, flags);
-COMPAT_SYSCALL_WRAP1(epoll_create1, int, flags);
-COMPAT_SYSCALL_WRAP2(tkill, int, pid, int, sig);
-COMPAT_SYSCALL_WRAP3(tgkill, int, tgid, int, pid, int, sig);
 COMPAT_SYSCALL_WRAP5(perf_event_open, struct perf_event_attr __user *, attr_uptr, pid_t, pid, int, cpu, int, group_fd, unsigned long, flags);
 COMPAT_SYSCALL_WRAP5(clone, unsigned long, newsp, unsigned long, clone_flags, int __user *, parent_tidptr, int __user *, child_tidptr, unsigned long, tls);
-COMPAT_SYSCALL_WRAP2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags);
 COMPAT_SYSCALL_WRAP4(prlimit64, pid_t, pid, unsigned int, resource, const struct rlimit64 __user *, new_rlim, struct rlimit64 __user *, old_rlim);
 COMPAT_SYSCALL_WRAP5(name_to_handle_at, int, dfd, const char __user *, name, struct file_handle __user *, handle, int __user *, mnt_id, int, flag);
-COMPAT_SYSCALL_WRAP1(syncfs, int, fd);
-COMPAT_SYSCALL_WRAP2(setns, int, fd, int, nstype);
-COMPAT_SYSCALL_WRAP2(s390_runtime_instr, int, command, int, signum);
 COMPAT_SYSCALL_WRAP5(kcmp, pid_t, pid1, pid_t, pid2, int, type, unsigned long, idx1, unsigned long, idx2);
 COMPAT_SYSCALL_WRAP3(finit_module, int, fd, const char __user *, uargs, int, flags);
 COMPAT_SYSCALL_WRAP3(sched_setattr, pid_t, pid, struct sched_attr __user *, attr, unsigned int, flags);
@@ -220,3 +169,10 @@ COMPAT_SYSCALL_WRAP2(memfd_create, const char __user *, uname, unsigned int, fla
 COMPAT_SYSCALL_WRAP3(bpf, int, cmd, union bpf_attr *, attr, unsigned int, size);
 COMPAT_SYSCALL_WRAP3(s390_pci_mmio_write, const unsigned long, mmio_addr, const void __user *, user_buffer, const size_t, length);
 COMPAT_SYSCALL_WRAP3(s390_pci_mmio_read, const unsigned long, mmio_addr, void __user *, user_buffer, const size_t, length);
+COMPAT_SYSCALL_WRAP4(socketpair, int, family, int, type, int, protocol, int __user *, usockvec);
+COMPAT_SYSCALL_WRAP3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen);
+COMPAT_SYSCALL_WRAP3(connect, int, fd, struct sockaddr __user *, uservaddr, int, addrlen);
+COMPAT_SYSCALL_WRAP4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr, int __user *, upeer_addrlen, int, flags);
+COMPAT_SYSCALL_WRAP3(getsockname, int, fd, struct sockaddr __user *, usockaddr, int __user *, usockaddr_len);
+COMPAT_SYSCALL_WRAP3(getpeername, int, fd, struct sockaddr __user *, usockaddr, int __user *, usockaddr_len);
+COMPAT_SYSCALL_WRAP6(sendto, int, fd, void __user *, buff, size_t, len, unsigned int, flags, struct sockaddr __user *, addr, int, addr_len);
index 247b7aae4c6de0a332bf0b276b7224de00296307..582fe44ab07cc69aaef1d4f782f6f89364914974 100644 (file)
@@ -733,6 +733,14 @@ ENTRY(psw_idle)
        stg     %r3,__SF_EMPTY(%r15)
        larl    %r1,.Lpsw_idle_lpsw+4
        stg     %r1,__SF_EMPTY+8(%r15)
+#ifdef CONFIG_SMP
+       larl    %r1,smp_cpu_mtid
+       llgf    %r1,0(%r1)
+       ltgr    %r1,%r1
+       jz      .Lpsw_idle_stcctm
+       .insn   rsy,0xeb0000000017,%r1,5,__SF_EMPTY+16(%r15)
+.Lpsw_idle_stcctm:
+#endif
        STCK    __CLOCK_IDLE_ENTER(%r2)
        stpt    __TIMER_IDLE_ENTER(%r2)
 .Lpsw_idle_lpsw:
@@ -1159,7 +1167,27 @@ cleanup_critical:
        jhe     1f
        mvc     __CLOCK_IDLE_ENTER(8,%r2),__CLOCK_IDLE_EXIT(%r2)
        mvc     __TIMER_IDLE_ENTER(8,%r2),__TIMER_IDLE_EXIT(%r2)
-1:     # account system time going idle
+1:     # calculate idle cycles
+#ifdef CONFIG_SMP
+       clg     %r9,BASED(.Lcleanup_idle_insn)
+       jl      3f
+       larl    %r1,smp_cpu_mtid
+       llgf    %r1,0(%r1)
+       ltgr    %r1,%r1
+       jz      3f
+       .insn   rsy,0xeb0000000017,%r1,5,__SF_EMPTY+80(%r15)
+       larl    %r3,mt_cycles
+       ag      %r3,__LC_PERCPU_OFFSET
+       la      %r4,__SF_EMPTY+16(%r15)
+2:     lg      %r0,0(%r3)
+       slg     %r0,0(%r4)
+       alg     %r0,64(%r4)
+       stg     %r0,0(%r3)
+       la      %r3,8(%r3)
+       la      %r4,8(%r4)
+       brct    %r1,2b
+#endif
+3:     # account system time going idle
        lg      %r9,__LC_STEAL_TIMER
        alg     %r9,__CLOCK_IDLE_ENTER(%r2)
        slg     %r9,__LC_LAST_UPDATE_CLOCK
@@ -1191,6 +1219,7 @@ cleanup_critical:
        clg     %r9,BASED(.Lcleanup_save_fpu_fpc_end)
        jhe     1f
        lg      %r2,__LC_CURRENT
+       aghi    %r2,__TASK_thread
 0:     # Store floating-point controls
        stfpc   __THREAD_FPU_fpc(%r2)
 1:     # Load register save area and check if VX is active
@@ -1252,6 +1281,7 @@ cleanup_critical:
        clg     %r9,BASED(.Lcleanup_load_fpu_regs_vx_ctl)
        jhe     6f
        lg      %r4,__LC_CURRENT
+       aghi    %r4,__TASK_thread
        lfpc    __THREAD_FPU_fpc(%r4)
        tm      __THREAD_FPU_flags+3(%r4),FPU_USE_VX    # VX-enabled task ?
        lg      %r4,__THREAD_FPU_regs(%r4)      # %r4 <- reg save area
index 56fdad479115eafe3ec4acd6f4e5f128d71737a7..a9563409c36ea7bc37bfb405411b9c6ac70c2a50 100644 (file)
@@ -157,10 +157,14 @@ static int validate_ctr_auth(const struct hw_perf_event *hwc)
 
        cpuhw = &get_cpu_var(cpu_hw_events);
 
-       /* check authorization for cpu counter sets */
+       /* Check authorization for cpu counter sets.
+        * If the particular CPU counter set is not authorized,
+        * return with -ENOENT in order to fall back to other
+        * PMUs that might suffice the event request.
+        */
        ctrs_state = cpumf_state_ctl[hwc->config_base];
        if (!(ctrs_state & cpuhw->info.auth_ctl))
-               err = -EPERM;
+               err = -ENOENT;
 
        put_cpu_var(cpu_hw_events);
        return err;
@@ -536,7 +540,7 @@ static int cpumf_pmu_add(struct perf_event *event, int flags)
         */
        if (!(cpuhw->flags & PERF_EVENT_TXN))
                if (validate_ctr_auth(&event->hw))
-                       return -EPERM;
+                       return -ENOENT;
 
        ctr_set_enable(&cpuhw->state, event->hw.config_base);
        event->hw.state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
@@ -611,7 +615,7 @@ static int cpumf_pmu_commit_txn(struct pmu *pmu)
        state = cpuhw->state & ~((1 << CPUMF_LCCTL_ENABLE_SHIFT) - 1);
        state >>= CPUMF_LCCTL_ENABLE_SHIFT;
        if ((state & cpuhw->info.auth_ctl) != state)
-               return -EPERM;
+               return -ENOENT;
 
        cpuhw->flags &= ~PERF_EVENT_TXN;
        perf_pmu_enable(pmu);
index ca6294645dd37eeec22c4ab3d26226da37686cd0..2d6b6e81f812c453c7745da36bb7c8ad82d08c54 100644 (file)
@@ -30,6 +30,9 @@ ENTRY(swsusp_arch_suspend)
        aghi    %r15,-STACK_FRAME_OVERHEAD
        stg     %r1,__SF_BACKCHAIN(%r15)
 
+       /* Store FPU registers */
+       brasl   %r14,save_fpu_regs
+
        /* Deactivate DAT */
        stnsm   __SF_EMPTY(%r15),0xfb
 
@@ -47,23 +50,6 @@ ENTRY(swsusp_arch_suspend)
 
        /* Store registers */
        mvc     0x318(4,%r1),__SF_EMPTY(%r15)   /* move prefix to lowcore */
-       stfpc   0x31c(%r1)                      /* store fpu control */
-       std     0,0x200(%r1)                    /* store f0 */
-       std     1,0x208(%r1)                    /* store f1 */
-       std     2,0x210(%r1)                    /* store f2 */
-       std     3,0x218(%r1)                    /* store f3 */
-       std     4,0x220(%r1)                    /* store f4 */
-       std     5,0x228(%r1)                    /* store f5 */
-       std     6,0x230(%r1)                    /* store f6 */
-       std     7,0x238(%r1)                    /* store f7 */
-       std     8,0x240(%r1)                    /* store f8 */
-       std     9,0x248(%r1)                    /* store f9 */
-       std     10,0x250(%r1)                   /* store f10 */
-       std     11,0x258(%r1)                   /* store f11 */
-       std     12,0x260(%r1)                   /* store f12 */
-       std     13,0x268(%r1)                   /* store f13 */
-       std     14,0x270(%r1)                   /* store f14 */
-       std     15,0x278(%r1)                   /* store f15 */
        stam    %a0,%a15,0x340(%r1)             /* store access registers */
        stctg   %c0,%c15,0x380(%r1)             /* store control registers */
        stmg    %r0,%r15,0x280(%r1)             /* store general registers */
@@ -249,24 +235,6 @@ restore_registers:
        lctlg   %c0,%c15,0x380(%r13)    /* load control registers */
        lam     %a0,%a15,0x340(%r13)    /* load access registers */
 
-       lfpc    0x31c(%r13)             /* load fpu control */
-       ld      0,0x200(%r13)           /* load f0 */
-       ld      1,0x208(%r13)           /* load f1 */
-       ld      2,0x210(%r13)           /* load f2 */
-       ld      3,0x218(%r13)           /* load f3 */
-       ld      4,0x220(%r13)           /* load f4 */
-       ld      5,0x228(%r13)           /* load f5 */
-       ld      6,0x230(%r13)           /* load f6 */
-       ld      7,0x238(%r13)           /* load f7 */
-       ld      8,0x240(%r13)           /* load f8 */
-       ld      9,0x248(%r13)           /* load f9 */
-       ld      10,0x250(%r13)          /* load f10 */
-       ld      11,0x258(%r13)          /* load f11 */
-       ld      12,0x260(%r13)          /* load f12 */
-       ld      13,0x268(%r13)          /* load f13 */
-       ld      14,0x270(%r13)          /* load f14 */
-       ld      15,0x278(%r13)          /* load f15 */
-
        /* Load old stack */
        lg      %r15,0x2f8(%r13)
 
index f3f4a137aef6e9bc1d4e23049cc6592aef86bf29..8c56929c8d826e09ccd3620454b813101cb319e7 100644 (file)
@@ -9,12 +9,12 @@
 #define NI_SYSCALL SYSCALL(sys_ni_syscall,sys_ni_syscall)
 
 NI_SYSCALL                                             /* 0 */
-SYSCALL(sys_exit,compat_sys_exit)
+SYSCALL(sys_exit,sys_exit)
 SYSCALL(sys_fork,sys_fork)
 SYSCALL(sys_read,compat_sys_s390_read)
 SYSCALL(sys_write,compat_sys_s390_write)
 SYSCALL(sys_open,compat_sys_open)                      /* 5 */
-SYSCALL(sys_close,compat_sys_close)
+SYSCALL(sys_close,sys_close)
 SYSCALL(sys_restart_syscall,sys_restart_syscall)
 SYSCALL(sys_creat,compat_sys_creat)
 SYSCALL(sys_link,compat_sys_link)
@@ -35,21 +35,21 @@ SYSCALL(sys_ni_syscall,compat_sys_s390_setuid16)    /* old setuid16 syscall*/
 SYSCALL(sys_ni_syscall,compat_sys_s390_getuid16)       /* old getuid16 syscall*/
 SYSCALL(sys_ni_syscall,compat_sys_stime)               /* 25 old stime syscall */
 SYSCALL(sys_ptrace,compat_sys_ptrace)
-SYSCALL(sys_alarm,compat_sys_alarm)
+SYSCALL(sys_alarm,sys_alarm)
 NI_SYSCALL                                             /* old fstat syscall */
 SYSCALL(sys_pause,sys_pause)
 SYSCALL(sys_utime,compat_sys_utime)                    /* 30 */
 NI_SYSCALL                                             /* old stty syscall */
 NI_SYSCALL                                             /* old gtty syscall */
 SYSCALL(sys_access,compat_sys_access)
-SYSCALL(sys_nice,compat_sys_nice)
+SYSCALL(sys_nice,sys_nice)
 NI_SYSCALL                                             /* 35 old ftime syscall */
 SYSCALL(sys_sync,sys_sync)
-SYSCALL(sys_kill,compat_sys_kill)
+SYSCALL(sys_kill,sys_kill)
 SYSCALL(sys_rename,compat_sys_rename)
 SYSCALL(sys_mkdir,compat_sys_mkdir)
 SYSCALL(sys_rmdir,compat_sys_rmdir)                    /* 40 */
-SYSCALL(sys_dup,compat_sys_dup)
+SYSCALL(sys_dup,sys_dup)
 SYSCALL(sys_pipe,compat_sys_pipe)
 SYSCALL(sys_times,compat_sys_times)
 NI_SYSCALL                                             /* old prof syscall */
@@ -65,13 +65,13 @@ NI_SYSCALL                                          /* old lock syscall */
 SYSCALL(sys_ioctl,compat_sys_ioctl)
 SYSCALL(sys_fcntl,compat_sys_fcntl)                    /* 55 */
 NI_SYSCALL                                             /* intel mpx syscall */
-SYSCALL(sys_setpgid,compat_sys_setpgid)
+SYSCALL(sys_setpgid,sys_setpgid)
 NI_SYSCALL                                             /* old ulimit syscall */
 NI_SYSCALL                                             /* old uname syscall */
-SYSCALL(sys_umask,compat_sys_umask)                    /* 60 */
+SYSCALL(sys_umask,sys_umask)                           /* 60 */
 SYSCALL(sys_chroot,compat_sys_chroot)
 SYSCALL(sys_ustat,compat_sys_ustat)
-SYSCALL(sys_dup2,compat_sys_dup2)
+SYSCALL(sys_dup2,sys_dup2)
 SYSCALL(sys_getppid,sys_getppid)
 SYSCALL(sys_getpgrp,sys_getpgrp)                       /* 65 */
 SYSCALL(sys_setsid,sys_setsid)
@@ -102,10 +102,10 @@ SYSCALL(sys_old_mmap,compat_sys_s390_old_mmap)            /* 90 */
 SYSCALL(sys_munmap,compat_sys_munmap)
 SYSCALL(sys_truncate,compat_sys_truncate)
 SYSCALL(sys_ftruncate,compat_sys_ftruncate)
-SYSCALL(sys_fchmod,compat_sys_fchmod)
+SYSCALL(sys_fchmod,sys_fchmod)
 SYSCALL(sys_ni_syscall,compat_sys_s390_fchown16)       /* 95 old fchown16 syscall*/
-SYSCALL(sys_getpriority,compat_sys_getpriority)
-SYSCALL(sys_setpriority,compat_sys_setpriority)
+SYSCALL(sys_getpriority,sys_getpriority)
+SYSCALL(sys_setpriority,sys_setpriority)
 NI_SYSCALL                                             /* old profil syscall */
 SYSCALL(sys_statfs,compat_sys_statfs)
 SYSCALL(sys_fstatfs,compat_sys_fstatfs)                        /* 100 */
@@ -126,7 +126,7 @@ SYSCALL(sys_wait4,compat_sys_wait4)
 SYSCALL(sys_swapoff,compat_sys_swapoff)                        /* 115 */
 SYSCALL(sys_sysinfo,compat_sys_sysinfo)
 SYSCALL(sys_s390_ipc,compat_sys_s390_ipc)
-SYSCALL(sys_fsync,compat_sys_fsync)
+SYSCALL(sys_fsync,sys_fsync)
 SYSCALL(sys_sigreturn,compat_sys_sigreturn)
 SYSCALL(sys_clone,compat_sys_clone)                    /* 120 */
 SYSCALL(sys_setdomainname,compat_sys_setdomainname)
@@ -140,35 +140,35 @@ SYSCALL(sys_init_module,compat_sys_init_module)
 SYSCALL(sys_delete_module,compat_sys_delete_module)
 NI_SYSCALL                                             /* 130: old get_kernel_syms */
 SYSCALL(sys_quotactl,compat_sys_quotactl)
-SYSCALL(sys_getpgid,compat_sys_getpgid)
-SYSCALL(sys_fchdir,compat_sys_fchdir)
+SYSCALL(sys_getpgid,sys_getpgid)
+SYSCALL(sys_fchdir,sys_fchdir)
 SYSCALL(sys_bdflush,compat_sys_bdflush)
 SYSCALL(sys_sysfs,compat_sys_sysfs)                    /* 135 */
-SYSCALL(sys_s390_personality,compat_sys_s390_personality)
+SYSCALL(sys_s390_personality,sys_s390_personality)
 NI_SYSCALL                                             /* for afs_syscall */
 SYSCALL(sys_ni_syscall,compat_sys_s390_setfsuid16)     /* old setfsuid16 syscall */
 SYSCALL(sys_ni_syscall,compat_sys_s390_setfsgid16)     /* old setfsgid16 syscall */
 SYSCALL(sys_llseek,compat_sys_llseek)                  /* 140 */
 SYSCALL(sys_getdents,compat_sys_getdents)
 SYSCALL(sys_select,compat_sys_select)
-SYSCALL(sys_flock,compat_sys_flock)
+SYSCALL(sys_flock,sys_flock)
 SYSCALL(sys_msync,compat_sys_msync)
 SYSCALL(sys_readv,compat_sys_readv)                    /* 145 */
 SYSCALL(sys_writev,compat_sys_writev)
-SYSCALL(sys_getsid,compat_sys_getsid)
-SYSCALL(sys_fdatasync,compat_sys_fdatasync)
+SYSCALL(sys_getsid,sys_getsid)
+SYSCALL(sys_fdatasync,sys_fdatasync)
 SYSCALL(sys_sysctl,compat_sys_sysctl)
 SYSCALL(sys_mlock,compat_sys_mlock)                    /* 150 */
 SYSCALL(sys_munlock,compat_sys_munlock)
-SYSCALL(sys_mlockall,compat_sys_mlockall)
+SYSCALL(sys_mlockall,sys_mlockall)
 SYSCALL(sys_munlockall,sys_munlockall)
 SYSCALL(sys_sched_setparam,compat_sys_sched_setparam)
 SYSCALL(sys_sched_getparam,compat_sys_sched_getparam)  /* 155 */
 SYSCALL(sys_sched_setscheduler,compat_sys_sched_setscheduler)
-SYSCALL(sys_sched_getscheduler,compat_sys_sched_getscheduler)
+SYSCALL(sys_sched_getscheduler,sys_sched_getscheduler)
 SYSCALL(sys_sched_yield,sys_sched_yield)
-SYSCALL(sys_sched_get_priority_max,compat_sys_sched_get_priority_max)
-SYSCALL(sys_sched_get_priority_min,compat_sys_sched_get_priority_min)  /* 160 */
+SYSCALL(sys_sched_get_priority_max,sys_sched_get_priority_max)
+SYSCALL(sys_sched_get_priority_min,sys_sched_get_priority_min) /* 160 */
 SYSCALL(sys_sched_rr_get_interval,compat_sys_sched_rr_get_interval)
 SYSCALL(sys_nanosleep,compat_sys_nanosleep)
 SYSCALL(sys_mremap,compat_sys_mremap)
@@ -211,20 +211,20 @@ SYSCALL(sys_getuid,sys_getuid)
 SYSCALL(sys_getgid,sys_getgid)                         /* 200 */
 SYSCALL(sys_geteuid,sys_geteuid)
 SYSCALL(sys_getegid,sys_getegid)
-SYSCALL(sys_setreuid,compat_sys_setreuid)
-SYSCALL(sys_setregid,compat_sys_setregid)
+SYSCALL(sys_setreuid,sys_setreuid)
+SYSCALL(sys_setregid,sys_setregid)
 SYSCALL(sys_getgroups,compat_sys_getgroups)            /* 205 */
 SYSCALL(sys_setgroups,compat_sys_setgroups)
-SYSCALL(sys_fchown,compat_sys_fchown)
-SYSCALL(sys_setresuid,compat_sys_setresuid)
+SYSCALL(sys_fchown,sys_fchown)
+SYSCALL(sys_setresuid,sys_setresuid)
 SYSCALL(sys_getresuid,compat_sys_getresuid)
-SYSCALL(sys_setresgid,compat_sys_setresgid)            /* 210 */
+SYSCALL(sys_setresgid,sys_setresgid)                   /* 210 */
 SYSCALL(sys_getresgid,compat_sys_getresgid)
 SYSCALL(sys_chown,compat_sys_chown)
-SYSCALL(sys_setuid,compat_sys_setuid)
-SYSCALL(sys_setgid,compat_sys_setgid)
-SYSCALL(sys_setfsuid,compat_sys_setfsuid)              /* 215 */
-SYSCALL(sys_setfsgid,compat_sys_setfsgid)
+SYSCALL(sys_setuid,sys_setuid)
+SYSCALL(sys_setgid,sys_setgid)
+SYSCALL(sys_setfsuid,sys_setfsuid)                     /* 215 */
+SYSCALL(sys_setfsgid,sys_setfsgid)
 SYSCALL(sys_pivot_root,compat_sys_pivot_root)
 SYSCALL(sys_mincore,compat_sys_mincore)
 SYSCALL(sys_madvise,compat_sys_madvise)
@@ -245,19 +245,19 @@ SYSCALL(sys_removexattr,compat_sys_removexattr)
 SYSCALL(sys_lremovexattr,compat_sys_lremovexattr)
 SYSCALL(sys_fremovexattr,compat_sys_fremovexattr)      /* 235 */
 SYSCALL(sys_gettid,sys_gettid)
-SYSCALL(sys_tkill,compat_sys_tkill)
+SYSCALL(sys_tkill,sys_tkill)
 SYSCALL(sys_futex,compat_sys_futex)
 SYSCALL(sys_sched_setaffinity,compat_sys_sched_setaffinity)
 SYSCALL(sys_sched_getaffinity,compat_sys_sched_getaffinity)    /* 240 */
-SYSCALL(sys_tgkill,compat_sys_tgkill)
+SYSCALL(sys_tgkill,sys_tgkill)
 NI_SYSCALL                                             /* reserved for TUX */
 SYSCALL(sys_io_setup,compat_sys_io_setup)
 SYSCALL(sys_io_destroy,compat_sys_io_destroy)
 SYSCALL(sys_io_getevents,compat_sys_io_getevents)      /* 245 */
 SYSCALL(sys_io_submit,compat_sys_io_submit)
 SYSCALL(sys_io_cancel,compat_sys_io_cancel)
-SYSCALL(sys_exit_group,compat_sys_exit_group)
-SYSCALL(sys_epoll_create,compat_sys_epoll_create)
+SYSCALL(sys_exit_group,sys_exit_group)
+SYSCALL(sys_epoll_create,sys_epoll_create)
 SYSCALL(sys_epoll_ctl,compat_sys_epoll_ctl)            /* 250 */
 SYSCALL(sys_epoll_wait,compat_sys_epoll_wait)
 SYSCALL(sys_set_tid_address,compat_sys_set_tid_address)
@@ -265,8 +265,8 @@ SYSCALL(sys_fadvise64_64,compat_sys_s390_fadvise64)
 SYSCALL(sys_timer_create,compat_sys_timer_create)
 SYSCALL(sys_timer_settime,compat_sys_timer_settime)    /* 255 */
 SYSCALL(sys_timer_gettime,compat_sys_timer_gettime)
-SYSCALL(sys_timer_getoverrun,compat_sys_timer_getoverrun)
-SYSCALL(sys_timer_delete,compat_sys_timer_delete)
+SYSCALL(sys_timer_getoverrun,sys_timer_getoverrun)
+SYSCALL(sys_timer_delete,sys_timer_delete)
 SYSCALL(sys_clock_settime,compat_sys_clock_settime)
 SYSCALL(sys_clock_gettime,compat_sys_clock_gettime)    /* 260 */
 SYSCALL(sys_clock_getres,compat_sys_clock_getres)
@@ -290,11 +290,11 @@ SYSCALL(sys_add_key,compat_sys_add_key)
 SYSCALL(sys_request_key,compat_sys_request_key)
 SYSCALL(sys_keyctl,compat_sys_keyctl)                  /* 280 */
 SYSCALL(sys_waitid,compat_sys_waitid)
-SYSCALL(sys_ioprio_set,compat_sys_ioprio_set)
-SYSCALL(sys_ioprio_get,compat_sys_ioprio_get)
+SYSCALL(sys_ioprio_set,sys_ioprio_set)
+SYSCALL(sys_ioprio_get,sys_ioprio_get)
 SYSCALL(sys_inotify_init,sys_inotify_init)
 SYSCALL(sys_inotify_add_watch,compat_sys_inotify_add_watch)    /* 285 */
-SYSCALL(sys_inotify_rm_watch,compat_sys_inotify_rm_watch)
+SYSCALL(sys_inotify_rm_watch,sys_inotify_rm_watch)
 SYSCALL(sys_migrate_pages,compat_sys_migrate_pages)
 SYSCALL(sys_openat,compat_sys_openat)
 SYSCALL(sys_mkdirat,compat_sys_mkdirat)
@@ -326,31 +326,31 @@ SYSCALL(sys_fallocate,compat_sys_s390_fallocate)
 SYSCALL(sys_utimensat,compat_sys_utimensat)            /* 315 */
 SYSCALL(sys_signalfd,compat_sys_signalfd)
 NI_SYSCALL                                             /* 317 old sys_timer_fd */
-SYSCALL(sys_eventfd,compat_sys_eventfd)
-SYSCALL(sys_timerfd_create,compat_sys_timerfd_create)
+SYSCALL(sys_eventfd,sys_eventfd)
+SYSCALL(sys_timerfd_create,sys_timerfd_create)
 SYSCALL(sys_timerfd_settime,compat_sys_timerfd_settime) /* 320 */
 SYSCALL(sys_timerfd_gettime,compat_sys_timerfd_gettime)
 SYSCALL(sys_signalfd4,compat_sys_signalfd4)
-SYSCALL(sys_eventfd2,compat_sys_eventfd2)
-SYSCALL(sys_inotify_init1,compat_sys_inotify_init1)
+SYSCALL(sys_eventfd2,sys_eventfd2)
+SYSCALL(sys_inotify_init1,sys_inotify_init1)
 SYSCALL(sys_pipe2,compat_sys_pipe2)                    /* 325 */
-SYSCALL(sys_dup3,compat_sys_dup3)
-SYSCALL(sys_epoll_create1,compat_sys_epoll_create1)
+SYSCALL(sys_dup3,sys_dup3)
+SYSCALL(sys_epoll_create1,sys_epoll_create1)
 SYSCALL(sys_preadv,compat_sys_preadv)
 SYSCALL(sys_pwritev,compat_sys_pwritev)
 SYSCALL(sys_rt_tgsigqueueinfo,compat_sys_rt_tgsigqueueinfo) /* 330 */
 SYSCALL(sys_perf_event_open,compat_sys_perf_event_open)
-SYSCALL(sys_fanotify_init,compat_sys_fanotify_init)
+SYSCALL(sys_fanotify_init,sys_fanotify_init)
 SYSCALL(sys_fanotify_mark,compat_sys_fanotify_mark)
 SYSCALL(sys_prlimit64,compat_sys_prlimit64)
 SYSCALL(sys_name_to_handle_at,compat_sys_name_to_handle_at) /* 335 */
 SYSCALL(sys_open_by_handle_at,compat_sys_open_by_handle_at)
 SYSCALL(sys_clock_adjtime,compat_sys_clock_adjtime)
-SYSCALL(sys_syncfs,compat_sys_syncfs)
-SYSCALL(sys_setns,compat_sys_setns)
+SYSCALL(sys_syncfs,sys_syncfs)
+SYSCALL(sys_setns,sys_setns)
 SYSCALL(sys_process_vm_readv,compat_sys_process_vm_readv) /* 340 */
 SYSCALL(sys_process_vm_writev,compat_sys_process_vm_writev)
-SYSCALL(sys_s390_runtime_instr,compat_sys_s390_runtime_instr)
+SYSCALL(sys_s390_runtime_instr,sys_s390_runtime_instr)
 SYSCALL(sys_kcmp,compat_sys_kcmp)
 SYSCALL(sys_finit_module,compat_sys_finit_module)
 SYSCALL(sys_sched_setattr,compat_sys_sched_setattr)    /* 345 */
@@ -363,3 +363,22 @@ SYSCALL(sys_bpf,compat_sys_bpf)
 SYSCALL(sys_s390_pci_mmio_write,compat_sys_s390_pci_mmio_write)
 SYSCALL(sys_s390_pci_mmio_read,compat_sys_s390_pci_mmio_read)
 SYSCALL(sys_execveat,compat_sys_execveat)
+SYSCALL(sys_userfaultfd,sys_userfaultfd)               /* 355 */
+SYSCALL(sys_membarrier,sys_membarrier)
+SYSCALL(sys_recvmmsg,compat_sys_recvmmsg)
+SYSCALL(sys_sendmmsg,compat_sys_sendmmsg)
+SYSCALL(sys_socket,sys_socket)
+SYSCALL(sys_socketpair,compat_sys_socketpair)          /* 360 */
+SYSCALL(sys_bind,sys_bind)
+SYSCALL(sys_connect,sys_connect)
+SYSCALL(sys_listen,sys_listen)
+SYSCALL(sys_accept4,sys_accept4)
+SYSCALL(sys_getsockopt,compat_sys_getsockopt)          /* 365 */
+SYSCALL(sys_setsockopt,compat_sys_setsockopt)
+SYSCALL(sys_getsockname,compat_sys_getsockname)
+SYSCALL(sys_getpeername,compat_sys_getpeername)
+SYSCALL(sys_sendto,compat_sys_sendto)
+SYSCALL(sys_sendmsg,compat_sys_sendmsg)                        /* 370 */
+SYSCALL(sys_recvfrom,compat_sys_recvfrom)
+SYSCALL(sys_recvmsg,compat_sys_recvmsg)
+SYSCALL(sys_shutdown,sys_shutdown)
index b9ce650e9e992065aa611f5bc654f59b5b8bf40f..dafc44f519c340329581c8a5b2fda6fdb6920252 100644 (file)
@@ -25,7 +25,7 @@ static DEFINE_SPINLOCK(virt_timer_lock);
 static atomic64_t virt_timer_current;
 static atomic64_t virt_timer_elapsed;
 
-static DEFINE_PER_CPU(u64, mt_cycles[32]);
+DEFINE_PER_CPU(u64, mt_cycles[8]);
 static DEFINE_PER_CPU(u64, mt_scaling_mult) = { 1 };
 static DEFINE_PER_CPU(u64, mt_scaling_div) = { 1 };
 static DEFINE_PER_CPU(u64, mt_scaling_jiffies);
@@ -60,6 +60,34 @@ static inline int virt_timer_forward(u64 elapsed)
        return elapsed >= atomic64_read(&virt_timer_current);
 }
 
+static void update_mt_scaling(void)
+{
+       u64 cycles_new[8], *cycles_old;
+       u64 delta, fac, mult, div;
+       int i;
+
+       stcctm5(smp_cpu_mtid + 1, cycles_new);
+       cycles_old = this_cpu_ptr(mt_cycles);
+       fac = 1;
+       mult = div = 0;
+       for (i = 0; i <= smp_cpu_mtid; i++) {
+               delta = cycles_new[i] - cycles_old[i];
+               div += delta;
+               mult *= i + 1;
+               mult += delta * fac;
+               fac *= i + 1;
+       }
+       div *= fac;
+       if (div > 0) {
+               /* Update scaling factor */
+               __this_cpu_write(mt_scaling_mult, mult);
+               __this_cpu_write(mt_scaling_div, div);
+               memcpy(cycles_old, cycles_new,
+                      sizeof(u64) * (smp_cpu_mtid + 1));
+       }
+       __this_cpu_write(mt_scaling_jiffies, jiffies_64);
+}
+
 /*
  * Update process times based on virtual cpu times stored by entry.S
  * to the lowcore fields user_timer, system_timer & steal_clock.
@@ -69,7 +97,6 @@ static int do_account_vtime(struct task_struct *tsk, int hardirq_offset)
        struct thread_info *ti = task_thread_info(tsk);
        u64 timer, clock, user, system, steal;
        u64 user_scaled, system_scaled;
-       int i;
 
        timer = S390_lowcore.last_update_timer;
        clock = S390_lowcore.last_update_clock;
@@ -85,30 +112,10 @@ static int do_account_vtime(struct task_struct *tsk, int hardirq_offset)
        S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer;
        S390_lowcore.steal_timer += S390_lowcore.last_update_clock - clock;
 
-       /* Do MT utilization calculation */
+       /* Update MT utilization calculation */
        if (smp_cpu_mtid &&
-           time_after64(jiffies_64, __this_cpu_read(mt_scaling_jiffies))) {
-               u64 cycles_new[32], *cycles_old;
-               u64 delta, mult, div;
-
-               cycles_old = this_cpu_ptr(mt_cycles);
-               if (stcctm5(smp_cpu_mtid + 1, cycles_new) < 2) {
-                       mult = div = 0;
-                       for (i = 0; i <= smp_cpu_mtid; i++) {
-                               delta = cycles_new[i] - cycles_old[i];
-                               mult += delta;
-                               div += (i + 1) * delta;
-                       }
-                       if (mult > 0) {
-                               /* Update scaling factor */
-                               __this_cpu_write(mt_scaling_mult, mult);
-                               __this_cpu_write(mt_scaling_div, div);
-                               memcpy(cycles_old, cycles_new,
-                                      sizeof(u64) * (smp_cpu_mtid + 1));
-                       }
-               }
-               __this_cpu_write(mt_scaling_jiffies, jiffies_64);
-       }
+           time_after64(jiffies_64, this_cpu_read(mt_scaling_jiffies)))
+               update_mt_scaling();
 
        user = S390_lowcore.user_timer - ti->user_timer;
        S390_lowcore.steal_timer -= user;
@@ -177,6 +184,11 @@ void vtime_account_irq_enter(struct task_struct *tsk)
        S390_lowcore.last_update_timer = get_vtimer();
        S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer;
 
+       /* Update MT utilization calculation */
+       if (smp_cpu_mtid &&
+           time_after64(jiffies_64, this_cpu_read(mt_scaling_jiffies)))
+               update_mt_scaling();
+
        system = S390_lowcore.system_timer - ti->system_timer;
        S390_lowcore.steal_timer -= system;
        ti->system_timer = S390_lowcore.system_timer;
index c91eb941b444ee7cad8c5a9ea2523495e71e8f2d..0a67c40eece9b0f7bc74a350221975d2c7393cb0 100644 (file)
@@ -63,6 +63,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
        { "exit_program_interruption", VCPU_STAT(exit_program_interruption) },
        { "exit_instr_and_program_int", VCPU_STAT(exit_instr_and_program) },
        { "halt_successful_poll", VCPU_STAT(halt_successful_poll) },
+       { "halt_attempted_poll", VCPU_STAT(halt_attempted_poll) },
        { "halt_wakeup", VCPU_STAT(halt_wakeup) },
        { "instruction_lctlg", VCPU_STAT(instruction_lctlg) },
        { "instruction_lctl", VCPU_STAT(instruction_lctl) },
@@ -1574,7 +1575,7 @@ static void kvm_s390_vcpu_request(struct kvm_vcpu *vcpu)
 
 static void kvm_s390_vcpu_request_handled(struct kvm_vcpu *vcpu)
 {
-       atomic_or(PROG_REQUEST, &vcpu->arch.sie_block->prog20);
+       atomic_andnot(PROG_REQUEST, &vcpu->arch.sie_block->prog20);
 }
 
 /*
index 7de4e2f780d789478d4d700821944f96b3846586..30b2698a28e29a6991a7116da1877e5bdee1963e 100644 (file)
@@ -368,7 +368,7 @@ static void topology_add_core(struct toptree *core)
                cpumask_copy(&top->thread_mask, &core->mask);
                cpumask_copy(&top->core_mask, &core_mc(core)->mask);
                cpumask_copy(&top->book_mask, &core_book(core)->mask);
-               cpumask_set_cpu(cpu, node_to_cpumask_map[core_node(core)->id]);
+               cpumask_set_cpu(cpu, &node_to_cpumask_map[core_node(core)->id]);
                top->node_id = core_node(core)->id;
        }
 }
@@ -383,7 +383,7 @@ static void toptree_to_topology(struct toptree *numa)
 
        /* Clear all node masks */
        for (i = 0; i < MAX_NUMNODES; i++)
-               cpumask_clear(node_to_cpumask_map[i]);
+               cpumask_clear(&node_to_cpumask_map[i]);
 
        /* Rebuild all masks */
        toptree_for_each(core, numa, CORE)
index 09b1d2355bd9849ab583bb52c33eb789b4f9804b..43f32ce60aa3d98af0b7665090fa3eb080d12fa7 100644 (file)
@@ -23,7 +23,7 @@
 pg_data_t *node_data[MAX_NUMNODES];
 EXPORT_SYMBOL(node_data);
 
-cpumask_var_t node_to_cpumask_map[MAX_NUMNODES];
+cpumask_t node_to_cpumask_map[MAX_NUMNODES];
 EXPORT_SYMBOL(node_to_cpumask_map);
 
 const struct numa_mode numa_mode_plain = {
@@ -144,7 +144,7 @@ void __init numa_setup(void)
 static int __init numa_init_early(void)
 {
        /* Attach all possible CPUs to node 0 for now. */
-       cpumask_copy(node_to_cpumask_map[0], cpu_possible_mask);
+       cpumask_copy(&node_to_cpumask_map[0], cpu_possible_mask);
        return 0;
 }
 early_initcall(numa_init_early);
index 92ffe397b893c553c8504f10525a5e3d9d1e9e34..a05218ff3fe465b6e4812d7655360dc1b495a519 100644 (file)
@@ -13,3 +13,4 @@ generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += xor.h
 generic-y += serial.h
+generic-y += word-at-a-time.h
index 6f97a8f0d0d65718c09282fd146e8ca2d3a0c96e..6129aef6db766366dd5628aa760f1a70d6ce2707 100644 (file)
@@ -29,7 +29,7 @@
 static void __iomem *se7343_irq_regs;
 struct irq_domain *se7343_irq_domain;
 
-static void se7343_irq_demux(unsigned int irq, struct irq_desc *desc)
+static void se7343_irq_demux(struct irq_desc *desc)
 {
        struct irq_data *data = irq_desc_get_irq_data(desc);
        struct irq_chip *chip = irq_data_get_irq_chip(data);
index 60aebd14ccf8c5cd44e287d0ec958a78a136ca4f..24c74a88290c6559ef59108e4a478805c6bfd1b2 100644 (file)
@@ -28,7 +28,7 @@
 static void __iomem *se7722_irq_regs;
 struct irq_domain *se7722_irq_domain;
 
-static void se7722_irq_demux(unsigned int irq, struct irq_desc *desc)
+static void se7722_irq_demux(struct irq_desc *desc)
 {
        struct irq_data *data = irq_desc_get_irq_data(desc);
        struct irq_chip *chip = irq_data_get_irq_chip(data);
index 9f20338986521ba2d81b89a5a2f3b3c9d3fdfcd8..64e681e66c5797c68b5d3f59929b5c17960a825a 100644 (file)
@@ -92,7 +92,7 @@ static struct irq_chip se7724_irq_chip __read_mostly = {
        .irq_unmask     = enable_se7724_irq,
 };
 
-static void se7724_irq_demux(unsigned int __irq, struct irq_desc *desc)
+static void se7724_irq_demux(struct irq_desc *desc)
 {
        unsigned int irq = irq_desc_get_irq(desc);
        struct fpga_irq set = get_fpga_irq(irq);
index 24555c364d5bccfd0ff4e8ffa737d757a421aa3f..1fb2cbee25f2c5108ef8e8ba49b010ad6730006d 100644 (file)
@@ -60,7 +60,7 @@ static int x3proto_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
        return virq;
 }
 
-static void x3proto_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void x3proto_gpio_irq_handler(struct irq_desc *desc)
 {
        struct irq_data *data = irq_desc_get_irq_data(desc);
        struct irq_chip *chip = irq_data_get_irq_chip(data);
index e9735616bdc8ac96bb5fee14923ba53a0d5f12dd..8180092502f7040c4a0d94a1040d4629aab7dfa2 100644 (file)
@@ -56,7 +56,7 @@ static struct irq_chip hd64461_irq_chip = {
        .irq_unmask     = hd64461_unmask_irq,
 };
 
-static void hd64461_irq_demux(unsigned int irq, struct irq_desc *desc)
+static void hd64461_irq_demux(struct irq_desc *desc)
 {
        unsigned short intv = __raw_readw(HD64461_NIRR);
        unsigned int ext_irq = HD64461_IRQBASE;
index fe20d14ae051a5892350185d55ce1adfc352e538..ceb5201a30ed36899010715143b8679cd4a819fb 100644 (file)
@@ -59,6 +59,7 @@ pages_do_alias(unsigned long addr1, unsigned long addr2)
 
 #define clear_page(page)       memset((void *)(page), 0, PAGE_SIZE)
 extern void copy_page(void *to, void *from);
+#define copy_user_page(to, from, vaddr, pg)  __copy_user(to, from, PAGE_SIZE)
 
 struct page;
 struct vm_area_struct;
index 2e48eb8813ffa2fccf6df34ad5cee3bcf1857f94..c90930de76ba8670041598ba0d6461ef439c9539 100644 (file)
@@ -433,6 +433,7 @@ static struct crypto_alg algs[] = { {
                .blkcipher = {
                        .min_keysize    = AES_MIN_KEY_SIZE,
                        .max_keysize    = AES_MAX_KEY_SIZE,
+                       .ivsize         = AES_BLOCK_SIZE,
                        .setkey         = aes_set_key,
                        .encrypt        = cbc_encrypt,
                        .decrypt        = cbc_decrypt,
@@ -452,6 +453,7 @@ static struct crypto_alg algs[] = { {
                .blkcipher = {
                        .min_keysize    = AES_MIN_KEY_SIZE,
                        .max_keysize    = AES_MAX_KEY_SIZE,
+                       .ivsize         = AES_BLOCK_SIZE,
                        .setkey         = aes_set_key,
                        .encrypt        = ctr_crypt,
                        .decrypt        = ctr_crypt,
index 6bf2479a12fbe2a9c82b4275e40ac9e85ac191ed..561a84d93cf682a400a7555862f065f1fb04c84c 100644 (file)
@@ -274,6 +274,7 @@ static struct crypto_alg algs[] = { {
                .blkcipher = {
                        .min_keysize    = CAMELLIA_MIN_KEY_SIZE,
                        .max_keysize    = CAMELLIA_MAX_KEY_SIZE,
+                       .ivsize         = CAMELLIA_BLOCK_SIZE,
                        .setkey         = camellia_set_key,
                        .encrypt        = cbc_encrypt,
                        .decrypt        = cbc_decrypt,
index dd6a34fa6e19d2e36f5d30de6256655dc0ee2e0c..61af794aa2d31d5df27d0a318ac8b8f9d605637b 100644 (file)
@@ -429,6 +429,7 @@ static struct crypto_alg algs[] = { {
                .blkcipher = {
                        .min_keysize    = DES_KEY_SIZE,
                        .max_keysize    = DES_KEY_SIZE,
+                       .ivsize         = DES_BLOCK_SIZE,
                        .setkey         = des_set_key,
                        .encrypt        = cbc_encrypt,
                        .decrypt        = cbc_decrypt,
@@ -485,6 +486,7 @@ static struct crypto_alg algs[] = { {
                .blkcipher = {
                        .min_keysize    = DES3_EDE_KEY_SIZE,
                        .max_keysize    = DES3_EDE_KEY_SIZE,
+                       .ivsize         = DES3_EDE_BLOCK_SIZE,
                        .setkey         = des3_ede_set_key,
                        .encrypt        = cbc3_encrypt,
                        .decrypt        = cbc3_decrypt,
index 0299f052a2efc0a2f67321a51fa46094d0cf0fed..42efcf85f721b17196f88810fa52f82b0d24bf0d 100644 (file)
@@ -53,7 +53,7 @@ static inline unsigned int leon_eirq_get(int cpu)
 }
 
 /* Handle one or multiple IRQs from the extended interrupt controller */
-static void leon_handle_ext_irq(unsigned int irq, struct irq_desc *desc)
+static void leon_handle_ext_irq(struct irq_desc *desc)
 {
        unsigned int eirq;
        struct irq_bucket *p;
index 3382f7b3eeef2d9a5c74dece68e983501af955c0..1e77128a8f881b9670342d17f7f67d44d38b8698 100644 (file)
@@ -357,7 +357,7 @@ static struct irq_chip grpci1_irq = {
 };
 
 /* Handle one or multiple IRQs from the PCI core */
-static void grpci1_pci_flow_irq(unsigned int irq, struct irq_desc *desc)
+static void grpci1_pci_flow_irq(struct irq_desc *desc)
 {
        struct grpci1_priv *priv = grpci1priv;
        int i, ack = 0;
index 814fb1729b120bdeccbe2aacea958e7ae8add28d..f727c4de1316578505ed37aee52e39f9e9626ea5 100644 (file)
@@ -498,7 +498,7 @@ static struct irq_chip grpci2_irq = {
 };
 
 /* Handle one or multiple IRQs from the PCI core */
-static void grpci2_pci_flow_irq(unsigned int irq, struct irq_desc *desc)
+static void grpci2_pci_flow_irq(struct irq_desc *desc)
 {
        struct grpci2_priv *priv = grpci2priv;
        int i, ack = 0;
index ee186e13dfe6fde92c9127aa07dccc474d1253d2..f102048d9c0e78a31b6773715a491e85e755a89c 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/errno.h>
 #include <linux/io.h>
 #include <linux/module.h>
+#include <linux/string.h>
 
 #include <gxio/iorpc_globals.h>
 #include <gxio/iorpc_mpipe.h>
 /* HACK: Avoid pointless "shadow" warnings. */
 #define link link_shadow
 
-/**
- * strscpy - Copy a C-string into a sized buffer, but only if it fits
- * @dest: Where to copy the string to
- * @src: Where to copy the string from
- * @size: size of destination buffer
- *
- * Use this routine to avoid copying too-long strings.
- * The routine returns the total number of bytes copied
- * (including the trailing NUL) or zero if the buffer wasn't
- * big enough.  To ensure that programmers pay attention
- * to the return code, the destination has a single NUL
- * written at the front (if size is non-zero) when the
- * buffer is not big enough.
- */
-static size_t strscpy(char *dest, const char *src, size_t size)
-{
-       size_t len = strnlen(src, size) + 1;
-       if (len > size) {
-               if (size)
-                       dest[0] = '\0';
-               return 0;
-       }
-       memcpy(dest, src, len);
-       return len;
-}
-
 int gxio_mpipe_init(gxio_mpipe_context_t *context, unsigned int mpipe_index)
 {
        char file[32];
@@ -540,7 +515,7 @@ int gxio_mpipe_link_instance(const char *link_name)
        if (!context)
                return GXIO_ERR_NO_DEVICE;
 
-       if (strscpy(name.name, link_name, sizeof(name.name)) == 0)
+       if (strscpy(name.name, link_name, sizeof(name.name)) < 0)
                return GXIO_ERR_NO_DEVICE;
 
        return gxio_mpipe_info_instance_aux(context, name);
@@ -559,7 +534,7 @@ int gxio_mpipe_link_enumerate_mac(int idx, char *link_name, uint8_t *link_mac)
 
        rv = gxio_mpipe_info_enumerate_aux(context, idx, &name, &mac);
        if (rv >= 0) {
-               if (strscpy(link_name, name.name, sizeof(name.name)) == 0)
+               if (strscpy(link_name, name.name, sizeof(name.name)) < 0)
                        return GXIO_ERR_INVAL_MEMORY_SIZE;
                memcpy(link_mac, mac.mac, sizeof(mac.mac));
        }
@@ -576,7 +551,7 @@ int gxio_mpipe_link_open(gxio_mpipe_link_t *link,
        _gxio_mpipe_link_name_t name;
        int rv;
 
-       if (strscpy(name.name, link_name, sizeof(name.name)) == 0)
+       if (strscpy(name.name, link_name, sizeof(name.name)) < 0)
                return GXIO_ERR_NO_DEVICE;
 
        rv = gxio_mpipe_link_open_aux(context, name, flags);
index 9e5ce0d7b292160d5f544fcda08c00ea6c04f168..b66a693c2c3453e4f4642fea133890ab268a32d8 100644 (file)
@@ -6,7 +6,7 @@
 struct word_at_a_time { /* unused */ };
 #define WORD_AT_A_TIME_CONSTANTS {}
 
-/* Generate 0x01 byte values for non-zero bytes using a SIMD instruction. */
+/* Generate 0x01 byte values for zero bytes using a SIMD instruction. */
 static inline unsigned long has_zero(unsigned long val, unsigned long *data,
                                     const struct word_at_a_time *c)
 {
@@ -33,4 +33,10 @@ static inline long find_zero(unsigned long mask)
 #endif
 }
 
+#ifdef __BIG_ENDIAN
+#define zero_bytemask(mask) (~1ul << (63 - __builtin_clzl(mask)))
+#else
+#define zero_bytemask(mask) ((2ul << __builtin_ctzl(mask)) - 1)
+#endif
+
 #endif /* _ASM_WORD_AT_A_TIME_H */
index b3f73fd764a35b60002b507ea029c732363d4a6f..4c017d0d2de8c193f14f301138a45134bd587c5e 100644 (file)
@@ -304,17 +304,16 @@ static struct irq_chip tilegx_legacy_irq_chip = {
  * to Linux which just calls handle_level_irq() after clearing the
  * MAC INTx Assert status bit associated with this interrupt.
  */
-static void trio_handle_level_irq(unsigned int __irq, struct irq_desc *desc)
+static void trio_handle_level_irq(struct irq_desc *desc)
 {
        struct pci_controller *controller = irq_desc_get_handler_data(desc);
        gxio_trio_context_t *trio_context = controller->trio;
        uint64_t intx = (uint64_t)irq_desc_get_chip_data(desc);
-       unsigned int irq = irq_desc_get_irq(desc);
        int mac = controller->mac;
        unsigned int reg_offset;
        uint64_t level_mask;
 
-       handle_level_irq(irq, desc);
+       handle_level_irq(desc);
 
        /*
         * Clear the INTx Level status, otherwise future interrupts are
index f0da5a237e94077ced050b6f3d746c89d44bd341..9f1e05e12255b84d94d59f67ecbc7cc9330d889a 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/platform_device.h>
 #include <linux/usb/tilegx.h>
 #include <linux/init.h>
+#include <linux/module.h>
 #include <linux/types.h>
 
 static u64 ehci_dmamask = DMA_BIT_MASK(32);
index 098ab3333e7cdd5e4cdce7f20b28c7678ed2a852..e3abe6f3156d3fbacca4003c072954619c7e1bb1 100644 (file)
@@ -70,8 +70,8 @@ KBUILD_AFLAGS += $(ARCH_INCLUDE)
 
 USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -I%,,$(KBUILD_CFLAGS))) \
                $(ARCH_INCLUDE) $(MODE_INCLUDE) $(filter -I%,$(CFLAGS)) \
-               -D_FILE_OFFSET_BITS=64 -idirafter include \
-               -D__KERNEL__ -D__UM_HOST__
+               -D_FILE_OFFSET_BITS=64 -idirafter $(srctree)/include \
+               -idirafter $(obj)/include -D__KERNEL__ -D__UM_HOST__
 
 #This will adjust *FLAGS accordingly to the platform.
 include $(ARCH_DIR)/Makefile-os-$(OS)
index 149ec55f9c46abd97cbb9b69c7a55afa23e23393..904f3ebf4220153f816a1deca118381190f44ec4 100644 (file)
@@ -25,4 +25,5 @@ generic-y += preempt.h
 generic-y += switch_to.h
 generic-y += topology.h
 generic-y += trace_clock.h
+generic-y += word-at-a-time.h
 generic-y += xor.h
index d8a9fce6ee2e5b10a63405654c3958c7361951fe..98783dd0fa2ea697a50cb65afb661aa7f7bf0322 100644 (file)
@@ -220,7 +220,7 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
                show_regs(container_of(regs, struct pt_regs, regs));
                panic("Segfault with no mm");
        }
-       else if (!is_user && address < TASK_SIZE) {
+       else if (!is_user && address > PAGE_SIZE && address < TASK_SIZE) {
                show_regs(container_of(regs, struct pt_regs, regs));
                panic("Kernel tried to access user memory at addr 0x%lx, ip 0x%lx",
                       address, ip);
index e3ee4a51ef63a3ec7e7314aa7f00d59ec93ce37e..3f02d42328127bc6c41b786fd9b10145256cd57f 100644 (file)
@@ -96,7 +96,7 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
                               "ret = %d\n", -n);
                        ret = n;
                }
-               CATCH_EINTR(waitpid(pid, NULL, __WCLONE));
+               CATCH_EINTR(waitpid(pid, NULL, __WALL));
        }
 
 out_free2:
@@ -129,7 +129,7 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
                return err;
        }
        if (stack_out == NULL) {
-               CATCH_EINTR(pid = waitpid(pid, &status, __WCLONE));
+               CATCH_EINTR(pid = waitpid(pid, &status, __WALL));
                if (pid < 0) {
                        err = -errno;
                        printk(UM_KERN_ERR "run_helper_thread - wait failed, "
@@ -148,7 +148,7 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
 int helper_wait(int pid)
 {
        int ret, status;
-       int wflags = __WCLONE;
+       int wflags = __WALL;
 
        CATCH_EINTR(ret = waitpid(pid, &status, wflags));
        if (ret < 0) {
index 1fc7a286dc6f342319ec06a81b53a087b9708ef9..256c45b3ae343c983e667b01404d8fb3e3667b4a 100644 (file)
@@ -62,4 +62,5 @@ generic-y += ucontext.h
 generic-y += unaligned.h
 generic-y += user.h
 generic-y += vga.h
+generic-y += word-at-a-time.h
 generic-y += xor.h
index c53729d92e8df72529e5370f100a5b51b84977ce..eb1fd00303598bfcbdc0136e2656a2fb265bbd31 100644 (file)
@@ -112,7 +112,7 @@ static struct irq_chip puv3_low_gpio_chip = {
  * irq_controller_lock held, and IRQs disabled.  Decode the IRQ
  * and call the handler.
  */
-static void puv3_gpio_handler(unsigned int __irq, struct irq_desc *desc)
+static void puv3_gpio_handler(struct irq_desc *desc)
 {
        unsigned int mask, irq;
 
index 7aef2d52daa0d8ea8b55a683a11eb2c2e204eaef..96d058a871007e7b119bd3a6d3ff14eb9a5a61eb 100644 (file)
@@ -1006,7 +1006,7 @@ config X86_THERMAL_VECTOR
        depends on X86_MCE_INTEL
 
 config X86_LEGACY_VM86
-       bool "Legacy VM86 support (obsolete)"
+       bool "Legacy VM86 support"
        default n
        depends on X86_32
        ---help---
@@ -1018,19 +1018,20 @@ config X86_LEGACY_VM86
          available to accelerate real mode DOS programs.  However, any
          recent version of DOSEMU, X, or vbetool should be fully
          functional even without kernel VM86 support, as they will all
-         fall back to (pretty well performing) software emulation.
+         fall back to software emulation. Nevertheless, if you are using
+         a 16-bit DOS program where 16-bit performance matters, vm86
+         mode might be faster than emulation and you might want to
+         enable this option.
 
-         Anything that works on a 64-bit kernel is unlikely to need
-         this option, as 64-bit kernels don't, and can't, support V8086
-         mode.  This option is also unrelated to 16-bit protected mode
-         and is not needed to run most 16-bit programs under Wine.
+         Note that any app that works on a 64-bit kernel is unlikely to
+         need this option, as 64-bit kernels don't, and can't, support
+         V8086 mode. This option is also unrelated to 16-bit protected
+         mode and is not needed to run most 16-bit programs under Wine.
 
-         Enabling this option adds considerable attack surface to the
-         kernel and slows down system calls and exception handling.
+         Enabling this option increases the complexity of the kernel
+         and slows down exception handling a tiny bit.
 
-         Unless you use very old userspace or need the last drop of
-         performance in your real mode DOS games and can't use KVM,
-         say N here.
+         If unsure, say N here.
 
 config VM86
        bool
@@ -1307,6 +1308,7 @@ config HIGHMEM
 config X86_PAE
        bool "PAE (Physical Address Extension) Support"
        depends on X86_32 && !HIGHMEM4G
+       select SWIOTLB
        ---help---
          PAE is required for NX support, and furthermore enables
          larger swapspace support for non-overcommit purposes. It
index ee1b6d346b983ad196a003dcb47c7a1de439eb3b..db51c1f27446157001cedc87bdd38b551e2f1844 100644 (file)
@@ -667,6 +667,7 @@ setup_gop32(struct screen_info *si, efi_guid_t *proto,
                bool conout_found = false;
                void *dummy = NULL;
                u32 h = handles[i];
+               u32 current_fb_base;
 
                status = efi_call_early(handle_protocol, h,
                                        proto, (void **)&gop32);
@@ -678,7 +679,7 @@ setup_gop32(struct screen_info *si, efi_guid_t *proto,
                if (status == EFI_SUCCESS)
                        conout_found = true;
 
-               status = __gop_query32(gop32, &info, &size, &fb_base);
+               status = __gop_query32(gop32, &info, &size, &current_fb_base);
                if (status == EFI_SUCCESS && (!first_gop || conout_found)) {
                        /*
                         * Systems that use the UEFI Console Splitter may
@@ -692,6 +693,7 @@ setup_gop32(struct screen_info *si, efi_guid_t *proto,
                        pixel_format = info->pixel_format;
                        pixel_info = info->pixel_information;
                        pixels_per_scan_line = info->pixels_per_scan_line;
+                       fb_base = current_fb_base;
 
                        /*
                         * Once we've found a GOP supporting ConOut,
@@ -770,6 +772,7 @@ setup_gop64(struct screen_info *si, efi_guid_t *proto,
                bool conout_found = false;
                void *dummy = NULL;
                u64 h = handles[i];
+               u32 current_fb_base;
 
                status = efi_call_early(handle_protocol, h,
                                        proto, (void **)&gop64);
@@ -781,7 +784,7 @@ setup_gop64(struct screen_info *si, efi_guid_t *proto,
                if (status == EFI_SUCCESS)
                        conout_found = true;
 
-               status = __gop_query64(gop64, &info, &size, &fb_base);
+               status = __gop_query64(gop64, &info, &size, &current_fb_base);
                if (status == EFI_SUCCESS && (!first_gop || conout_found)) {
                        /*
                         * Systems that use the UEFI Console Splitter may
@@ -795,6 +798,7 @@ setup_gop64(struct screen_info *si, efi_guid_t *proto,
                        pixel_format = info->pixel_format;
                        pixel_info = info->pixel_information;
                        pixels_per_scan_line = info->pixels_per_scan_line;
+                       fb_base = current_fb_base;
 
                        /*
                         * Once we've found a GOP supporting ConOut,
index 80a0e4389c9ad3f5e6e1f6d8bc5292e391801ff2..bacaa13acac544e037571bd292e91f5239256edc 100644 (file)
@@ -554,6 +554,11 @@ static int __init camellia_aesni_init(void)
 {
        const char *feature_name;
 
+       if (!cpu_has_avx || !cpu_has_aes || !cpu_has_osxsave) {
+               pr_info("AVX or AES-NI instructions are not detected.\n");
+               return -ENODEV;
+       }
+
        if (!cpu_has_xfeatures(XSTATE_SSE | XSTATE_YMM, &feature_name)) {
                pr_info("CPU feature '%s' is not supported.\n", feature_name);
                return -ENODEV;
index d3033183ed7038ffae691c6784f10a994a0eb765..055a01de7c8da6e052cfdebe0be8447b14933c87 100644 (file)
@@ -1128,7 +1128,18 @@ END(error_exit)
 
 /* Runs on exception stack */
 ENTRY(nmi)
+       /*
+        * Fix up the exception frame if we're on Xen.
+        * PARAVIRT_ADJUST_EXCEPTION_FRAME is guaranteed to push at most
+        * one value to the stack on native, so it may clobber the rdx
+        * scratch slot, but it won't clobber any of the important
+        * slots past it.
+        *
+        * Xen is a different story, because the Xen frame itself overlaps
+        * the "NMI executing" variable.
+        */
        PARAVIRT_ADJUST_EXCEPTION_FRAME
+
        /*
         * We allow breakpoints in NMIs. If a breakpoint occurs, then
         * the iretq it performs will take us out of NMI context.
@@ -1179,9 +1190,12 @@ ENTRY(nmi)
         * we don't want to enable interrupts, because then we'll end
         * up in an awkward situation in which IRQs are on but NMIs
         * are off.
+        *
+        * We also must not push anything to the stack before switching
+        * stacks lest we corrupt the "NMI executing" variable.
         */
 
-       SWAPGS
+       SWAPGS_UNSAFE_STACK
        cld
        movq    %rsp, %rdx
        movq    PER_CPU_VAR(cpu_current_top_of_stack), %rsp
index 477fc28050e447681e957a470d756205fef81eca..9727b3b48bd174c8ae8297bd94e897484375618a 100644 (file)
 #define X86_FEATURE_HW_PSTATE  ( 7*32+ 8) /* AMD HW-PState */
 #define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9) /* AMD ProcFeedbackInterface */
 #define X86_FEATURE_HWP                ( 7*32+ 10) /* "hwp" Intel HWP */
-#define X86_FEATURE_HWP_NOITFY ( 7*32+ 11) /* Intel HWP_NOTIFY */
+#define X86_FEATURE_HWP_NOTIFY ( 7*32+ 11) /* Intel HWP_NOTIFY */
 #define X86_FEATURE_HWP_ACT_WINDOW ( 7*32+ 12) /* Intel HWP_ACT_WINDOW */
 #define X86_FEATURE_HWP_EPP    ( 7*32+13) /* Intel HWP_EPP */
 #define X86_FEATURE_HWP_PKG_REQ ( 7*32+14) /* Intel HWP_PKG_REQ */
 #define X86_FEATURE_AVX512PF   ( 9*32+26) /* AVX-512 Prefetch */
 #define X86_FEATURE_AVX512ER   ( 9*32+27) /* AVX-512 Exponential and Reciprocal */
 #define X86_FEATURE_AVX512CD   ( 9*32+28) /* AVX-512 Conflict Detection */
+#define X86_FEATURE_SHA_NI     ( 9*32+29) /* SHA1/SHA256 Instruction Extensions */
 
 /* Extended state features, CPUID level 0x0000000d:1 (eax), word 10 */
 #define X86_FEATURE_XSAVEOPT   (10*32+ 0) /* XSAVEOPT */
index 155162ea0e00292b619cc2a02ff8b2f31fafd02b..ae68be92f75587ce2bfdc2d09f18711ef9cd9c8a 100644 (file)
@@ -86,6 +86,18 @@ extern u64 asmlinkage efi_call(void *fp, ...);
 extern void __iomem *__init efi_ioremap(unsigned long addr, unsigned long size,
                                        u32 type, u64 attribute);
 
+#ifdef CONFIG_KASAN
+/*
+ * CONFIG_KASAN may redefine memset to __memset.  __memset function is present
+ * only in kernel binary.  Since the EFI stub linked into a separate binary it
+ * doesn't have __memset().  So we should use standard memset from
+ * arch/x86/boot/compressed/string.c.  The same applies to memcpy and memmove.
+ */
+#undef memcpy
+#undef memset
+#undef memmove
+#endif
+
 #endif /* CONFIG_X86_32 */
 
 extern struct efi_scratch efi_scratch;
index c12e845f59e6b40c5afb62d8ecf1e08f22dce4db..3a36ee704c307414b305e1cac21ec9aba4de5872 100644 (file)
@@ -40,6 +40,7 @@
 
 #define KVM_PIO_PAGE_OFFSET 1
 #define KVM_COALESCED_MMIO_PAGE_OFFSET 2
+#define KVM_HALT_POLL_NS_DEFAULT 500000
 
 #define KVM_IRQCHIP_NUM_PINS  KVM_IOAPIC_NUM_PINS
 
@@ -711,6 +712,7 @@ struct kvm_vcpu_stat {
        u32 nmi_window_exits;
        u32 halt_exits;
        u32 halt_successful_poll;
+       u32 halt_attempted_poll;
        u32 halt_wakeup;
        u32 request_irq_exits;
        u32 irq_exits;
@@ -1224,10 +1226,8 @@ void kvm_complete_insn_gp(struct kvm_vcpu *vcpu, int err);
 
 int kvm_is_in_guest(void);
 
-int __x86_set_memory_region(struct kvm *kvm,
-                           const struct kvm_userspace_memory_region *mem);
-int x86_set_memory_region(struct kvm *kvm,
-                         const struct kvm_userspace_memory_region *mem);
+int __x86_set_memory_region(struct kvm *kvm, int id, gpa_t gpa, u32 size);
+int x86_set_memory_region(struct kvm *kvm, int id, gpa_t gpa, u32 size);
 bool kvm_vcpu_is_reset_bsp(struct kvm_vcpu *vcpu);
 bool kvm_vcpu_is_bsp(struct kvm_vcpu *vcpu);
 
index c1c0a1c14344c111158ac5f7f30a4fca13650d16..b8c14bb7fc8f37ee004dc10342a99c8579110e1d 100644 (file)
 #define DEBUGCTLMSR_BTS_OFF_USR                (1UL << 10)
 #define DEBUGCTLMSR_FREEZE_LBRS_ON_PMI (1UL << 11)
 
+#define MSR_PEBS_FRONTEND              0x000003f7
+
 #define MSR_IA32_POWER_CTL             0x000001fc
 
 #define MSR_IA32_MC0_CTL               0x00000400
 /* C1E active bits in int pending message */
 #define K8_INTP_C1E_ACTIVE_MASK                0x18000000
 #define MSR_K8_TSEG_ADDR               0xc0010112
+#define MSR_K8_TSEG_MASK               0xc0010113
 #define K8_MTRRFIXRANGE_DRAM_ENABLE    0x00040000 /* MtrrFixDramEn bit    */
 #define K8_MTRRFIXRANGE_DRAM_MODIFY    0x00080000 /* MtrrFixDramModEn bit */
 #define K8_MTRR_RDMEM_WRMEM_MASK       0x18181818 /* Mask: RdMem|WrMem    */
index ce029e4fa7c62bc2bf969ed8df9f2330af2abb28..31247b5bff7c8ff86d893851dc9073b72a647cc2 100644 (file)
@@ -97,7 +97,6 @@ struct pv_lazy_ops {
 struct pv_time_ops {
        unsigned long long (*sched_clock)(void);
        unsigned long long (*steal_clock)(int cpu);
-       unsigned long (*get_tsc_khz)(void);
 };
 
 struct pv_cpu_ops {
index 655e07a48f6cfa9c09114108f7d8b4cb466fc705..67f08230103aa5ab5f9f74ce90622577b76caef4 100644 (file)
@@ -41,6 +41,7 @@ struct pvclock_wall_clock {
 
 #define PVCLOCK_TSC_STABLE_BIT (1 << 0)
 #define PVCLOCK_GUEST_STOPPED  (1 << 1)
+/* PVCLOCK_COUNTS_FROM_ZERO broke ABI and can't be used anymore. */
 #define PVCLOCK_COUNTS_FROM_ZERO (1 << 2)
 #endif /* __ASSEMBLY__ */
 #endif /* _ASM_X86_PVCLOCK_ABI_H */
index 9d51fae1cba345e5cf01387a6c16207a6b5be872..eaba0807603009e6ed1612a7049bb35bafeaf31e 100644 (file)
@@ -39,18 +39,27 @@ static inline void queued_spin_unlock(struct qspinlock *lock)
 }
 #endif
 
-#define virt_queued_spin_lock virt_queued_spin_lock
-
-static inline bool virt_queued_spin_lock(struct qspinlock *lock)
+#ifdef CONFIG_PARAVIRT
+#define virt_spin_lock virt_spin_lock
+static inline bool virt_spin_lock(struct qspinlock *lock)
 {
        if (!static_cpu_has(X86_FEATURE_HYPERVISOR))
                return false;
 
-       while (atomic_cmpxchg(&lock->val, 0, _Q_LOCKED_VAL) != 0)
-               cpu_relax();
+       /*
+        * On hypervisors without PARAVIRT_SPINLOCKS support we fall
+        * back to a Test-and-Set spinlock, because fair locks have
+        * horrible lock 'holder' preemption issues.
+        */
+
+       do {
+               while (atomic_read(&lock->val) != 0)
+                       cpu_relax();
+       } while (atomic_cmpxchg(&lock->val, 0, _Q_LOCKED_VAL) != 0);
 
        return true;
 }
+#endif /* CONFIG_PARAVIRT */
 
 #include <asm-generic/qspinlock.h>
 
index e4661196994e86b189da7f6c2e84841d3dcdcb9b..ff8b9a17dc4b2d354971fb52b60b69e6fbb0e903 100644 (file)
@@ -27,12 +27,11 @@ static __always_inline void *__inline_memcpy(void *to, const void *from, size_t
    function. */
 
 #define __HAVE_ARCH_MEMCPY 1
+extern void *memcpy(void *to, const void *from, size_t len);
 extern void *__memcpy(void *to, const void *from, size_t len);
 
 #ifndef CONFIG_KMEMCHECK
-#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4
-extern void *memcpy(void *to, const void *from, size_t len);
-#else
+#if (__GNUC__ == 4 && __GNUC_MINOR__ < 3) || __GNUC__ < 4
 #define memcpy(dst, src, len)                                  \
 ({                                                             \
        size_t __len = (len);                                   \
index 83aea8055119e2f26beb1c909536609d30e88943..4c20dd333412db5b367d0625e9b7cf69a7891493 100644 (file)
@@ -336,10 +336,10 @@ HYPERVISOR_update_descriptor(u64 ma, u64 desc)
        return _hypercall4(int, update_descriptor, ma, ma>>32, desc, desc>>32);
 }
 
-static inline int
+static inline long
 HYPERVISOR_memory_op(unsigned int cmd, void *arg)
 {
-       return _hypercall2(int, memory_op, cmd, arg);
+       return _hypercall2(long, memory_op, cmd, arg);
 }
 
 static inline int
index b0ae1c4dc79142d9284d14e76ac181f1c271ad64..217909b4d6f56d84892655f680f974eaf83ec78e 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __ASM_X86_BITSPERLONG_H
 #define __ASM_X86_BITSPERLONG_H
 
-#ifdef __x86_64__
+#if defined(__x86_64__) && !defined(__ILP32__)
 # define __BITS_PER_LONG 64
 #else
 # define __BITS_PER_LONG 32
index c42827eb86cf0c52c36389d0c26dc937776b03bf..25f909362b7a89c42f32c8ebe74fb91239df3ca8 100644 (file)
@@ -338,10 +338,15 @@ done:
 
 static void __init_or_module optimize_nops(struct alt_instr *a, u8 *instr)
 {
+       unsigned long flags;
+
        if (instr[0] != 0x90)
                return;
 
+       local_irq_save(flags);
        add_nops(instr + (a->instrlen - a->padlen), a->padlen);
+       sync_core();
+       local_irq_restore(flags);
 
        DUMP_BYTES(instr, a->instrlen, "%p: [%d:%d) optimized NOPs: ",
                   instr, a->instrlen - a->padlen, a->padlen);
index 3ca3e46aa405ff606c205e849e9470735405f4cf..24e94ce454e2363e6ad14ae2e4cff6c4ac492ab4 100644 (file)
@@ -336,6 +336,13 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
        apic_write(APIC_LVTT, lvtt_value);
 
        if (lvtt_value & APIC_LVT_TIMER_TSCDEADLINE) {
+               /*
+                * See Intel SDM: TSC-Deadline Mode chapter. In xAPIC mode,
+                * writing to the APIC LVTT and TSC_DEADLINE MSR isn't serialized.
+                * According to Intel, MFENCE can do the serialization here.
+                */
+               asm volatile("mfence" : : : "memory");
+
                printk_once(KERN_DEBUG "TSC deadline timer enabled\n");
                return;
        }
index 38a76f826530358c898ae781cebea72069e3277c..4f2821527014e14eba4051c27d05dc53ffe958f3 100644 (file)
@@ -2522,6 +2522,7 @@ void __init setup_ioapic_dest(void)
        int pin, ioapic, irq, irq_entry;
        const struct cpumask *mask;
        struct irq_data *idata;
+       struct irq_chip *chip;
 
        if (skip_ioapic_setup == 1)
                return;
@@ -2545,9 +2546,11 @@ void __init setup_ioapic_dest(void)
                else
                        mask = apic->target_cpus();
 
-               irq_set_affinity(irq, mask);
+               chip = irq_data_get_irq_chip(idata);
+               /* Might be lapic_chip for irq 0 */
+               if (chip->irq_set_affinity)
+                       chip->irq_set_affinity(idata, mask, false);
        }
-
 }
 #endif
 
@@ -2906,6 +2909,7 @@ int mp_irqdomain_alloc(struct irq_domain *domain, unsigned int virq,
        struct irq_data *irq_data;
        struct mp_chip_data *data;
        struct irq_alloc_info *info = arg;
+       unsigned long flags;
 
        if (!info || nr_irqs > 1)
                return -EINVAL;
@@ -2938,11 +2942,14 @@ int mp_irqdomain_alloc(struct irq_domain *domain, unsigned int virq,
 
        cfg = irqd_cfg(irq_data);
        add_pin_to_irq_node(data, ioapic_alloc_attr_node(info), ioapic, pin);
+
+       local_irq_save(flags);
        if (info->ioapic_entry)
                mp_setup_entry(cfg, data, info->ioapic_entry);
        mp_register_handler(virq, data->trigger);
        if (virq < nr_legacy_irqs())
                legacy_pic->mask(virq);
+       local_irq_restore(flags);
 
        apic_printk(APIC_VERBOSE, KERN_DEBUG
                    "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> IRQ %d Mode:%i Active:%i Dest:%d)\n",
index 1bbd0fe2c8062f35f795d2ed23f75373f5a6b872..836d11b92811ce73446a6081f02a38231fdb9429 100644 (file)
@@ -489,10 +489,8 @@ static int apic_set_affinity(struct irq_data *irq_data,
 
        err = assign_irq_vector(irq, data, dest);
        if (err) {
-               struct irq_data *top = irq_get_irq_data(irq);
-
                if (assign_irq_vector(irq, data,
-                                     irq_data_get_affinity_mask(top)))
+                                     irq_data_get_affinity_mask(irq_data)))
                        pr_err("Failed to recover vector for irq %d\n", irq);
                return err;
        }
index 07ce52c22ec843b72177307942bb5785e31458ef..de22ea7ff82f93ea1a8d4a204f10a7c6e8fdef76 100644 (file)
@@ -1110,10 +1110,10 @@ void print_cpu_info(struct cpuinfo_x86 *c)
        else
                printk(KERN_CONT "%d86", c->x86);
 
-       printk(KERN_CONT " (fam: %02x, model: %02x", c->x86, c->x86_model);
+       printk(KERN_CONT " (family: 0x%x, model: 0x%x", c->x86, c->x86_model);
 
        if (c->x86_mask || c->cpuid_level >= 0)
-               printk(KERN_CONT ", stepping: %02x)\n", c->x86_mask);
+               printk(KERN_CONT ", stepping: 0x%x)\n", c->x86_mask);
        else
                printk(KERN_CONT ")\n");
 
index 381c8b9b3a33570fcf88b82fa69d1fc43298d89f..20e242ea1bc46b5f5828c7b95071d920853b7609 100644 (file)
 struct ms_hyperv_info ms_hyperv;
 EXPORT_SYMBOL_GPL(ms_hyperv);
 
-static void (*hv_kexec_handler)(void);
-static void (*hv_crash_handler)(struct pt_regs *regs);
-
 #if IS_ENABLED(CONFIG_HYPERV)
 static void (*vmbus_handler)(void);
+static void (*hv_kexec_handler)(void);
+static void (*hv_crash_handler)(struct pt_regs *regs);
 
 void hyperv_vector_handler(struct pt_regs *regs)
 {
@@ -96,8 +95,8 @@ void hv_remove_crash_handler(void)
        hv_crash_handler = NULL;
 }
 EXPORT_SYMBOL_GPL(hv_remove_crash_handler);
-#endif
 
+#ifdef CONFIG_KEXEC_CORE
 static void hv_machine_shutdown(void)
 {
        if (kexec_in_progress && hv_kexec_handler)
@@ -111,7 +110,8 @@ static void hv_machine_crash_shutdown(struct pt_regs *regs)
                hv_crash_handler(regs);
        native_machine_crash_shutdown(regs);
 }
-
+#endif /* CONFIG_KEXEC_CORE */
+#endif /* CONFIG_HYPERV */
 
 static uint32_t  __init ms_hyperv_platform(void)
 {
@@ -186,8 +186,10 @@ static void __init ms_hyperv_init_platform(void)
        no_timer_check = 1;
 #endif
 
+#if IS_ENABLED(CONFIG_HYPERV) && defined(CONFIG_KEXEC_CORE)
        machine_ops.shutdown = hv_machine_shutdown;
        machine_ops.crash_shutdown = hv_machine_crash_shutdown;
+#endif
        mark_tsc_unstable("running on Hyper-V");
 }
 
index 5edf6d868fc16c1e24633d1ea1b727b69fb68584..165be83a7fa48a105fe67c67791e19d0b92c22ad 100644 (file)
@@ -47,6 +47,7 @@ enum extra_reg_type {
        EXTRA_REG_RSP_1 = 1,    /* offcore_response_1 */
        EXTRA_REG_LBR   = 2,    /* lbr_select */
        EXTRA_REG_LDLAT = 3,    /* ld_lat_threshold */
+       EXTRA_REG_FE    = 4,    /* fe_* */
 
        EXTRA_REG_MAX           /* number of entries needed */
 };
index cd9b6d0b10bf408d04956e45c1a2d77bd3f99b07..f63360be22387d4fb4cb30728f1834ee4cbd6228 100644 (file)
@@ -205,6 +205,11 @@ static struct extra_reg intel_skl_extra_regs[] __read_mostly = {
        INTEL_UEVENT_EXTRA_REG(0x01b7, MSR_OFFCORE_RSP_0, 0x3fffff8fffull, RSP_0),
        INTEL_UEVENT_EXTRA_REG(0x01bb, MSR_OFFCORE_RSP_1, 0x3fffff8fffull, RSP_1),
        INTEL_UEVENT_PEBS_LDLAT_EXTRA_REG(0x01cd),
+       /*
+        * Note the low 8 bits eventsel code is not a continuous field, containing
+        * some #GPing bits. These are masked out.
+        */
+       INTEL_UEVENT_EXTRA_REG(0x01c6, MSR_PEBS_FRONTEND, 0x7fff17, FE),
        EVENT_EXTRA_END
 };
 
@@ -250,7 +255,7 @@ struct event_constraint intel_bdw_event_constraints[] = {
        FIXED_EVENT_CONSTRAINT(0x003c, 1),      /* CPU_CLK_UNHALTED.CORE */
        FIXED_EVENT_CONSTRAINT(0x0300, 2),      /* CPU_CLK_UNHALTED.REF */
        INTEL_UEVENT_CONSTRAINT(0x148, 0x4),    /* L1D_PEND_MISS.PENDING */
-       INTEL_EVENT_CONSTRAINT(0xa3, 0x4),      /* CYCLE_ACTIVITY.* */
+       INTEL_UEVENT_CONSTRAINT(0x8a3, 0x4),    /* CYCLE_ACTIVITY.CYCLES_L1D_MISS */
        EVENT_CONSTRAINT_END
 };
 
@@ -2316,9 +2321,12 @@ static struct event_constraint *
 intel_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
                            struct perf_event *event)
 {
-       struct event_constraint *c1 = cpuc->event_constraint[idx];
+       struct event_constraint *c1 = NULL;
        struct event_constraint *c2;
 
+       if (idx >= 0) /* fake does < 0 */
+               c1 = cpuc->event_constraint[idx];
+
        /*
         * first time only
         * - static constraint: no change across incremental scheduling calls
@@ -2888,6 +2896,8 @@ PMU_FORMAT_ATTR(offcore_rsp, "config1:0-63");
 
 PMU_FORMAT_ATTR(ldlat, "config1:0-15");
 
+PMU_FORMAT_ATTR(frontend, "config1:0-23");
+
 static struct attribute *intel_arch3_formats_attr[] = {
        &format_attr_event.attr,
        &format_attr_umask.attr,
@@ -2904,6 +2914,11 @@ static struct attribute *intel_arch3_formats_attr[] = {
        NULL,
 };
 
+static struct attribute *skl_format_attr[] = {
+       &format_attr_frontend.attr,
+       NULL,
+};
+
 static __initconst const struct x86_pmu core_pmu = {
        .name                   = "core",
        .handle_irq             = x86_pmu_handle_irq,
@@ -3513,7 +3528,8 @@ __init int intel_pmu_init(void)
 
                x86_pmu.hw_config = hsw_hw_config;
                x86_pmu.get_event_constraints = hsw_get_event_constraints;
-               x86_pmu.cpu_events = hsw_events_attrs;
+               x86_pmu.format_attrs = merge_attr(intel_arch3_formats_attr,
+                                                 skl_format_attr);
                WARN_ON(!x86_pmu.format_attrs);
                x86_pmu.cpu_events = hsw_events_attrs;
                pr_cont("Skylake events, ");
index 54690e885759dd7b89711d3568e8916495e7b34f..d1c0f254afbeefe61fcfaeeb7625664d7d352918 100644 (file)
@@ -222,6 +222,7 @@ static void __bts_event_start(struct perf_event *event)
        if (!buf || bts_buffer_is_full(buf, bts))
                return;
 
+       event->hw.itrace_started = 1;
        event->hw.state = 0;
 
        if (!buf->snapshot)
index 086b12eae79493329c8792538ea8c6f179aee4fb..f32ac13934f2310c1b61f54884246089c7e06e01 100644 (file)
@@ -10,12 +10,12 @@ enum perf_msr_id {
        PERF_MSR_EVENT_MAX,
 };
 
-bool test_aperfmperf(int idx)
+static bool test_aperfmperf(int idx)
 {
        return boot_cpu_has(X86_FEATURE_APERFMPERF);
 }
 
-bool test_intel(int idx)
+static bool test_intel(int idx)
 {
        if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||
            boot_cpu_data.x86 != 6)
index 3d423a101fae05ccd722a4e564b83ba5e0112b6e..608fb26c72544c5ee0fd7793c0703f642c7ed60f 100644 (file)
@@ -37,7 +37,7 @@ void init_scattered_cpuid_features(struct cpuinfo_x86 *c)
                { X86_FEATURE_PLN,              CR_EAX, 4, 0x00000006, 0 },
                { X86_FEATURE_PTS,              CR_EAX, 6, 0x00000006, 0 },
                { X86_FEATURE_HWP,              CR_EAX, 7, 0x00000006, 0 },
-               { X86_FEATURE_HWP_NOITFY,       CR_EAX, 8, 0x00000006, 0 },
+               { X86_FEATURE_HWP_NOTIFY,       CR_EAX, 8, 0x00000006, 0 },
                { X86_FEATURE_HWP_ACT_WINDOW,   CR_EAX, 9, 0x00000006, 0 },
                { X86_FEATURE_HWP_EPP,          CR_EAX,10, 0x00000006, 0 },
                { X86_FEATURE_HWP_PKG_REQ,      CR_EAX,11, 0x00000006, 0 },
index e068d6683dba6bab6bd4c9f9804a621385e3baee..74ca2fe7a0b3a60d7fc6c71c2d5dda30fcf3e767 100644 (file)
@@ -185,10 +185,9 @@ void native_machine_crash_shutdown(struct pt_regs *regs)
 }
 
 #ifdef CONFIG_KEXEC_FILE
-static int get_nr_ram_ranges_callback(unsigned long start_pfn,
-                               unsigned long nr_pfn, void *arg)
+static int get_nr_ram_ranges_callback(u64 start, u64 end, void *arg)
 {
-       int *nr_ranges = arg;
+       unsigned int *nr_ranges = arg;
 
        (*nr_ranges)++;
        return 0;
@@ -214,7 +213,7 @@ static void fill_up_crash_elf_data(struct crash_elf_data *ced,
 
        ced->image = image;
 
-       walk_system_ram_range(0, -1, &nr_ranges,
+       walk_system_ram_res(0, -1, &nr_ranges,
                                get_nr_ram_ranges_callback);
 
        ced->max_nr_ranges = nr_ranges;
index c80cf66996785bd5309eaf8c1831ee0fcf7ec9b3..38da8f29a9c81f075d4b91fc6982e28ae2f28eee 100644 (file)
@@ -68,11 +68,10 @@ static inline void *current_stack(void)
        return (void *)(current_stack_pointer() & ~(THREAD_SIZE - 1));
 }
 
-static inline int
-execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq)
+static inline int execute_on_irq_stack(int overflow, struct irq_desc *desc)
 {
        struct irq_stack *curstk, *irqstk;
-       u32 *isp, *prev_esp, arg1, arg2;
+       u32 *isp, *prev_esp, arg1;
 
        curstk = (struct irq_stack *) current_stack();
        irqstk = __this_cpu_read(hardirq_stack);
@@ -98,8 +97,8 @@ execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq)
        asm volatile("xchgl     %%ebx,%%esp     \n"
                     "call      *%%edi          \n"
                     "movl      %%ebx,%%esp     \n"
-                    : "=a" (arg1), "=d" (arg2), "=b" (isp)
-                    :  "0" (irq),   "1" (desc),  "2" (isp),
+                    : "=a" (arg1), "=b" (isp)
+                    :  "0" (desc),   "1" (isp),
                        "D" (desc->handle_irq)
                     : "memory", "cc", "ecx");
        return 1;
@@ -150,19 +149,15 @@ void do_softirq_own_stack(void)
 
 bool handle_irq(struct irq_desc *desc, struct pt_regs *regs)
 {
-       unsigned int irq;
-       int overflow;
-
-       overflow = check_stack_overflow();
+       int overflow = check_stack_overflow();
 
        if (IS_ERR_OR_NULL(desc))
                return false;
 
-       irq = irq_desc_get_irq(desc);
-       if (user_mode(regs) || !execute_on_irq_stack(overflow, desc, irq)) {
+       if (user_mode(regs) || !execute_on_irq_stack(overflow, desc)) {
                if (unlikely(overflow))
                        print_stack_overflow();
-               generic_handle_irq_desc(irq, desc);
+               generic_handle_irq_desc(desc);
        }
 
        return true;
index ff16ccb918f20c08527e95cd8073dd8b9b68f113..c767cf2bc80a0b8f44be521f6171c3d8d4fa7b7d 100644 (file)
@@ -75,6 +75,6 @@ bool handle_irq(struct irq_desc *desc, struct pt_regs *regs)
        if (unlikely(IS_ERR_OR_NULL(desc)))
                return false;
 
-       generic_handle_irq_desc(irq_desc_get_irq(desc), desc);
+       generic_handle_irq_desc(desc);
        return true;
 }
index 2bcc0525f1c10e80b3db33df075b3189c4a68239..6acc9dd91f368a1fada3f2d6dd2a0755f1d7b46d 100644 (file)
@@ -58,7 +58,7 @@ static struct ldt_struct *alloc_ldt_struct(int size)
        if (alloc_size > PAGE_SIZE)
                new_ldt->entries = vzalloc(alloc_size);
        else
-               new_ldt->entries = kzalloc(PAGE_SIZE, GFP_KERNEL);
+               new_ldt->entries = (void *)get_zeroed_page(GFP_KERNEL);
 
        if (!new_ldt->entries) {
                kfree(new_ldt);
@@ -95,7 +95,7 @@ static void free_ldt_struct(struct ldt_struct *ldt)
        if (ldt->size * LDT_ENTRY_SIZE > PAGE_SIZE)
                vfree(ldt->entries);
        else
-               kfree(ldt->entries);
+               free_page((unsigned long)ldt->entries);
        kfree(ldt);
 }
 
index f68e48f5f6c2692be684fc4460fa9b59bed6c901..c2130aef3f9d25d6c6a47f3499b8096c5cfb8e80 100644 (file)
 #include <asm/timer.h>
 #include <asm/special_insns.h>
 
-/* nop stub */
-void _paravirt_nop(void)
-{
-}
+/*
+ * nop stub, which must not clobber anything *including the stack* to
+ * avoid confusing the entry prologues.
+ */
+extern void _paravirt_nop(void);
+asm (".pushsection .entry.text, \"ax\"\n"
+     ".global _paravirt_nop\n"
+     "_paravirt_nop:\n\t"
+     "ret\n\t"
+     ".size _paravirt_nop, . - _paravirt_nop\n\t"
+     ".type _paravirt_nop, @function\n\t"
+     ".popsection");
 
 /* identity function, which can be inlined */
 u32 _paravirt_ident_32(u32 x)
index 84b8ef82a159bc7756914b40518d7fa00ed968ff..cd99433b8ba17597cbc9e91aba9c40eee7e05e4b 100644 (file)
@@ -131,11 +131,12 @@ void dma_generic_free_coherent(struct device *dev, size_t size, void *vaddr,
 
 bool arch_dma_alloc_attrs(struct device **dev, gfp_t *gfp)
 {
-       *gfp = dma_alloc_coherent_gfp_flags(*dev, *gfp);
-       *gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32);
-
        if (!*dev)
                *dev = &x86_dma_fallback_dev;
+
+       *gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32);
+       *gfp = dma_alloc_coherent_gfp_flags(*dev, *gfp);
+
        if (!is_device_dma_capable(*dev))
                return false;
        return true;
index 6d0e62ae8516760d6ae4af7deaa31418e82238fa..9f7c21c22477e59462d72e930d79a4c2a238a051 100644 (file)
@@ -84,6 +84,9 @@ EXPORT_SYMBOL_GPL(idle_notifier_unregister);
 int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
 {
        memcpy(dst, src, arch_task_struct_size);
+#ifdef CONFIG_VM86
+       dst->thread.vm86 = NULL;
+#endif
 
        return fpu__copy(&dst->thread.fpu, &src->thread.fpu);
 }
@@ -506,3 +509,58 @@ unsigned long arch_randomize_brk(struct mm_struct *mm)
        return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
 }
 
+/*
+ * Called from fs/proc with a reference on @p to find the function
+ * which called into schedule(). This needs to be done carefully
+ * because the task might wake up and we might look at a stack
+ * changing under us.
+ */
+unsigned long get_wchan(struct task_struct *p)
+{
+       unsigned long start, bottom, top, sp, fp, ip;
+       int count = 0;
+
+       if (!p || p == current || p->state == TASK_RUNNING)
+               return 0;
+
+       start = (unsigned long)task_stack_page(p);
+       if (!start)
+               return 0;
+
+       /*
+        * Layout of the stack page:
+        *
+        * ----------- topmax = start + THREAD_SIZE - sizeof(unsigned long)
+        * PADDING
+        * ----------- top = topmax - TOP_OF_KERNEL_STACK_PADDING
+        * stack
+        * ----------- bottom = start + sizeof(thread_info)
+        * thread_info
+        * ----------- start
+        *
+        * The tasks stack pointer points at the location where the
+        * framepointer is stored. The data on the stack is:
+        * ... IP FP ... IP FP
+        *
+        * We need to read FP and IP, so we need to adjust the upper
+        * bound by another unsigned long.
+        */
+       top = start + THREAD_SIZE - TOP_OF_KERNEL_STACK_PADDING;
+       top -= 2 * sizeof(unsigned long);
+       bottom = start + sizeof(struct thread_info);
+
+       sp = READ_ONCE(p->thread.sp);
+       if (sp < bottom || sp > top)
+               return 0;
+
+       fp = READ_ONCE_NOCHECK(*(unsigned long *)sp);
+       do {
+               if (fp < bottom || fp > top)
+                       return 0;
+               ip = READ_ONCE_NOCHECK(*(unsigned long *)(fp + sizeof(unsigned long)));
+               if (!in_sched_functions(ip))
+                       return ip;
+               fp = READ_ONCE_NOCHECK(*(unsigned long *)fp);
+       } while (count++ < 16 && p->state != TASK_RUNNING);
+       return 0;
+}
index c13df2c735f82765015a4924b08aed9904c27419..737527b40e5bf40bb1e757b635cc30994db911bd 100644 (file)
@@ -324,31 +324,3 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
 
        return prev_p;
 }
-
-#define top_esp                (THREAD_SIZE - sizeof(unsigned long))
-#define top_ebp                (THREAD_SIZE - 2*sizeof(unsigned long))
-
-unsigned long get_wchan(struct task_struct *p)
-{
-       unsigned long bp, sp, ip;
-       unsigned long stack_page;
-       int count = 0;
-       if (!p || p == current || p->state == TASK_RUNNING)
-               return 0;
-       stack_page = (unsigned long)task_stack_page(p);
-       sp = p->thread.sp;
-       if (!stack_page || sp < stack_page || sp > top_esp+stack_page)
-               return 0;
-       /* include/asm-i386/system.h:switch_to() pushes bp last. */
-       bp = *(unsigned long *) sp;
-       do {
-               if (bp < stack_page || bp > top_ebp+stack_page)
-                       return 0;
-               ip = *(unsigned long *) (bp+4);
-               if (!in_sched_functions(ip))
-                       return ip;
-               bp = *(unsigned long *) bp;
-       } while (count++ < 16);
-       return 0;
-}
-
index 3c1bbcf129245aa7909708af46489d73f2e9c297..b35921a670b25b03878e3f9ac2e96abfae0e910c 100644 (file)
@@ -499,30 +499,6 @@ void set_personality_ia32(bool x32)
 }
 EXPORT_SYMBOL_GPL(set_personality_ia32);
 
-unsigned long get_wchan(struct task_struct *p)
-{
-       unsigned long stack;
-       u64 fp, ip;
-       int count = 0;
-
-       if (!p || p == current || p->state == TASK_RUNNING)
-               return 0;
-       stack = (unsigned long)task_stack_page(p);
-       if (p->thread.sp < stack || p->thread.sp >= stack+THREAD_SIZE)
-               return 0;
-       fp = *(u64 *)(p->thread.sp);
-       do {
-               if (fp < (unsigned long)stack ||
-                   fp >= (unsigned long)stack+THREAD_SIZE)
-                       return 0;
-               ip = *(u64 *)(fp+8);
-               if (!in_sched_functions(ip))
-                       return ip;
-               fp = *(u64 *)fp;
-       } while (count++ < 16);
-       return 0;
-}
-
 long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
 {
        int ret = 0;
index fdb7f2a2d3286013a7ea41d392e48596c90fc672..a3cccbfc5f777e3483cad7da4a5a587bdd56c09c 100644 (file)
@@ -1173,6 +1173,14 @@ void __init setup_arch(char **cmdline_p)
        clone_pgd_range(initial_page_table + KERNEL_PGD_BOUNDARY,
                        swapper_pg_dir     + KERNEL_PGD_BOUNDARY,
                        KERNEL_PGD_PTRS);
+
+       /*
+        * sync back low identity map too.  It is used for example
+        * in the 32-bit EFI stub.
+        */
+       clone_pgd_range(initial_page_table,
+                       swapper_pg_dir     + KERNEL_PGD_BOUNDARY,
+                       KERNEL_PGD_PTRS);
 #endif
 
        tboot_probe();
index e0c198e5f920202bf25fa36e34922d4b0d29d82c..892ee2e5ecbce417df506715f7b28d28c403ef91 100644 (file)
@@ -509,7 +509,7 @@ void __inquire_remote_apic(int apicid)
  */
 #define UDELAY_10MS_DEFAULT 10000
 
-static unsigned int init_udelay = UDELAY_10MS_DEFAULT;
+static unsigned int init_udelay = INT_MAX;
 
 static int __init cpu_init_udelay(char *str)
 {
@@ -522,13 +522,16 @@ early_param("cpu_init_udelay", cpu_init_udelay);
 static void __init smp_quirk_init_udelay(void)
 {
        /* if cmdline changed it from default, leave it alone */
-       if (init_udelay != UDELAY_10MS_DEFAULT)
+       if (init_udelay != INT_MAX)
                return;
 
        /* if modern processor, use no delay */
        if (((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && (boot_cpu_data.x86 == 6)) ||
            ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) && (boot_cpu_data.x86 >= 0xF)))
                init_udelay = 0;
+
+       /* else, use legacy delay */
+       init_udelay = UDELAY_10MS_DEFAULT;
 }
 
 /*
@@ -657,7 +660,9 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)
                /*
                 * Give the other CPU some time to accept the IPI.
                 */
-               if (init_udelay)
+               if (init_udelay == 0)
+                       udelay(10);
+               else
                        udelay(300);
 
                pr_debug("Startup point 1\n");
@@ -668,7 +673,9 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)
                /*
                 * Give the other CPU some time to accept the IPI.
                 */
-               if (init_udelay)
+               if (init_udelay == 0)
+                       udelay(10);
+               else
                        udelay(200);
 
                if (maxlvt > 3)         /* Due to the Pentium erratum 3AP.  */
index c8d52cb4cb6e8b9ee9d81cfc9c0fa3603284ce0e..c3f7602cd0386b2fb0a1a7437263f9c71f27d03c 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/hypervisor.h>
 #include <asm/nmi.h>
 #include <asm/x86_init.h>
+#include <asm/geode.h>
 
 unsigned int __read_mostly cpu_khz;    /* TSC clocks / usec, not used here */
 EXPORT_SYMBOL(cpu_khz);
@@ -1013,15 +1014,17 @@ EXPORT_SYMBOL_GPL(mark_tsc_unstable);
 
 static void __init check_system_tsc_reliable(void)
 {
-#ifdef CONFIG_MGEODE_LX
-       /* RTSC counts during suspend */
+#if defined(CONFIG_MGEODEGX1) || defined(CONFIG_MGEODE_LX) || defined(CONFIG_X86_GENERIC)
+       if (is_geode_lx()) {
+               /* RTSC counts during suspend */
 #define RTSC_SUSP 0x100
-       unsigned long res_low, res_high;
+               unsigned long res_low, res_high;
 
-       rdmsr_safe(MSR_GEODE_BUSCONT_CONF0, &res_low, &res_high);
-       /* Geode_LX - the OLPC CPU has a very reliable TSC */
-       if (res_low & RTSC_SUSP)
-               tsc_clocksource_reliable = 1;
+               rdmsr_safe(MSR_GEODE_BUSCONT_CONF0, &res_low, &res_high);
+               /* Geode_LX - the OLPC CPU has a very reliable TSC */
+               if (res_low & RTSC_SUSP)
+                       tsc_clocksource_reliable = 1;
+       }
 #endif
        if (boot_cpu_has(X86_FEATURE_TSC_RELIABLE))
                tsc_clocksource_reliable = 1;
index abd8b856bd2b50af307caa2eaad953dc80c4ed00..5246193519614dbd8d3a602544e8117376df05f7 100644 (file)
@@ -45,6 +45,7 @@
 #include <linux/audit.h>
 #include <linux/stddef.h>
 #include <linux/slab.h>
+#include <linux/security.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -232,6 +233,32 @@ static long do_sys_vm86(struct vm86plus_struct __user *user_vm86, bool plus)
        struct pt_regs *regs = current_pt_regs();
        unsigned long err = 0;
 
+       err = security_mmap_addr(0);
+       if (err) {
+               /*
+                * vm86 cannot virtualize the address space, so vm86 users
+                * need to manage the low 1MB themselves using mmap.  Given
+                * that BIOS places important data in the first page, vm86
+                * is essentially useless if mmap_min_addr != 0.  DOSEMU,
+                * for example, won't even bother trying to use vm86 if it
+                * can't map a page at virtual address 0.
+                *
+                * To reduce the available kernel attack surface, simply
+                * disallow vm86(old) for users who cannot mmap at va 0.
+                *
+                * The implementation of security_mmap_addr will allow
+                * suitably privileged users to map va 0 even if
+                * vm.mmap_min_addr is set above 0, and we want this
+                * behavior for vm86 as well, as it ensures that legacy
+                * tools like vbetool will not fail just because of
+                * vm.mmap_min_addr.
+                */
+               pr_info_once("Denied a call to vm86(old) from %s[%d] (uid: %d).  Set the vm.mmap_min_addr sysctl to 0 and/or adjust LSM mmap_min_addr policy to enable vm86 if you are using a vm86-based DOS emulator.\n",
+                            current->comm, task_pid_nr(current),
+                            from_kuid_munged(&init_user_ns, current_uid()));
+               return -EPERM;
+       }
+
        if (!vm86) {
                if (!(vm86 = kzalloc(sizeof(*vm86), GFP_KERNEL)))
                        return -ENOMEM;
index b372a7557c16c7d8391fffafdf0b1c74b49c4822..9da95b9daf8deb83af606ae0fffb73f7fab74ff2 100644 (file)
@@ -2418,7 +2418,7 @@ static int rsm_load_state_64(struct x86_emulate_ctxt *ctxt, u64 smbase)
        u64 val, cr0, cr4;
        u32 base3;
        u16 selector;
-       int i;
+       int i, r;
 
        for (i = 0; i < 16; i++)
                *reg_write(ctxt, i) = GET_SMSTATE(u64, smbase, 0x7ff8 - i * 8);
@@ -2460,13 +2460,17 @@ static int rsm_load_state_64(struct x86_emulate_ctxt *ctxt, u64 smbase)
        dt.address =                GET_SMSTATE(u64, smbase, 0x7e68);
        ctxt->ops->set_gdt(ctxt, &dt);
 
+       r = rsm_enter_protected_mode(ctxt, cr0, cr4);
+       if (r != X86EMUL_CONTINUE)
+               return r;
+
        for (i = 0; i < 6; i++) {
-               int r = rsm_load_seg_64(ctxt, smbase, i);
+               r = rsm_load_seg_64(ctxt, smbase, i);
                if (r != X86EMUL_CONTINUE)
                        return r;
        }
 
-       return rsm_enter_protected_mode(ctxt, cr0, cr4);
+       return X86EMUL_CONTINUE;
 }
 
 static int em_rsm(struct x86_emulate_ctxt *ctxt)
index 69088a1ba5090ffa763a56f5c105560f360de767..ff606f5079137736e6827c3b3f33dec808854974 100644 (file)
@@ -3322,7 +3322,7 @@ walk_shadow_page_get_mmio_spte(struct kvm_vcpu *vcpu, u64 addr, u64 *sptep)
                        break;
 
                reserved |= is_shadow_zero_bits_set(&vcpu->arch.mmu, spte,
-                                                   leaf);
+                                                   iterator.level);
        }
 
        walk_shadow_page_lockless_end(vcpu);
@@ -3614,7 +3614,7 @@ static void
 __reset_rsvds_bits_mask(struct kvm_vcpu *vcpu,
                        struct rsvd_bits_validate *rsvd_check,
                        int maxphyaddr, int level, bool nx, bool gbpages,
-                       bool pse)
+                       bool pse, bool amd)
 {
        u64 exb_bit_rsvd = 0;
        u64 gbpages_bit_rsvd = 0;
@@ -3631,7 +3631,7 @@ __reset_rsvds_bits_mask(struct kvm_vcpu *vcpu,
         * Non-leaf PML4Es and PDPEs reserve bit 8 (which would be the G bit for
         * leaf entries) on AMD CPUs only.
         */
-       if (guest_cpuid_is_amd(vcpu))
+       if (amd)
                nonleaf_bit8_rsvd = rsvd_bits(8, 8);
 
        switch (level) {
@@ -3699,7 +3699,7 @@ static void reset_rsvds_bits_mask(struct kvm_vcpu *vcpu,
        __reset_rsvds_bits_mask(vcpu, &context->guest_rsvd_check,
                                cpuid_maxphyaddr(vcpu), context->root_level,
                                context->nx, guest_cpuid_has_gbpages(vcpu),
-                               is_pse(vcpu));
+                               is_pse(vcpu), guest_cpuid_is_amd(vcpu));
 }
 
 static void
@@ -3749,13 +3749,24 @@ static void reset_rsvds_bits_mask_ept(struct kvm_vcpu *vcpu,
 void
 reset_shadow_zero_bits_mask(struct kvm_vcpu *vcpu, struct kvm_mmu *context)
 {
+       /*
+        * Passing "true" to the last argument is okay; it adds a check
+        * on bit 8 of the SPTEs which KVM doesn't use anyway.
+        */
        __reset_rsvds_bits_mask(vcpu, &context->shadow_zero_check,
                                boot_cpu_data.x86_phys_bits,
                                context->shadow_root_level, context->nx,
-                               guest_cpuid_has_gbpages(vcpu), is_pse(vcpu));
+                               guest_cpuid_has_gbpages(vcpu), is_pse(vcpu),
+                               true);
 }
 EXPORT_SYMBOL_GPL(reset_shadow_zero_bits_mask);
 
+static inline bool boot_cpu_is_amd(void)
+{
+       WARN_ON_ONCE(!tdp_enabled);
+       return shadow_x_mask == 0;
+}
+
 /*
  * the direct page table on host, use as much mmu features as
  * possible, however, kvm currently does not do execution-protection.
@@ -3764,11 +3775,11 @@ static void
 reset_tdp_shadow_zero_bits_mask(struct kvm_vcpu *vcpu,
                                struct kvm_mmu *context)
 {
-       if (guest_cpuid_is_amd(vcpu))
+       if (boot_cpu_is_amd())
                __reset_rsvds_bits_mask(vcpu, &context->shadow_zero_check,
                                        boot_cpu_data.x86_phys_bits,
                                        context->shadow_root_level, false,
-                                       cpu_has_gbpages, true);
+                                       cpu_has_gbpages, true, true);
        else
                __reset_rsvds_bits_mask_ept(&context->shadow_zero_check,
                                            boot_cpu_data.x86_phys_bits,
index fdb8cb63a6c0da7c8ba0585360646d7aa0c54f32..2f9ed1ff063260ed33bf845e1e523df0ad2bd58e 100644 (file)
@@ -202,6 +202,7 @@ module_param(npt, int, S_IRUGO);
 static int nested = true;
 module_param(nested, int, S_IRUGO);
 
+static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0);
 static void svm_flush_tlb(struct kvm_vcpu *vcpu);
 static void svm_complete_interrupts(struct vcpu_svm *svm);
 
@@ -513,7 +514,7 @@ static void skip_emulated_instruction(struct kvm_vcpu *vcpu)
        struct vcpu_svm *svm = to_svm(vcpu);
 
        if (svm->vmcb->control.next_rip != 0) {
-               WARN_ON(!static_cpu_has(X86_FEATURE_NRIPS));
+               WARN_ON_ONCE(!static_cpu_has(X86_FEATURE_NRIPS));
                svm->next_rip = svm->vmcb->control.next_rip;
        }
 
@@ -865,64 +866,6 @@ static void svm_disable_lbrv(struct vcpu_svm *svm)
        set_msr_interception(msrpm, MSR_IA32_LASTINTTOIP, 0, 0);
 }
 
-#define MTRR_TYPE_UC_MINUS     7
-#define MTRR2PROTVAL_INVALID 0xff
-
-static u8 mtrr2protval[8];
-
-static u8 fallback_mtrr_type(int mtrr)
-{
-       /*
-        * WT and WP aren't always available in the host PAT.  Treat
-        * them as UC and UC- respectively.  Everything else should be
-        * there.
-        */
-       switch (mtrr)
-       {
-       case MTRR_TYPE_WRTHROUGH:
-               return MTRR_TYPE_UNCACHABLE;
-       case MTRR_TYPE_WRPROT:
-               return MTRR_TYPE_UC_MINUS;
-       default:
-               BUG();
-       }
-}
-
-static void build_mtrr2protval(void)
-{
-       int i;
-       u64 pat;
-
-       for (i = 0; i < 8; i++)
-               mtrr2protval[i] = MTRR2PROTVAL_INVALID;
-
-       /* Ignore the invalid MTRR types.  */
-       mtrr2protval[2] = 0;
-       mtrr2protval[3] = 0;
-
-       /*
-        * Use host PAT value to figure out the mapping from guest MTRR
-        * values to nested page table PAT/PCD/PWT values.  We do not
-        * want to change the host PAT value every time we enter the
-        * guest.
-        */
-       rdmsrl(MSR_IA32_CR_PAT, pat);
-       for (i = 0; i < 8; i++) {
-               u8 mtrr = pat >> (8 * i);
-
-               if (mtrr2protval[mtrr] == MTRR2PROTVAL_INVALID)
-                       mtrr2protval[mtrr] = __cm_idx2pte(i);
-       }
-
-       for (i = 0; i < 8; i++) {
-               if (mtrr2protval[i] == MTRR2PROTVAL_INVALID) {
-                       u8 fallback = fallback_mtrr_type(i);
-                       mtrr2protval[i] = mtrr2protval[fallback];
-                       BUG_ON(mtrr2protval[i] == MTRR2PROTVAL_INVALID);
-               }
-       }
-}
-
 static __init int svm_hardware_setup(void)
 {
        int cpu;
@@ -989,7 +932,6 @@ static __init int svm_hardware_setup(void)
        } else
                kvm_disable_tdp();
 
-       build_mtrr2protval();
        return 0;
 
 err:
@@ -1144,43 +1086,6 @@ static u64 svm_compute_tsc_offset(struct kvm_vcpu *vcpu, u64 target_tsc)
        return target_tsc - tsc;
 }
 
-static void svm_set_guest_pat(struct vcpu_svm *svm, u64 *g_pat)
-{
-       struct kvm_vcpu *vcpu = &svm->vcpu;
-
-       /* Unlike Intel, AMD takes the guest's CR0.CD into account.
-        *
-        * AMD does not have IPAT.  To emulate it for the case of guests
-        * with no assigned devices, just set everything to WB.  If guests
-        * have assigned devices, however, we cannot force WB for RAM
-        * pages only, so use the guest PAT directly.
-        */
-       if (!kvm_arch_has_assigned_device(vcpu->kvm))
-               *g_pat = 0x0606060606060606;
-       else
-               *g_pat = vcpu->arch.pat;
-}
-
-static u64 svm_get_mt_mask(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio)
-{
-       u8 mtrr;
-
-       /*
-        * 1. MMIO: trust guest MTRR, so same as item 3.
-        * 2. No passthrough: always map as WB, and force guest PAT to WB as well
-        * 3. Passthrough: can't guarantee the result, try to trust guest.
-        */
-       if (!is_mmio && !kvm_arch_has_assigned_device(vcpu->kvm))
-               return 0;
-
-       if (!kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_CD_NW_CLEARED) &&
-           kvm_read_cr0(vcpu) & X86_CR0_CD)
-               return _PAGE_NOCACHE;
-
-       mtrr = kvm_mtrr_get_guest_memory_type(vcpu, gfn);
-       return mtrr2protval[mtrr];
-}
-
 static void init_vmcb(struct vcpu_svm *svm, bool init_event)
 {
        struct vmcb_control_area *control = &svm->vmcb->control;
@@ -1263,7 +1168,8 @@ static void init_vmcb(struct vcpu_svm *svm, bool init_event)
         * svm_set_cr0() sets PG and WP and clears NW and CD on save->cr0.
         * It also updates the guest-visible cr0 value.
         */
-       (void)kvm_set_cr0(&svm->vcpu, X86_CR0_NW | X86_CR0_CD | X86_CR0_ET);
+       svm_set_cr0(&svm->vcpu, X86_CR0_NW | X86_CR0_CD | X86_CR0_ET);
+       kvm_mmu_reset_context(&svm->vcpu);
 
        save->cr4 = X86_CR4_PAE;
        /* rdx = ?? */
@@ -1276,7 +1182,6 @@ static void init_vmcb(struct vcpu_svm *svm, bool init_event)
                clr_cr_intercept(svm, INTERCEPT_CR3_READ);
                clr_cr_intercept(svm, INTERCEPT_CR3_WRITE);
                save->g_pat = svm->vcpu.arch.pat;
-               svm_set_guest_pat(svm, &save->g_pat);
                save->cr3 = 0;
                save->cr4 = 0;
        }
@@ -1671,10 +1576,13 @@ static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
 
        if (!vcpu->fpu_active)
                cr0 |= X86_CR0_TS;
-
-       /* These are emulated via page tables.  */
-       cr0 &= ~(X86_CR0_CD | X86_CR0_NW);
-
+       /*
+        * re-enable caching here because the QEMU bios
+        * does not do it - this results in some delay at
+        * reboot
+        */
+       if (kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_CD_NW_CLEARED))
+               cr0 &= ~(X86_CR0_CD | X86_CR0_NW);
        svm->vmcb->save.cr0 = cr0;
        mark_dirty(svm->vmcb, VMCB_CR);
        update_cr0_intercept(svm);
@@ -3349,16 +3257,6 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
        case MSR_VM_IGNNE:
                vcpu_unimpl(vcpu, "unimplemented wrmsr: 0x%x data 0x%llx\n", ecx, data);
                break;
-       case MSR_IA32_CR_PAT:
-               if (npt_enabled) {
-                       if (!kvm_mtrr_valid(vcpu, MSR_IA32_CR_PAT, data))
-                               return 1;
-                       vcpu->arch.pat = data;
-                       svm_set_guest_pat(svm, &svm->vmcb->save.g_pat);
-                       mark_dirty(svm->vmcb, VMCB_NPT);
-                       break;
-               }
-               /* fall through */
        default:
                return kvm_set_msr_common(vcpu, msr);
        }
@@ -4193,6 +4091,11 @@ static bool svm_has_high_real_mode_segbase(void)
        return true;
 }
 
+static u64 svm_get_mt_mask(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio)
+{
+       return 0;
+}
+
 static void svm_cpuid_update(struct kvm_vcpu *vcpu)
 {
 }
index d01986832afc28ed225b2f414ccb2742e528169c..6a8bc64566abde57f8914f103a6b5d9d49ed8ae8 100644 (file)
@@ -4105,17 +4105,13 @@ static void seg_setup(int seg)
 static int alloc_apic_access_page(struct kvm *kvm)
 {
        struct page *page;
-       struct kvm_userspace_memory_region kvm_userspace_mem;
        int r = 0;
 
        mutex_lock(&kvm->slots_lock);
        if (kvm->arch.apic_access_page_done)
                goto out;
-       kvm_userspace_mem.slot = APIC_ACCESS_PAGE_PRIVATE_MEMSLOT;
-       kvm_userspace_mem.flags = 0;
-       kvm_userspace_mem.guest_phys_addr = APIC_DEFAULT_PHYS_BASE;
-       kvm_userspace_mem.memory_size = PAGE_SIZE;
-       r = __x86_set_memory_region(kvm, &kvm_userspace_mem);
+       r = __x86_set_memory_region(kvm, APIC_ACCESS_PAGE_PRIVATE_MEMSLOT,
+                                   APIC_DEFAULT_PHYS_BASE, PAGE_SIZE);
        if (r)
                goto out;
 
@@ -4140,17 +4136,12 @@ static int alloc_identity_pagetable(struct kvm *kvm)
 {
        /* Called with kvm->slots_lock held. */
 
-       struct kvm_userspace_memory_region kvm_userspace_mem;
        int r = 0;
 
        BUG_ON(kvm->arch.ept_identity_pagetable_done);
 
-       kvm_userspace_mem.slot = IDENTITY_PAGETABLE_PRIVATE_MEMSLOT;
-       kvm_userspace_mem.flags = 0;
-       kvm_userspace_mem.guest_phys_addr =
-               kvm->arch.ept_identity_map_addr;
-       kvm_userspace_mem.memory_size = PAGE_SIZE;
-       r = __x86_set_memory_region(kvm, &kvm_userspace_mem);
+       r = __x86_set_memory_region(kvm, IDENTITY_PAGETABLE_PRIVATE_MEMSLOT,
+                                   kvm->arch.ept_identity_map_addr, PAGE_SIZE);
 
        return r;
 }
@@ -4949,14 +4940,9 @@ static int vmx_interrupt_allowed(struct kvm_vcpu *vcpu)
 static int vmx_set_tss_addr(struct kvm *kvm, unsigned int addr)
 {
        int ret;
-       struct kvm_userspace_memory_region tss_mem = {
-               .slot = TSS_PRIVATE_MEMSLOT,
-               .guest_phys_addr = addr,
-               .memory_size = PAGE_SIZE * 3,
-               .flags = 0,
-       };
 
-       ret = x86_set_memory_region(kvm, &tss_mem);
+       ret = x86_set_memory_region(kvm, TSS_PRIVATE_MEMSLOT, addr,
+                                   PAGE_SIZE * 3);
        if (ret)
                return ret;
        kvm->arch.tss_addr = addr;
@@ -6064,6 +6050,8 @@ static __init int hardware_setup(void)
        memcpy(vmx_msr_bitmap_longmode_x2apic,
                        vmx_msr_bitmap_longmode, PAGE_SIZE);
 
+       set_bit(0, vmx_vpid_bitmap); /* 0 is reserved for host */
+
        if (enable_apicv) {
                for (msr = 0x800; msr <= 0x8ff; msr++)
                        vmx_disable_intercept_msr_read_x2apic(msr);
@@ -8615,17 +8603,22 @@ static u64 vmx_get_mt_mask(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio)
        u64 ipat = 0;
 
        /* For VT-d and EPT combination
-        * 1. MMIO: guest may want to apply WC, trust it.
+        * 1. MMIO: always map as UC
         * 2. EPT with VT-d:
         *   a. VT-d without snooping control feature: can't guarantee the
-        *      result, try to trust guest.  So the same as item 1.
+        *      result, try to trust guest.
         *   b. VT-d with snooping control feature: snooping control feature of
         *      VT-d engine can guarantee the cache correctness. Just set it
         *      to WB to keep consistent with host. So the same as item 3.
         * 3. EPT without VT-d: always map as WB and set IPAT=1 to keep
         *    consistent with host MTRR
         */
-       if (!is_mmio && !kvm_arch_has_noncoherent_dma(vcpu->kvm)) {
+       if (is_mmio) {
+               cache = MTRR_TYPE_UNCACHABLE;
+               goto exit;
+       }
+
+       if (!kvm_arch_has_noncoherent_dma(vcpu->kvm)) {
                ipat = VMX_EPT_IPAT_BIT;
                cache = MTRR_TYPE_WRBACK;
                goto exit;
index a60bdbccff5189b5a98b9a7fcc6a3b9f7ff5eeec..9a9a198303219b6430159af03d4d1e1d898ec6f7 100644 (file)
@@ -149,6 +149,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
        { "nmi_window", VCPU_STAT(nmi_window_exits) },
        { "halt_exits", VCPU_STAT(halt_exits) },
        { "halt_successful_poll", VCPU_STAT(halt_successful_poll) },
+       { "halt_attempted_poll", VCPU_STAT(halt_attempted_poll) },
        { "halt_wakeup", VCPU_STAT(halt_wakeup) },
        { "hypercalls", VCPU_STAT(hypercalls) },
        { "request_irq", VCPU_STAT(request_irq_exits) },
@@ -1707,8 +1708,6 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
                vcpu->pvclock_set_guest_stopped_request = false;
        }
 
-       pvclock_flags |= PVCLOCK_COUNTS_FROM_ZERO;
-
        /* If the host uses TSC clocksource, then it is stable */
        if (use_master_clock)
                pvclock_flags |= PVCLOCK_TSC_STABLE_BIT;
@@ -2006,8 +2005,6 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
                                        &vcpu->requests);
 
                        ka->boot_vcpu_runs_old_kvmclock = tmp;
-
-                       ka->kvmclock_offset = -get_kernel_ns();
                }
 
                vcpu->arch.time = data;
@@ -2189,6 +2186,8 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
        case MSR_IA32_LASTINTFROMIP:
        case MSR_IA32_LASTINTTOIP:
        case MSR_K8_SYSCFG:
+       case MSR_K8_TSEG_ADDR:
+       case MSR_K8_TSEG_MASK:
        case MSR_K7_HWCR:
        case MSR_VM_HSAVE_PA:
        case MSR_K8_INT_PENDING_MSG:
@@ -6454,6 +6453,12 @@ static inline int vcpu_block(struct kvm *kvm, struct kvm_vcpu *vcpu)
        return 1;
 }
 
+static inline bool kvm_vcpu_running(struct kvm_vcpu *vcpu)
+{
+       return (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE &&
+               !vcpu->arch.apf.halted);
+}
+
 static int vcpu_run(struct kvm_vcpu *vcpu)
 {
        int r;
@@ -6462,8 +6467,7 @@ static int vcpu_run(struct kvm_vcpu *vcpu)
        vcpu->srcu_idx = srcu_read_lock(&kvm->srcu);
 
        for (;;) {
-               if (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE &&
-                   !vcpu->arch.apf.halted)
+               if (kvm_vcpu_running(vcpu))
                        r = vcpu_enter_guest(vcpu);
                else
                        r = vcpu_block(kvm, vcpu);
@@ -7475,34 +7479,66 @@ void kvm_arch_sync_events(struct kvm *kvm)
        kvm_free_pit(kvm);
 }
 
-int __x86_set_memory_region(struct kvm *kvm,
-                           const struct kvm_userspace_memory_region *mem)
+int __x86_set_memory_region(struct kvm *kvm, int id, gpa_t gpa, u32 size)
 {
        int i, r;
+       unsigned long hva;
+       struct kvm_memslots *slots = kvm_memslots(kvm);
+       struct kvm_memory_slot *slot, old;
 
        /* Called with kvm->slots_lock held.  */
-       BUG_ON(mem->slot >= KVM_MEM_SLOTS_NUM);
+       if (WARN_ON(id >= KVM_MEM_SLOTS_NUM))
+               return -EINVAL;
 
+       slot = id_to_memslot(slots, id);
+       if (size) {
+               if (WARN_ON(slot->npages))
+                       return -EEXIST;
+
+               /*
+                * MAP_SHARED to prevent internal slot pages from being moved
+                * by fork()/COW.
+                */
+               hva = vm_mmap(NULL, 0, size, PROT_READ | PROT_WRITE,
+                             MAP_SHARED | MAP_ANONYMOUS, 0);
+               if (IS_ERR((void *)hva))
+                       return PTR_ERR((void *)hva);
+       } else {
+               if (!slot->npages)
+                       return 0;
+
+               hva = 0;
+       }
+
+       old = *slot;
        for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++) {
-               struct kvm_userspace_memory_region m = *mem;
+               struct kvm_userspace_memory_region m;
 
-               m.slot |= i << 16;
+               m.slot = id | (i << 16);
+               m.flags = 0;
+               m.guest_phys_addr = gpa;
+               m.userspace_addr = hva;
+               m.memory_size = size;
                r = __kvm_set_memory_region(kvm, &m);
                if (r < 0)
                        return r;
        }
 
+       if (!size) {
+               r = vm_munmap(old.userspace_addr, old.npages * PAGE_SIZE);
+               WARN_ON(r < 0);
+       }
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(__x86_set_memory_region);
 
-int x86_set_memory_region(struct kvm *kvm,
-                         const struct kvm_userspace_memory_region *mem)
+int x86_set_memory_region(struct kvm *kvm, int id, gpa_t gpa, u32 size)
 {
        int r;
 
        mutex_lock(&kvm->slots_lock);
-       r = __x86_set_memory_region(kvm, mem);
+       r = __x86_set_memory_region(kvm, id, gpa, size);
        mutex_unlock(&kvm->slots_lock);
 
        return r;
@@ -7517,16 +7553,9 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
                 * unless the the memory map has changed due to process exit
                 * or fd copying.
                 */
-               struct kvm_userspace_memory_region mem;
-               memset(&mem, 0, sizeof(mem));
-               mem.slot = APIC_ACCESS_PAGE_PRIVATE_MEMSLOT;
-               x86_set_memory_region(kvm, &mem);
-
-               mem.slot = IDENTITY_PAGETABLE_PRIVATE_MEMSLOT;
-               x86_set_memory_region(kvm, &mem);
-
-               mem.slot = TSS_PRIVATE_MEMSLOT;
-               x86_set_memory_region(kvm, &mem);
+               x86_set_memory_region(kvm, APIC_ACCESS_PAGE_PRIVATE_MEMSLOT, 0, 0);
+               x86_set_memory_region(kvm, IDENTITY_PAGETABLE_PRIVATE_MEMSLOT, 0, 0);
+               x86_set_memory_region(kvm, TSS_PRIVATE_MEMSLOT, 0, 0);
        }
        kvm_iommu_unmap_guest(kvm);
        kfree(kvm->arch.vpic);
@@ -7629,27 +7658,6 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
                                const struct kvm_userspace_memory_region *mem,
                                enum kvm_mr_change change)
 {
-       /*
-        * Only private memory slots need to be mapped here since
-        * KVM_SET_MEMORY_REGION ioctl is no longer supported.
-        */
-       if ((memslot->id >= KVM_USER_MEM_SLOTS) && (change == KVM_MR_CREATE)) {
-               unsigned long userspace_addr;
-
-               /*
-                * MAP_SHARED to prevent internal slot pages from being moved
-                * by fork()/COW.
-                */
-               userspace_addr = vm_mmap(NULL, 0, memslot->npages * PAGE_SIZE,
-                                        PROT_READ | PROT_WRITE,
-                                        MAP_SHARED | MAP_ANONYMOUS, 0);
-
-               if (IS_ERR((void *)userspace_addr))
-                       return PTR_ERR((void *)userspace_addr);
-
-               memslot->userspace_addr = userspace_addr;
-       }
-
        return 0;
 }
 
@@ -7711,17 +7719,6 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
 {
        int nr_mmu_pages = 0;
 
-       if (change == KVM_MR_DELETE && old->id >= KVM_USER_MEM_SLOTS) {
-               int ret;
-
-               ret = vm_munmap(old->userspace_addr,
-                               old->npages * PAGE_SIZE);
-               if (ret < 0)
-                       printk(KERN_WARNING
-                              "kvm_vm_ioctl_set_memory_region: "
-                              "failed to munmap memory\n");
-       }
-
        if (!kvm->arch.n_requested_mmu_pages)
                nr_mmu_pages = kvm_mmu_calculate_mmu_pages(kvm);
 
@@ -7770,19 +7767,36 @@ void kvm_arch_flush_shadow_memslot(struct kvm *kvm,
        kvm_mmu_invalidate_zap_all_pages(kvm);
 }
 
+static inline bool kvm_vcpu_has_events(struct kvm_vcpu *vcpu)
+{
+       if (!list_empty_careful(&vcpu->async_pf.done))
+               return true;
+
+       if (kvm_apic_has_events(vcpu))
+               return true;
+
+       if (vcpu->arch.pv.pv_unhalted)
+               return true;
+
+       if (atomic_read(&vcpu->arch.nmi_queued))
+               return true;
+
+       if (test_bit(KVM_REQ_SMI, &vcpu->requests))
+               return true;
+
+       if (kvm_arch_interrupt_allowed(vcpu) &&
+           kvm_cpu_has_interrupt(vcpu))
+               return true;
+
+       return false;
+}
+
 int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
 {
        if (is_guest_mode(vcpu) && kvm_x86_ops->check_nested_events)
                kvm_x86_ops->check_nested_events(vcpu, false);
 
-       return (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE &&
-               !vcpu->arch.apf.halted)
-               || !list_empty_careful(&vcpu->async_pf.done)
-               || kvm_apic_has_events(vcpu)
-               || vcpu->arch.pv.pv_unhalted
-               || atomic_read(&vcpu->arch.nmi_queued) ||
-               (kvm_arch_interrupt_allowed(vcpu) &&
-                kvm_cpu_has_interrupt(vcpu));
+       return kvm_vcpu_running(vcpu) || kvm_vcpu_has_events(vcpu);
 }
 
 int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
index 161804de124ac4b224e1bd328905fc99c959f73a..a0d09f6c65337fc381353783639f45251bf28d78 100644 (file)
@@ -1015,7 +1015,7 @@ static struct clock_event_device lguest_clockevent = {
  * This is the Guest timer interrupt handler (hardware interrupt 0).  We just
  * call the clockevent infrastructure and it does whatever needs doing.
  */
-static void lguest_time_irq(unsigned int irq, struct irq_desc *desc)
+static void lguest_time_irq(struct irq_desc *desc)
 {
        unsigned long flags;
 
index 30564e2752d361870e91a4e25a5afbb3d029b7d6..df48430c279b8688996b9f0074c08b1ce139af06 100644 (file)
@@ -1132,7 +1132,7 @@ void mark_rodata_ro(void)
         * has been zapped already via cleanup_highmem().
         */
        all_end = roundup((unsigned long)_brk_end, PMD_SIZE);
-       set_memory_nx(rodata_start, (all_end - rodata_start) >> PAGE_SHIFT);
+       set_memory_nx(text_end, (all_end - text_end) >> PAGE_SHIFT);
 
        rodata_test();
 
index 66338a60aa6ef961c6017731b6fd6d9d169736e1..c2aea63bee2085fdb08c9d4ea8f3accaf4ae2e5e 100644 (file)
@@ -192,10 +192,11 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
 
        node_set(node, numa_nodes_parsed);
 
-       pr_info("SRAT: Node %u PXM %u [mem %#010Lx-%#010Lx]%s\n",
+       pr_info("SRAT: Node %u PXM %u [mem %#010Lx-%#010Lx]%s%s\n",
                node, pxm,
                (unsigned long long) start, (unsigned long long) end - 1,
-               hotpluggable ? " hotplug" : "");
+               hotpluggable ? " hotplug" : "",
+               ma->flags & ACPI_SRAT_MEM_NON_VOLATILE ? " non-volatile" : "");
 
        /* Mark hotplug range in memblock. */
        if (hotpluggable && memblock_mark_hotplug(start, ma->length))
index 09d3afc0a181c1ac44ca654f9fde35796dbe3843..dc78a4a9a46663f10600afd013d9230fe5fe222b 100644 (file)
@@ -166,6 +166,7 @@ void pcibios_fixup_bus(struct pci_bus *b)
 {
        struct pci_dev *dev;
 
+       pci_read_bridge_bases(b);
        list_for_each_entry(dev, &b->devices, bus_list)
                pcibios_fixup_device_resources(dev);
 }
index 1db84c0758b732b3465fcc896ef98862dabe0f16..6a28ded74211145a74bfe677f9619f2d2fb676ae 100644 (file)
@@ -704,6 +704,70 @@ out:
        return ret;
 }
 
+/*
+ * Iterate the EFI memory map in reverse order because the regions
+ * will be mapped top-down. The end result is the same as if we had
+ * mapped things forward, but doesn't require us to change the
+ * existing implementation of efi_map_region().
+ */
+static inline void *efi_map_next_entry_reverse(void *entry)
+{
+       /* Initial call */
+       if (!entry)
+               return memmap.map_end - memmap.desc_size;
+
+       entry -= memmap.desc_size;
+       if (entry < memmap.map)
+               return NULL;
+
+       return entry;
+}
+
+/*
+ * efi_map_next_entry - Return the next EFI memory map descriptor
+ * @entry: Previous EFI memory map descriptor
+ *
+ * This is a helper function to iterate over the EFI memory map, which
+ * we do in different orders depending on the current configuration.
+ *
+ * To begin traversing the memory map @entry must be %NULL.
+ *
+ * Returns %NULL when we reach the end of the memory map.
+ */
+static void *efi_map_next_entry(void *entry)
+{
+       if (!efi_enabled(EFI_OLD_MEMMAP) && efi_enabled(EFI_64BIT)) {
+               /*
+                * Starting in UEFI v2.5 the EFI_PROPERTIES_TABLE
+                * config table feature requires us to map all entries
+                * in the same order as they appear in the EFI memory
+                * map. That is to say, entry N must have a lower
+                * virtual address than entry N+1. This is because the
+                * firmware toolchain leaves relative references in
+                * the code/data sections, which are split and become
+                * separate EFI memory regions. Mapping things
+                * out-of-order leads to the firmware accessing
+                * unmapped addresses.
+                *
+                * Since we need to map things this way whether or not
+                * the kernel actually makes use of
+                * EFI_PROPERTIES_TABLE, let's just switch to this
+                * scheme by default for 64-bit.
+                */
+               return efi_map_next_entry_reverse(entry);
+       }
+
+       /* Initial call */
+       if (!entry)
+               return memmap.map;
+
+       entry += memmap.desc_size;
+       if (entry >= memmap.map_end)
+               return NULL;
+
+       return entry;
+}
+
 /*
  * Map the efi memory ranges of the runtime services and update new_mmap with
  * virtual addresses.
@@ -714,7 +778,8 @@ static void * __init efi_map_regions(int *count, int *pg_shift)
        unsigned long left = 0;
        efi_memory_desc_t *md;
 
-       for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
+       p = NULL;
+       while ((p = efi_map_next_entry(p))) {
                md = p;
                if (!(md->attribute & EFI_MEMORY_RUNTIME)) {
 #ifdef CONFIG_X86_64
index 9701a4fd7bf2ea83d640ddeefebd5e4d5de27598..836a1eb5df436bdad88fe3b4ae59b512f9573b19 100644 (file)
 #include <skas.h>
 #include <sysdep/tls.h>
 
-extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
+static inline int modify_ldt (int func, void *ptr, unsigned long bytecount)
+{
+       return syscall(__NR_modify_ldt, func, ptr, bytecount);
+}
 
 static long write_ldt_entry(struct mm_id *mm_idp, int func,
                     struct user_desc *desc, void **addr, int done)
index 30d12afe52ed173b2a81720cd5c89c24e667de2a..993b7a71386d53f79befa7a302ede2fdcbed6bd4 100644 (file)
 #include <linux/memblock.h>
 #include <linux/edd.h>
 
+#ifdef CONFIG_KEXEC_CORE
+#include <linux/kexec.h>
+#endif
+
 #include <xen/xen.h>
 #include <xen/events.h>
 #include <xen/interface/xen.h>
@@ -1077,6 +1081,7 @@ static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high)
                /* Fast syscall setup is all done in hypercalls, so
                   these are all ignored.  Stub them out here to stop
                   Xen console noise. */
+               break;
 
        default:
                if (!pmu_msr_write(msr, low, high, &ret))
@@ -1807,6 +1812,21 @@ static struct notifier_block xen_hvm_cpu_notifier = {
        .notifier_call  = xen_hvm_cpu_notify,
 };
 
+#ifdef CONFIG_KEXEC_CORE
+static void xen_hvm_shutdown(void)
+{
+       native_machine_shutdown();
+       if (kexec_in_progress)
+               xen_reboot(SHUTDOWN_soft_reset);
+}
+
+static void xen_hvm_crash_shutdown(struct pt_regs *regs)
+{
+       native_machine_crash_shutdown(regs);
+       xen_reboot(SHUTDOWN_soft_reset);
+}
+#endif
+
 static void __init xen_hvm_guest_init(void)
 {
        if (xen_pv_domain())
@@ -1826,6 +1846,10 @@ static void __init xen_hvm_guest_init(void)
        x86_init.irqs.intr_init = xen_init_IRQ;
        xen_hvm_init_time_ops();
        xen_hvm_init_mmu_ops();
+#ifdef CONFIG_KEXEC_CORE
+       machine_ops.shutdown = xen_hvm_shutdown;
+       machine_ops.crash_shutdown = xen_hvm_crash_shutdown;
+#endif
 }
 #endif
 
index bfc08b13044b181c5948e5a2f22c205e900e0b47..660b3cfef23485f149e1a9b0b88f0b12666dbefb 100644 (file)
@@ -112,6 +112,15 @@ static unsigned long *p2m_identity;
 static pte_t *p2m_missing_pte;
 static pte_t *p2m_identity_pte;
 
+/*
+ * Hint at last populated PFN.
+ *
+ * Used to set HYPERVISOR_shared_info->arch.max_pfn so the toolstack
+ * can avoid scanning the whole P2M (which may be sized to account for
+ * hotplugged memory).
+ */
+static unsigned long xen_p2m_last_pfn;
+
 static inline unsigned p2m_top_index(unsigned long pfn)
 {
        BUG_ON(pfn >= MAX_P2M_PFN);
@@ -270,7 +279,7 @@ void xen_setup_mfn_list_list(void)
        else
                HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
                        virt_to_mfn(p2m_top_mfn);
-       HYPERVISOR_shared_info->arch.max_pfn = xen_max_p2m_pfn;
+       HYPERVISOR_shared_info->arch.max_pfn = xen_p2m_last_pfn;
        HYPERVISOR_shared_info->arch.p2m_generation = 0;
        HYPERVISOR_shared_info->arch.p2m_vaddr = (unsigned long)xen_p2m_addr;
        HYPERVISOR_shared_info->arch.p2m_cr3 =
@@ -406,6 +415,8 @@ void __init xen_vmalloc_p2m_tree(void)
        static struct vm_struct vm;
        unsigned long p2m_limit;
 
+       xen_p2m_last_pfn = xen_max_p2m_pfn;
+
        p2m_limit = (phys_addr_t)P2M_LIMIT * 1024 * 1024 * 1024 / PAGE_SIZE;
        vm.flags = VM_ALLOC;
        vm.size = ALIGN(sizeof(unsigned long) * max(xen_max_p2m_pfn, p2m_limit),
@@ -608,6 +619,12 @@ static bool alloc_p2m(unsigned long pfn)
                        free_p2m_page(p2m);
        }
 
+       /* Expanded the p2m? */
+       if (pfn > xen_p2m_last_pfn) {
+               xen_p2m_last_pfn = pfn;
+               HYPERVISOR_shared_info->arch.max_pfn = xen_p2m_last_pfn;
+       }
+
        return true;
 }
 
index f5ef6746d47a0ee36f6b0a11edd0c49cbcf3590a..1c30e4ab1022bda71ff80d841509605ae07034cc 100644 (file)
@@ -548,7 +548,7 @@ static unsigned long __init xen_get_max_pages(void)
 {
        unsigned long max_pages, limit;
        domid_t domid = DOMID_SELF;
-       int ret;
+       long ret;
 
        limit = xen_get_pages_limit();
        max_pages = limit;
@@ -798,7 +798,7 @@ char * __init xen_memory_setup(void)
                xen_ignore_unusable();
 
        /* Make sure the Xen-supplied memory map is well-ordered. */
-       sanitize_e820_map(xen_e820_map, xen_e820_map_entries,
+       sanitize_e820_map(xen_e820_map, ARRAY_SIZE(xen_e820_map),
                          &xen_e820_map_entries);
 
        max_pages = xen_get_max_pages();
index 63c223dff5f1eebed92297d2cd641535a3aeceb9..b56855a1382a374f8c52632b9aa243a1112a1a06 100644 (file)
@@ -28,4 +28,5 @@ generic-y += statfs.h
 generic-y += termios.h
 generic-y += topology.h
 generic-y += trace_clock.h
+generic-y += word-at-a-time.h
 generic-y += xor.h
index d27b4dcf221f8904e34198474d396c77b1034bb6..b848cc3dc913d8de7dc5181fc140a9f83215e6cf 100644 (file)
@@ -210,6 +210,10 @@ subsys_initcall(pcibios_init);
 
 void pcibios_fixup_bus(struct pci_bus *bus)
 {
+       if (bus->parent) {
+               /* This is a subordinate bridge */
+               pci_read_bridge_bases(bus);
+       }
 }
 
 void pcibios_set_master(struct pci_dev *dev)
index 4aecca79374adefb7d9496957788f9f376aa095f..14b8faf8b09d48937985713e10ed25745aad2dc2 100644 (file)
@@ -140,6 +140,11 @@ int bio_integrity_add_page(struct bio *bio, struct page *page,
 
        iv = bip->bip_vec + bip->bip_vcnt;
 
+       if (bip->bip_vcnt &&
+           bvec_gap_to_prev(bdev_get_queue(bio->bi_bdev),
+                            &bip->bip_vec[bip->bip_vcnt - 1], offset))
+               return 0;
+
        iv->bv_page = page;
        iv->bv_len = len;
        iv->bv_offset = offset;
index ac8370cb25157d2ed1cd215f8b95edde0735e3de..55512dd626336eae49b758def08d601bc3515b74 100644 (file)
@@ -370,6 +370,9 @@ static void blkg_destroy_all(struct request_queue *q)
                blkg_destroy(blkg);
                spin_unlock(&blkcg->lock);
        }
+
+       q->root_blkg = NULL;
+       q->root_rl.blkg = NULL;
 }
 
 /*
index 2eb722d48773cb8a8de49d58b934eed830755da7..18e92a6645e24741b786bc35f14b9d06f1355569 100644 (file)
@@ -576,7 +576,7 @@ void blk_cleanup_queue(struct request_queue *q)
                q->queue_lock = &q->__queue_lock;
        spin_unlock_irq(lock);
 
-       bdi_destroy(&q->backing_dev_info);
+       bdi_unregister(&q->backing_dev_info);
 
        /* @q is and will stay empty, shutdown and put */
        blk_put_queue(q);
index f548b64be09242a77f7db6ac7cedd5f68ee397b7..75f29cf701889a5711cad9e63f041bd98c74022f 100644 (file)
@@ -204,6 +204,9 @@ bool blk_integrity_merge_rq(struct request_queue *q, struct request *req,
            q->limits.max_integrity_segments)
                return false;
 
+       if (integrity_req_gap_back_merge(req, next->bio))
+               return false;
+
        return true;
 }
 EXPORT_SYMBOL(blk_integrity_merge_rq);
index bd40292e5009675ef17d6914b67010834cf1beb6..9ebf65379556a0f5730b3934acd2fa78e232e816 100644 (file)
@@ -26,13 +26,6 @@ static void bio_batch_end_io(struct bio *bio)
        bio_put(bio);
 }
 
-/*
- * Ensure that max discard sectors doesn't overflow bi_size and hopefully
- * it is of the proper granularity as long as the granularity is a power
- * of two.
- */
-#define MAX_BIO_SECTORS ((1U << 31) >> 9)
-
 /**
  * blkdev_issue_discard - queue a discard
  * @bdev:      blockdev to issue discard for
@@ -50,6 +43,8 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
        DECLARE_COMPLETION_ONSTACK(wait);
        struct request_queue *q = bdev_get_queue(bdev);
        int type = REQ_WRITE | REQ_DISCARD;
+       unsigned int granularity;
+       int alignment;
        struct bio_batch bb;
        struct bio *bio;
        int ret = 0;
@@ -61,6 +56,10 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
        if (!blk_queue_discard(q))
                return -EOPNOTSUPP;
 
+       /* Zero-sector (unknown) and one-sector granularities are the same.  */
+       granularity = max(q->limits.discard_granularity >> 9, 1U);
+       alignment = (bdev_discard_alignment(bdev) >> 9) % granularity;
+
        if (flags & BLKDEV_DISCARD_SECURE) {
                if (!blk_queue_secdiscard(q))
                        return -EOPNOTSUPP;
@@ -74,7 +73,7 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
        blk_start_plug(&plug);
        while (nr_sects) {
                unsigned int req_sects;
-               sector_t end_sect;
+               sector_t end_sect, tmp;
 
                bio = bio_alloc(gfp_mask, 1);
                if (!bio) {
@@ -82,8 +81,22 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
                        break;
                }
 
-               req_sects = min_t(sector_t, nr_sects, MAX_BIO_SECTORS);
+               /* Make sure bi_size doesn't overflow */
+               req_sects = min_t(sector_t, nr_sects, UINT_MAX >> 9);
+
+               /*
+                * If splitting a request, and the next starting sector would be
+                * misaligned, stop the discard at the previous aligned sector.
+                */
                end_sect = sector + req_sects;
+               tmp = end_sect;
+               if (req_sects < nr_sects &&
+                   sector_div(tmp, granularity) != alignment) {
+                       end_sect = end_sect - alignment;
+                       sector_div(end_sect, granularity);
+                       end_sect = end_sect * granularity + alignment;
+                       req_sects = end_sect - sector;
+               }
 
                bio->bi_iter.bi_sector = sector;
                bio->bi_end_io = bio_batch_end_io;
index 233841644c9d3ab31c6b388db5fd74cb4976c270..f565e11f465aa145120973bce58ef7ecc192f349 100644 (file)
@@ -9,6 +9,24 @@
 
 #include "blk.h"
 
+static bool iovec_gap_to_prv(struct request_queue *q,
+                            struct iovec *prv, struct iovec *cur)
+{
+       unsigned long prev_end;
+
+       if (!queue_virt_boundary(q))
+               return false;
+
+       if (prv->iov_base == NULL && prv->iov_len == 0)
+               /* prv is not set - don't check */
+               return false;
+
+       prev_end = (unsigned long)(prv->iov_base + prv->iov_len);
+
+       return (((unsigned long)cur->iov_base & queue_virt_boundary(q)) ||
+               prev_end & queue_virt_boundary(q));
+}
+
 int blk_rq_append_bio(struct request_queue *q, struct request *rq,
                      struct bio *bio)
 {
@@ -67,7 +85,7 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq,
        struct bio *bio;
        int unaligned = 0;
        struct iov_iter i;
-       struct iovec iov;
+       struct iovec iov, prv = {.iov_base = NULL, .iov_len = 0};
 
        if (!iter || !iter->count)
                return -EINVAL;
@@ -81,8 +99,12 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq,
                /*
                 * Keep going so we check length of all segments
                 */
-               if (uaddr & queue_dma_alignment(q))
+               if ((uaddr & queue_dma_alignment(q)) ||
+                   iovec_gap_to_prv(q, &prv, &iov))
                        unaligned = 1;
+
+               prv.iov_base = iov.iov_base;
+               prv.iov_len = iov.iov_len;
        }
 
        if (unaligned || (q->dma_pad_mask & iter->count) || map_data)
index d088cffb810508a5e55f7543bc134537329d00ec..c4e9c37f3e38122e5125502d62ab1ddd2e887408 100644 (file)
@@ -66,36 +66,33 @@ static struct bio *blk_bio_segment_split(struct request_queue *q,
                                         struct bio *bio,
                                         struct bio_set *bs)
 {
-       struct bio *split;
-       struct bio_vec bv, bvprv;
+       struct bio_vec bv, bvprv, *bvprvp = NULL;
        struct bvec_iter iter;
        unsigned seg_size = 0, nsegs = 0, sectors = 0;
-       int prev = 0;
 
        bio_for_each_segment(bv, bio, iter) {
-               sectors += bv.bv_len >> 9;
-
-               if (sectors > queue_max_sectors(q))
+               if (sectors + (bv.bv_len >> 9) > queue_max_sectors(q))
                        goto split;
 
                /*
                 * If the queue doesn't support SG gaps and adding this
                 * offset would create a gap, disallow it.
                 */
-               if (prev && bvec_gap_to_prev(q, &bvprv, bv.bv_offset))
+               if (bvprvp && bvec_gap_to_prev(q, bvprvp, bv.bv_offset))
                        goto split;
 
-               if (prev && blk_queue_cluster(q)) {
+               if (bvprvp && blk_queue_cluster(q)) {
                        if (seg_size + bv.bv_len > queue_max_segment_size(q))
                                goto new_segment;
-                       if (!BIOVEC_PHYS_MERGEABLE(&bvprv, &bv))
+                       if (!BIOVEC_PHYS_MERGEABLE(bvprvp, &bv))
                                goto new_segment;
-                       if (!BIOVEC_SEG_BOUNDARY(q, &bvprv, &bv))
+                       if (!BIOVEC_SEG_BOUNDARY(q, bvprvp, &bv))
                                goto new_segment;
 
                        seg_size += bv.bv_len;
                        bvprv = bv;
-                       prev = 1;
+                       bvprvp = &bv;
+                       sectors += bv.bv_len >> 9;
                        continue;
                }
 new_segment:
@@ -104,23 +101,14 @@ new_segment:
 
                nsegs++;
                bvprv = bv;
-               prev = 1;
+               bvprvp = &bv;
                seg_size = bv.bv_len;
+               sectors += bv.bv_len >> 9;
        }
 
        return NULL;
 split:
-       split = bio_clone_bioset(bio, GFP_NOIO, bs);
-
-       split->bi_iter.bi_size -= iter.bi_size;
-       bio->bi_iter = iter;
-
-       if (bio_integrity(bio)) {
-               bio_integrity_advance(bio, split->bi_iter.bi_size);
-               bio_integrity_trim(split, 0, bio_sectors(split));
-       }
-
-       return split;
+       return bio_split(bio, sectors, GFP_NOIO, bs);
 }
 
 void blk_queue_split(struct request_queue *q, struct bio **bio,
@@ -439,6 +427,11 @@ no_merge:
 int ll_back_merge_fn(struct request_queue *q, struct request *req,
                     struct bio *bio)
 {
+       if (req_gap_back_merge(req, bio))
+               return 0;
+       if (blk_integrity_rq(req) &&
+           integrity_req_gap_back_merge(req, bio))
+               return 0;
        if (blk_rq_sectors(req) + bio_sectors(bio) >
            blk_rq_get_max_sectors(req)) {
                req->cmd_flags |= REQ_NOMERGE;
@@ -457,6 +450,12 @@ int ll_back_merge_fn(struct request_queue *q, struct request *req,
 int ll_front_merge_fn(struct request_queue *q, struct request *req,
                      struct bio *bio)
 {
+
+       if (req_gap_front_merge(req, bio))
+               return 0;
+       if (blk_integrity_rq(req) &&
+           integrity_req_gap_front_merge(req, bio))
+               return 0;
        if (blk_rq_sectors(req) + bio_sectors(bio) >
            blk_rq_get_max_sectors(req)) {
                req->cmd_flags |= REQ_NOMERGE;
@@ -483,14 +482,6 @@ static bool req_no_special_merge(struct request *req)
        return !q->mq_ops && req->special;
 }
 
-static int req_gap_to_prev(struct request *req, struct bio *next)
-{
-       struct bio *prev = req->biotail;
-
-       return bvec_gap_to_prev(req->q, &prev->bi_io_vec[prev->bi_vcnt - 1],
-                       next->bi_io_vec[0].bv_offset);
-}
-
 static int ll_merge_requests_fn(struct request_queue *q, struct request *req,
                                struct request *next)
 {
@@ -505,7 +496,7 @@ static int ll_merge_requests_fn(struct request_queue *q, struct request *req,
        if (req_no_special_merge(req) || req_no_special_merge(next))
                return 0;
 
-       if (req_gap_to_prev(req, next->bio))
+       if (req_gap_back_merge(req, next->bio))
                return 0;
 
        /*
@@ -713,10 +704,6 @@ bool blk_rq_merge_ok(struct request *rq, struct bio *bio)
            !blk_write_same_mergeable(rq->bio, bio))
                return false;
 
-       /* Only check gaps if the bio carries data */
-       if (bio_has_data(bio) && req_gap_to_prev(rq, bio))
-               return false;
-
        return true;
 }
 
index 1e28ddb656b891b92d7c135fa65914939b1451aa..8764c241e5bb44858e753b75f6c102c06a927171 100644 (file)
@@ -31,7 +31,8 @@ static int get_first_sibling(unsigned int cpu)
        return cpu;
 }
 
-int blk_mq_update_queue_map(unsigned int *map, unsigned int nr_queues)
+int blk_mq_update_queue_map(unsigned int *map, unsigned int nr_queues,
+                           const struct cpumask *online_mask)
 {
        unsigned int i, nr_cpus, nr_uniq_cpus, queue, first_sibling;
        cpumask_var_t cpus;
@@ -41,7 +42,7 @@ int blk_mq_update_queue_map(unsigned int *map, unsigned int nr_queues)
 
        cpumask_clear(cpus);
        nr_cpus = nr_uniq_cpus = 0;
-       for_each_online_cpu(i) {
+       for_each_cpu(i, online_mask) {
                nr_cpus++;
                first_sibling = get_first_sibling(i);
                if (!cpumask_test_cpu(first_sibling, cpus))
@@ -51,7 +52,7 @@ int blk_mq_update_queue_map(unsigned int *map, unsigned int nr_queues)
 
        queue = 0;
        for_each_possible_cpu(i) {
-               if (!cpu_online(i)) {
+               if (!cpumask_test_cpu(i, online_mask)) {
                        map[i] = 0;
                        continue;
                }
@@ -95,7 +96,7 @@ unsigned int *blk_mq_make_queue_map(struct blk_mq_tag_set *set)
        if (!map)
                return NULL;
 
-       if (!blk_mq_update_queue_map(map, set->nr_hw_queues))
+       if (!blk_mq_update_queue_map(map, set->nr_hw_queues, cpu_online_mask))
                return map;
 
        kfree(map);
index 279c5d674edf3cb38627feb360eb745194eecd4e..788fffd9b4098e35a953ed8cc182a9633f9cc421 100644 (file)
@@ -229,8 +229,6 @@ static ssize_t blk_mq_hw_sysfs_cpus_show(struct blk_mq_hw_ctx *hctx, char *page)
        unsigned int i, first = 1;
        ssize_t ret = 0;
 
-       blk_mq_disable_hotplug();
-
        for_each_cpu(i, hctx->cpumask) {
                if (first)
                        ret += sprintf(ret + page, "%u", i);
@@ -240,8 +238,6 @@ static ssize_t blk_mq_hw_sysfs_cpus_show(struct blk_mq_hw_ctx *hctx, char *page)
                first = 0;
        }
 
-       blk_mq_enable_hotplug();
-
        ret += sprintf(ret + page, "\n");
        return ret;
 }
@@ -343,7 +339,7 @@ static void blk_mq_unregister_hctx(struct blk_mq_hw_ctx *hctx)
        struct blk_mq_ctx *ctx;
        int i;
 
-       if (!hctx->nr_ctx || !(hctx->flags & BLK_MQ_F_SYSFS_UP))
+       if (!hctx->nr_ctx)
                return;
 
        hctx_for_each_ctx(hctx, ctx, i)
@@ -358,7 +354,7 @@ static int blk_mq_register_hctx(struct blk_mq_hw_ctx *hctx)
        struct blk_mq_ctx *ctx;
        int i, ret;
 
-       if (!hctx->nr_ctx || !(hctx->flags & BLK_MQ_F_SYSFS_UP))
+       if (!hctx->nr_ctx)
                return 0;
 
        ret = kobject_add(&hctx->kobj, &q->mq_kobj, "%u", hctx->queue_num);
@@ -381,6 +377,8 @@ void blk_mq_unregister_disk(struct gendisk *disk)
        struct blk_mq_ctx *ctx;
        int i, j;
 
+       blk_mq_disable_hotplug();
+
        queue_for_each_hw_ctx(q, hctx, i) {
                blk_mq_unregister_hctx(hctx);
 
@@ -395,6 +393,9 @@ void blk_mq_unregister_disk(struct gendisk *disk)
        kobject_put(&q->mq_kobj);
 
        kobject_put(&disk_to_dev(disk)->kobj);
+
+       q->mq_sysfs_init_done = false;
+       blk_mq_enable_hotplug();
 }
 
 static void blk_mq_sysfs_init(struct request_queue *q)
@@ -425,27 +426,30 @@ int blk_mq_register_disk(struct gendisk *disk)
        struct blk_mq_hw_ctx *hctx;
        int ret, i;
 
+       blk_mq_disable_hotplug();
+
        blk_mq_sysfs_init(q);
 
        ret = kobject_add(&q->mq_kobj, kobject_get(&dev->kobj), "%s", "mq");
        if (ret < 0)
-               return ret;
+               goto out;
 
        kobject_uevent(&q->mq_kobj, KOBJ_ADD);
 
        queue_for_each_hw_ctx(q, hctx, i) {
-               hctx->flags |= BLK_MQ_F_SYSFS_UP;
                ret = blk_mq_register_hctx(hctx);
                if (ret)
                        break;
        }
 
-       if (ret) {
+       if (ret)
                blk_mq_unregister_disk(disk);
-               return ret;
-       }
+       else
+               q->mq_sysfs_init_done = true;
+out:
+       blk_mq_enable_hotplug();
 
-       return 0;
+       return ret;
 }
 EXPORT_SYMBOL_GPL(blk_mq_register_disk);
 
@@ -454,6 +458,9 @@ void blk_mq_sysfs_unregister(struct request_queue *q)
        struct blk_mq_hw_ctx *hctx;
        int i;
 
+       if (!q->mq_sysfs_init_done)
+               return;
+
        queue_for_each_hw_ctx(q, hctx, i)
                blk_mq_unregister_hctx(hctx);
 }
@@ -463,6 +470,9 @@ int blk_mq_sysfs_register(struct request_queue *q)
        struct blk_mq_hw_ctx *hctx;
        int i, ret = 0;
 
+       if (!q->mq_sysfs_init_done)
+               return ret;
+
        queue_for_each_hw_ctx(q, hctx, i) {
                ret = blk_mq_register_hctx(hctx);
                if (ret)
index 9115c6d59948addbc445a26ad0f9ccaf4237b137..ec2d11915142a8f9b7a49e839e41a2f54a55aa09 100644 (file)
@@ -471,17 +471,30 @@ void blk_mq_all_tag_busy_iter(struct blk_mq_tags *tags, busy_tag_iter_fn *fn,
 }
 EXPORT_SYMBOL(blk_mq_all_tag_busy_iter);
 
-void blk_mq_tag_busy_iter(struct blk_mq_hw_ctx *hctx, busy_iter_fn *fn,
+void blk_mq_queue_tag_busy_iter(struct request_queue *q, busy_iter_fn *fn,
                void *priv)
 {
-       struct blk_mq_tags *tags = hctx->tags;
+       struct blk_mq_hw_ctx *hctx;
+       int i;
+
+
+       queue_for_each_hw_ctx(q, hctx, i) {
+               struct blk_mq_tags *tags = hctx->tags;
+
+               /*
+                * If not software queues are currently mapped to this
+                * hardware queue, there's nothing to check
+                */
+               if (!blk_mq_hw_queue_mapped(hctx))
+                       continue;
+
+               if (tags->nr_reserved_tags)
+                       bt_for_each(hctx, &tags->breserved_tags, 0, fn, priv, true);
+               bt_for_each(hctx, &tags->bitmap_tags, tags->nr_reserved_tags, fn, priv,
+                     false);
+       }
 
-       if (tags->nr_reserved_tags)
-               bt_for_each(hctx, &tags->breserved_tags, 0, fn, priv, true);
-       bt_for_each(hctx, &tags->bitmap_tags, tags->nr_reserved_tags, fn, priv,
-                       false);
 }
-EXPORT_SYMBOL(blk_mq_tag_busy_iter);
 
 static unsigned int bt_unused_tags(struct blk_mq_bitmap_tags *bt)
 {
@@ -628,6 +641,7 @@ void blk_mq_free_tags(struct blk_mq_tags *tags)
 {
        bt_free(&tags->bitmap_tags);
        bt_free(&tags->breserved_tags);
+       free_cpumask_var(tags->cpumask);
        kfree(tags);
 }
 
index 9eb2cf4f01cb874706d64af87a01e94e0121f7e4..d468a79f2c4a2c11a00387816bcc03b64aea09d1 100644 (file)
@@ -58,6 +58,8 @@ extern ssize_t blk_mq_tag_sysfs_show(struct blk_mq_tags *tags, char *page);
 extern void blk_mq_tag_init_last_tag(struct blk_mq_tags *tags, unsigned int *last_tag);
 extern int blk_mq_tag_update_depth(struct blk_mq_tags *tags, unsigned int depth);
 extern void blk_mq_tag_wakeup_all(struct blk_mq_tags *tags, bool);
+void blk_mq_queue_tag_busy_iter(struct request_queue *q, busy_iter_fn *fn,
+               void *priv);
 
 enum {
        BLK_MQ_TAG_CACHE_MIN    = 1,
index f2d67b4047a04d7015c3c2af16871972c3b5a720..85f014327342efc775c31833a52f531b69a66329 100644 (file)
@@ -393,14 +393,16 @@ void __blk_mq_complete_request(struct request *rq)
  *     Ends all I/O on a request. It does not handle partial completions.
  *     The actual completion happens out-of-order, through a IPI handler.
  **/
-void blk_mq_complete_request(struct request *rq)
+void blk_mq_complete_request(struct request *rq, int error)
 {
        struct request_queue *q = rq->q;
 
        if (unlikely(blk_should_fake_timeout(q)))
                return;
-       if (!blk_mark_rq_complete(rq))
+       if (!blk_mark_rq_complete(rq)) {
+               rq->errors = error;
                __blk_mq_complete_request(rq);
+       }
 }
 EXPORT_SYMBOL(blk_mq_complete_request);
 
@@ -616,10 +618,8 @@ static void blk_mq_check_expired(struct blk_mq_hw_ctx *hctx,
                 * If a request wasn't started before the queue was
                 * marked dying, kill it here or it'll go unnoticed.
                 */
-               if (unlikely(blk_queue_dying(rq->q))) {
-                       rq->errors = -EIO;
-                       blk_mq_complete_request(rq);
-               }
+               if (unlikely(blk_queue_dying(rq->q)))
+                       blk_mq_complete_request(rq, -EIO);
                return;
        }
        if (rq->cmd_flags & REQ_NO_TIMEOUT)
@@ -641,24 +641,16 @@ static void blk_mq_rq_timer(unsigned long priv)
                .next           = 0,
                .next_set       = 0,
        };
-       struct blk_mq_hw_ctx *hctx;
        int i;
 
-       queue_for_each_hw_ctx(q, hctx, i) {
-               /*
-                * If not software queues are currently mapped to this
-                * hardware queue, there's nothing to check
-                */
-               if (!blk_mq_hw_queue_mapped(hctx))
-                       continue;
-
-               blk_mq_tag_busy_iter(hctx, blk_mq_check_expired, &data);
-       }
+       blk_mq_queue_tag_busy_iter(q, blk_mq_check_expired, &data);
 
        if (data.next_set) {
                data.next = blk_rq_timeout(round_jiffies_up(data.next));
                mod_timer(&q->timeout, data.next);
        } else {
+               struct blk_mq_hw_ctx *hctx;
+
                queue_for_each_hw_ctx(q, hctx, i) {
                        /* the hctx may be unmapped, so check it here */
                        if (blk_mq_hw_queue_mapped(hctx))
@@ -1789,13 +1781,19 @@ static void blk_mq_init_cpu_queues(struct request_queue *q,
        }
 }
 
-static void blk_mq_map_swqueue(struct request_queue *q)
+static void blk_mq_map_swqueue(struct request_queue *q,
+                              const struct cpumask *online_mask)
 {
        unsigned int i;
        struct blk_mq_hw_ctx *hctx;
        struct blk_mq_ctx *ctx;
        struct blk_mq_tag_set *set = q->tag_set;
 
+       /*
+        * Avoid others reading imcomplete hctx->cpumask through sysfs
+        */
+       mutex_lock(&q->sysfs_lock);
+
        queue_for_each_hw_ctx(q, hctx, i) {
                cpumask_clear(hctx->cpumask);
                hctx->nr_ctx = 0;
@@ -1806,16 +1804,17 @@ static void blk_mq_map_swqueue(struct request_queue *q)
         */
        queue_for_each_ctx(q, ctx, i) {
                /* If the cpu isn't online, the cpu is mapped to first hctx */
-               if (!cpu_online(i))
+               if (!cpumask_test_cpu(i, online_mask))
                        continue;
 
                hctx = q->mq_ops->map_queue(q, i);
                cpumask_set_cpu(i, hctx->cpumask);
-               cpumask_set_cpu(i, hctx->tags->cpumask);
                ctx->index_hw = hctx->nr_ctx;
                hctx->ctxs[hctx->nr_ctx++] = ctx;
        }
 
+       mutex_unlock(&q->sysfs_lock);
+
        queue_for_each_hw_ctx(q, hctx, i) {
                struct blk_mq_ctxmap *map = &hctx->ctx_map;
 
@@ -1851,6 +1850,14 @@ static void blk_mq_map_swqueue(struct request_queue *q)
                hctx->next_cpu = cpumask_first(hctx->cpumask);
                hctx->next_cpu_batch = BLK_MQ_CPU_WORK_BATCH;
        }
+
+       queue_for_each_ctx(q, ctx, i) {
+               if (!cpumask_test_cpu(i, online_mask))
+                       continue;
+
+               hctx = q->mq_ops->map_queue(q, i);
+               cpumask_set_cpu(i, hctx->tags->cpumask);
+       }
 }
 
 static void blk_mq_update_tag_set_depth(struct blk_mq_tag_set *set)
@@ -1918,6 +1925,9 @@ void blk_mq_release(struct request_queue *q)
                kfree(hctx);
        }
 
+       kfree(q->mq_map);
+       q->mq_map = NULL;
+
        kfree(q->queue_hw_ctx);
 
        /* ctx kobj stays in queue_ctx */
@@ -2027,13 +2037,15 @@ struct request_queue *blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
        if (blk_mq_init_hw_queues(q, set))
                goto err_hctxs;
 
+       get_online_cpus();
        mutex_lock(&all_q_mutex);
-       list_add_tail(&q->all_q_node, &all_q_list);
-       mutex_unlock(&all_q_mutex);
 
+       list_add_tail(&q->all_q_node, &all_q_list);
        blk_mq_add_queue_tag_set(set, q);
+       blk_mq_map_swqueue(q, cpu_online_mask);
 
-       blk_mq_map_swqueue(q);
+       mutex_unlock(&all_q_mutex);
+       put_online_cpus();
 
        return q;
 
@@ -2057,30 +2069,27 @@ void blk_mq_free_queue(struct request_queue *q)
 {
        struct blk_mq_tag_set   *set = q->tag_set;
 
+       mutex_lock(&all_q_mutex);
+       list_del_init(&q->all_q_node);
+       mutex_unlock(&all_q_mutex);
+
        blk_mq_del_queue_tag_set(q);
 
        blk_mq_exit_hw_queues(q, set, set->nr_hw_queues);
        blk_mq_free_hw_queues(q, set);
 
        percpu_ref_exit(&q->mq_usage_counter);
-
-       kfree(q->mq_map);
-
-       q->mq_map = NULL;
-
-       mutex_lock(&all_q_mutex);
-       list_del_init(&q->all_q_node);
-       mutex_unlock(&all_q_mutex);
 }
 
 /* Basically redo blk_mq_init_queue with queue frozen */
-static void blk_mq_queue_reinit(struct request_queue *q)
+static void blk_mq_queue_reinit(struct request_queue *q,
+                               const struct cpumask *online_mask)
 {
        WARN_ON_ONCE(!atomic_read(&q->mq_freeze_depth));
 
        blk_mq_sysfs_unregister(q);
 
-       blk_mq_update_queue_map(q->mq_map, q->nr_hw_queues);
+       blk_mq_update_queue_map(q->mq_map, q->nr_hw_queues, online_mask);
 
        /*
         * redo blk_mq_init_cpu_queues and blk_mq_init_hw_queues. FIXME: maybe
@@ -2088,7 +2097,7 @@ static void blk_mq_queue_reinit(struct request_queue *q)
         * involves free and re-allocate memory, worthy doing?)
         */
 
-       blk_mq_map_swqueue(q);
+       blk_mq_map_swqueue(q, online_mask);
 
        blk_mq_sysfs_register(q);
 }
@@ -2097,16 +2106,43 @@ static int blk_mq_queue_reinit_notify(struct notifier_block *nb,
                                      unsigned long action, void *hcpu)
 {
        struct request_queue *q;
+       int cpu = (unsigned long)hcpu;
+       /*
+        * New online cpumask which is going to be set in this hotplug event.
+        * Declare this cpumasks as global as cpu-hotplug operation is invoked
+        * one-by-one and dynamically allocating this could result in a failure.
+        */
+       static struct cpumask online_new;
 
        /*
-        * Before new mappings are established, hotadded cpu might already
-        * start handling requests. This doesn't break anything as we map
-        * offline CPUs to first hardware queue. We will re-init the queue
-        * below to get optimal settings.
+        * Before hotadded cpu starts handling requests, new mappings must
+        * be established.  Otherwise, these requests in hw queue might
+        * never be dispatched.
+        *
+        * For example, there is a single hw queue (hctx) and two CPU queues
+        * (ctx0 for CPU0, and ctx1 for CPU1).
+        *
+        * Now CPU1 is just onlined and a request is inserted into
+        * ctx1->rq_list and set bit0 in pending bitmap as ctx1->index_hw is
+        * still zero.
+        *
+        * And then while running hw queue, flush_busy_ctxs() finds bit0 is
+        * set in pending bitmap and tries to retrieve requests in
+        * hctx->ctxs[0]->rq_list.  But htx->ctxs[0] is a pointer to ctx0,
+        * so the request in ctx1->rq_list is ignored.
         */
-       if (action != CPU_DEAD && action != CPU_DEAD_FROZEN &&
-           action != CPU_ONLINE && action != CPU_ONLINE_FROZEN)
+       switch (action & ~CPU_TASKS_FROZEN) {
+       case CPU_DEAD:
+       case CPU_UP_CANCELED:
+               cpumask_copy(&online_new, cpu_online_mask);
+               break;
+       case CPU_UP_PREPARE:
+               cpumask_copy(&online_new, cpu_online_mask);
+               cpumask_set_cpu(cpu, &online_new);
+               break;
+       default:
                return NOTIFY_OK;
+       }
 
        mutex_lock(&all_q_mutex);
 
@@ -2130,7 +2166,7 @@ static int blk_mq_queue_reinit_notify(struct notifier_block *nb,
        }
 
        list_for_each_entry(q, &all_q_list, all_q_node)
-               blk_mq_queue_reinit(q);
+               blk_mq_queue_reinit(q, &online_new);
 
        list_for_each_entry(q, &all_q_list, all_q_node)
                blk_mq_unfreeze_queue(q);
@@ -2260,10 +2296,8 @@ void blk_mq_free_tag_set(struct blk_mq_tag_set *set)
        int i;
 
        for (i = 0; i < set->nr_hw_queues; i++) {
-               if (set->tags[i]) {
+               if (set->tags[i])
                        blk_mq_free_rq_map(set, set->tags[i], i);
-                       free_cpumask_var(set->tags[i]->cpumask);
-               }
        }
 
        kfree(set->tags);
index 6a48c4c0d8a2a6efb881ea29b772df3bba9d5540..f4fea79649105b4e134860b53294ef2dac90a95f 100644 (file)
@@ -51,7 +51,8 @@ void blk_mq_disable_hotplug(void);
  * CPU -> queue mappings
  */
 extern unsigned int *blk_mq_make_queue_map(struct blk_mq_tag_set *set);
-extern int blk_mq_update_queue_map(unsigned int *map, unsigned int nr_queues);
+extern int blk_mq_update_queue_map(unsigned int *map, unsigned int nr_queues,
+                                  const struct cpumask *online_mask);
 extern int blk_mq_hw_queue_to_node(unsigned int *map, unsigned int);
 
 /*
index 3e44a9da2a13579cacaee3d5e03bb3868f34d02a..07b42f5ad797b7b5e6367d5c70051d3b34fca55c 100644 (file)
@@ -540,6 +540,7 @@ static void blk_release_queue(struct kobject *kobj)
        struct request_queue *q =
                container_of(kobj, struct request_queue, kobj);
 
+       bdi_exit(&q->backing_dev_info);
        blkcg_exit_queue(q);
 
        if (q->elevator) {
index 0611aea1cfe9f0310c08043b3a281fee10835c9d..1cb5dd3a5da1e7bf834f229d2c8776bbcb65a3d4 100644 (file)
@@ -128,12 +128,14 @@ static void bounce_end_io(struct bio *bio, mempool_t *pool)
        struct bio *bio_orig = bio->bi_private;
        struct bio_vec *bvec, *org_vec;
        int i;
+       int start = bio_orig->bi_iter.bi_idx;
 
        /*
         * free up bounce indirect pages used
         */
        bio_for_each_segment_all(bvec, bio, i) {
-               org_vec = bio_orig->bi_io_vec + i;
+               org_vec = bio_orig->bi_io_vec + i + start;
+
                if (bvec->bv_page == org_vec->bv_page)
                        continue;
 
index b788f169cc9880d0d1ac2ce4930145d9862b306d..b4ffc5be1a93c1ff0bceb6b9a5cc3dc1b5101d97 100644 (file)
@@ -706,7 +706,7 @@ struct crypto_ablkcipher *crypto_alloc_ablkcipher(const char *alg_name,
 err:
                if (err != -EAGAIN)
                        break;
-               if (signal_pending(current)) {
+               if (fatal_signal_pending(current)) {
                        err = -EINTR;
                        break;
                }
index 8acb886032ae7a604fe0e965eb5d3ce07dd4845b..9c1dc8d6106a89a0f853271c1dfc49cd301ec983 100644 (file)
@@ -544,7 +544,8 @@ static int ahash_prepare_alg(struct ahash_alg *alg)
        struct crypto_alg *base = &alg->halg.base;
 
        if (alg->halg.digestsize > PAGE_SIZE / 8 ||
-           alg->halg.statesize > PAGE_SIZE / 8)
+           alg->halg.statesize > PAGE_SIZE / 8 ||
+           alg->halg.statesize == 0)
                return -EINVAL;
 
        base->cra_type = &crypto_ahash_type;
index d130b41dbaea244000c35328d7eba7b463158bc8..59bf491fe3d8606acc4016c53182182615d32a21 100644 (file)
@@ -345,7 +345,7 @@ static void crypto_wait_for_test(struct crypto_larval *larval)
                crypto_alg_tested(larval->alg.cra_driver_name, 0);
        }
 
-       err = wait_for_completion_interruptible(&larval->completion);
+       err = wait_for_completion_killable(&larval->completion);
        WARN_ON(err);
 
 out:
index afe4610afc4b952d585ede5ba9cbd732f5aa3750..bbc147cb5dec87affad82510412459c075056f86 100644 (file)
@@ -172,7 +172,7 @@ static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg)
        struct crypto_larval *larval = (void *)alg;
        long timeout;
 
-       timeout = wait_for_completion_interruptible_timeout(
+       timeout = wait_for_completion_killable_timeout(
                &larval->completion, 60 * HZ);
 
        alg = larval->adult;
@@ -445,7 +445,7 @@ struct crypto_tfm *crypto_alloc_base(const char *alg_name, u32 type, u32 mask)
 err:
                if (err != -EAGAIN)
                        break;
-               if (signal_pending(current)) {
+               if (fatal_signal_pending(current)) {
                        err = -EINTR;
                        break;
                }
@@ -562,7 +562,7 @@ void *crypto_alloc_tfm(const char *alg_name,
 err:
                if (err != -EAGAIN)
                        break;
-               if (signal_pending(current)) {
+               if (fatal_signal_pending(current)) {
                        err = -EINTR;
                        break;
                }
index 6d88dd15c98da8cada935c0dc937eb5c8db158cd..19709663241223968ee73f3d1847be9e253969f7 100644 (file)
@@ -332,10 +332,6 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
                srlen = cert->raw_serial_size;
                q = cert->raw_serial;
        }
-       if (srlen > 1 && *q == 0) {
-               srlen--;
-               q++;
-       }
 
        ret = -ENOMEM;
        desc = kmalloc(sulen + 2 + srlen * 2 + 1, GFP_KERNEL);
index d94d99ffe8b9b6cecf2c8348241ea17738e9b457..237f3795cfaaa1f988fadf5b07eefe3c44609091 100644 (file)
@@ -375,7 +375,7 @@ static struct crypto_alg *crypto_user_skcipher_alg(const char *name, u32 type,
                err = PTR_ERR(alg);
                if (err != -EAGAIN)
                        break;
-               if (signal_pending(current)) {
+               if (fatal_signal_pending(current)) {
                        err = -EINTR;
                        break;
                }
index 35c2de13697182ba22190ea6d0c05d46c6b905be..fa18753f5c344de0eba58d9c9c1296255f4178c7 100644 (file)
@@ -940,6 +940,7 @@ static int __test_skcipher(struct crypto_skcipher *tfm, int enc,
        char *xbuf[XBUFSIZE];
        char *xoutbuf[XBUFSIZE];
        int ret = -ENOMEM;
+       unsigned int ivsize = crypto_skcipher_ivsize(tfm);
 
        if (testmgr_alloc_buf(xbuf))
                goto out_nobuf;
@@ -975,7 +976,7 @@ static int __test_skcipher(struct crypto_skcipher *tfm, int enc,
                        continue;
 
                if (template[i].iv)
-                       memcpy(iv, template[i].iv, MAX_IVLEN);
+                       memcpy(iv, template[i].iv, ivsize);
                else
                        memset(iv, 0, MAX_IVLEN);
 
@@ -1051,7 +1052,7 @@ static int __test_skcipher(struct crypto_skcipher *tfm, int enc,
                        continue;
 
                if (template[i].iv)
-                       memcpy(iv, template[i].iv, MAX_IVLEN);
+                       memcpy(iv, template[i].iv, ivsize);
                else
                        memset(iv, 0, MAX_IVLEN);
 
index 09f37b51680871d8a34dc3a33563872652d4f0d6..4dde37c3d8fcba549ad1eb978bf23466321e9152 100644 (file)
@@ -61,6 +61,7 @@ ACPI_GLOBAL(struct acpi_table_header, acpi_gbl_original_dsdt_header);
 ACPI_INIT_GLOBAL(u32, acpi_gbl_dsdt_index, ACPI_INVALID_TABLE_INDEX);
 ACPI_INIT_GLOBAL(u32, acpi_gbl_facs_index, ACPI_INVALID_TABLE_INDEX);
 ACPI_INIT_GLOBAL(u32, acpi_gbl_xfacs_index, ACPI_INVALID_TABLE_INDEX);
+ACPI_INIT_GLOBAL(u32, acpi_gbl_fadt_index, ACPI_INVALID_TABLE_INDEX);
 
 #if (!ACPI_REDUCED_HARDWARE)
 ACPI_GLOBAL(struct acpi_table_facs *, acpi_gbl_FACS);
index f7731f260c318606e32455b7175a01ea157d8267..591ea95319e25ca7e5630970dd080ab1eab85e5e 100644 (file)
@@ -85,7 +85,7 @@ void acpi_tb_set_table_loaded_flag(u32 table_index, u8 is_loaded);
 /*
  * tbfadt - FADT parse/convert/validate
  */
-void acpi_tb_parse_fadt(u32 table_index);
+void acpi_tb_parse_fadt(void);
 
 void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length);
 
@@ -138,8 +138,6 @@ acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id *owner_id);
  */
 acpi_status acpi_tb_initialize_facs(void);
 
-u8 acpi_tb_tables_loaded(void);
-
 void
 acpi_tb_print_table_header(acpi_physical_address address,
                           struct acpi_table_header *header);
index faad911d46b5eb71c4ae93a5300cf460e63c8738..10ce48e16ebf43a334fdc2f13479572d9bca4bd1 100644 (file)
@@ -71,7 +71,7 @@ acpi_status acpi_enable(void)
 
        /* ACPI tables must be present */
 
-       if (!acpi_tb_tables_loaded()) {
+       if (acpi_gbl_fadt_index == ACPI_INVALID_TABLE_INDEX) {
                return_ACPI_STATUS(AE_NO_ACPI_TABLES);
        }
 
index 455a0700db392b1663a16c392d8da3bb544b72b6..a6454f4a6fb343b52cada9dc5394094768c6ea14 100644 (file)
@@ -298,7 +298,7 @@ acpi_tb_select_address(char *register_name, u32 address32, u64 address64)
  *
  * FUNCTION:    acpi_tb_parse_fadt
  *
- * PARAMETERS:  table_index         - Index for the FADT
+ * PARAMETERS:  None
  *
  * RETURN:      None
  *
@@ -307,7 +307,7 @@ acpi_tb_select_address(char *register_name, u32 address32, u64 address64)
  *
  ******************************************************************************/
 
-void acpi_tb_parse_fadt(u32 table_index)
+void acpi_tb_parse_fadt(void)
 {
        u32 length;
        struct acpi_table_header *table;
@@ -319,11 +319,11 @@ void acpi_tb_parse_fadt(u32 table_index)
         * Get a local copy of the FADT and convert it to a common format
         * Map entire FADT, assumed to be smaller than one page.
         */
-       length = acpi_gbl_root_table_list.tables[table_index].length;
+       length = acpi_gbl_root_table_list.tables[acpi_gbl_fadt_index].length;
 
        table =
-           acpi_os_map_memory(acpi_gbl_root_table_list.tables[table_index].
-                              address, length);
+           acpi_os_map_memory(acpi_gbl_root_table_list.
+                              tables[acpi_gbl_fadt_index].address, length);
        if (!table) {
                return;
        }
index 4337990127cc39930b50983d7e7eff05966fcfb6..d8ddef38c947f750a226cee1b69fa373c9e1bf8f 100644 (file)
@@ -97,29 +97,6 @@ acpi_status acpi_tb_initialize_facs(void)
 }
 #endif                         /* !ACPI_REDUCED_HARDWARE */
 
-/*******************************************************************************
- *
- * FUNCTION:    acpi_tb_tables_loaded
- *
- * PARAMETERS:  None
- *
- * RETURN:      TRUE if required ACPI tables are loaded
- *
- * DESCRIPTION: Determine if the minimum required ACPI tables are present
- *              (FADT, FACS, DSDT)
- *
- ******************************************************************************/
-
-u8 acpi_tb_tables_loaded(void)
-{
-
-       if (acpi_gbl_root_table_list.current_table_count >= 4) {
-               return (TRUE);
-       }
-
-       return (FALSE);
-}
-
 /*******************************************************************************
  *
  * FUNCTION:    acpi_tb_check_dsdt_header
@@ -392,7 +369,8 @@ acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
                    ACPI_COMPARE_NAME(&acpi_gbl_root_table_list.
                                      tables[table_index].signature,
                                      ACPI_SIG_FADT)) {
-                       acpi_tb_parse_fadt(table_index);
+                       acpi_gbl_fadt_index = table_index;
+                       acpi_tb_parse_fadt();
                }
 
 next_table:
index 46506e7687cd11b5e3a4918a170c7bdd1214fee9..a212cefae524f8d2daaa2b4161ee16c2fae90cf8 100644 (file)
@@ -315,14 +315,10 @@ static void acpi_bus_osc_support(void)
 
        capbuf[OSC_QUERY_DWORD] = OSC_QUERY_ENABLE;
        capbuf[OSC_SUPPORT_DWORD] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */
-#if defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR) ||\
-                       defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR_MODULE)
-       capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PAD_SUPPORT;
-#endif
-
-#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE)
-       capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PPC_OST_SUPPORT;
-#endif
+       if (IS_ENABLED(CONFIG_ACPI_PROCESSOR_AGGREGATOR))
+               capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PAD_SUPPORT;
+       if (IS_ENABLED(CONFIG_ACPI_PROCESSOR))
+               capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PPC_OST_SUPPORT;
 
        capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_HOTPLUG_OST_SUPPORT;
 
index 2614a839c60dab8aca4d2955368888ae5c0fefc3..42c66b64c12cefd8c1491e7b91af138b86ddf5af 100644 (file)
@@ -1044,8 +1044,10 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 *data)
                goto err_exit;
 
        mutex_lock(&ec->mutex);
+       result = -ENODATA;
        list_for_each_entry(handler, &ec->list, node) {
                if (value == handler->query_bit) {
+                       result = 0;
                        q->handler = acpi_ec_get_query_handler(handler);
                        ec_dbg_evt("Query(0x%02x) scheduled",
                                   q->handler->query_bit);
index 9dcf83682e367e889db67cd5ae44670878893459..33505c651f62792e136cedc73a8b022c10f2ba21 100644 (file)
@@ -33,13 +33,12 @@ static const struct acpi_device_id int340x_thermal_device_ids[] = {
 static int int340x_thermal_handler_attach(struct acpi_device *adev,
                                        const struct acpi_device_id *id)
 {
-#if defined(CONFIG_INT340X_THERMAL) || defined(CONFIG_INT340X_THERMAL_MODULE)
-       acpi_create_platform_device(adev);
-#elif defined(INTEL_SOC_DTS_THERMAL) || defined(INTEL_SOC_DTS_THERMAL_MODULE)
+       if (IS_ENABLED(CONFIG_INT340X_THERMAL))
+               acpi_create_platform_device(adev);
        /* Intel SoC DTS thermal driver needs INT3401 to set IRQ descriptor */
-       if (id->driver_data == INT3401_DEVICE)
+       else if (IS_ENABLED(CONFIG_INTEL_SOC_DTS_THERMAL) &&
+                id->driver_data == INT3401_DEVICE)
                acpi_create_platform_device(adev);
-#endif
        return 1;
 }
 
index 6da0f9beab19880ac71199b7cd99fd57b2fa6e21..c9336751e5e3708f96e9f972ab05fc5454970adb 100644 (file)
@@ -372,6 +372,7 @@ static int acpi_isa_register_gsi(struct pci_dev *dev)
 
        /* Interrupt Line values above 0xF are forbidden */
        if (dev->irq > 0 && (dev->irq <= 0xF) &&
+           acpi_isa_irq_available(dev->irq) &&
            (acpi_isa_irq_to_gsi(dev->irq, &dev_gsi) == 0)) {
                dev_warn(&dev->dev, "PCI INT %c: no GSI - using ISA IRQ %d\n",
                         pin_name(dev->pin), dev->irq);
index 3b4ea98e3ea069eca5f9e0094f520c31eee639b2..7c8408b946ca10160d41648f14f99a6716529903 100644 (file)
@@ -498,8 +498,7 @@ int __init acpi_irq_penalty_init(void)
                            PIRQ_PENALTY_PCI_POSSIBLE;
                }
        }
-       /* Add a penalty for the SCI */
-       acpi_irq_penalty[acpi_gbl_FADT.sci_interrupt] += PIRQ_PENALTY_PCI_USING;
+
        return 0;
 }
 
@@ -553,6 +552,13 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
                                irq = link->irq.possible[i];
                }
        }
+       if (acpi_irq_penalty[irq] >= PIRQ_PENALTY_ISA_ALWAYS) {
+               printk(KERN_ERR PREFIX "No IRQ available for %s [%s]. "
+                           "Try pci=noacpi or acpi=off\n",
+                           acpi_device_name(link->device),
+                           acpi_device_bid(link->device));
+               return -ENODEV;
+       }
 
        /* Attempt to enable the link device at this IRQ. */
        if (acpi_pci_link_set(link, irq)) {
@@ -821,6 +827,12 @@ void acpi_penalize_isa_irq(int irq, int active)
        }
 }
 
+bool acpi_isa_irq_available(int irq)
+{
+       return irq >= 0 && (irq >= ARRAY_SIZE(acpi_irq_penalty) ||
+                           acpi_irq_penalty[irq] < PIRQ_PENALTY_ISA_ALWAYS);
+}
+
 /*
  * Penalize IRQ used by ACPI SCI. If ACPI SCI pin attributes conflict with
  * PCI IRQ attributes, mark ACPI SCI as ISA_ALWAYS so it won't be use for
index a8da3a50e374f8bb1b69a90ac049287ba11069b1..0f5cb37636bcc16b4e1ba23a58b30be4bba82b8f 100644 (file)
@@ -1578,9 +1578,7 @@ he_stop(struct he_dev *he_dev)
 
        kfree(he_dev->rbpl_virt);
        kfree(he_dev->rbpl_table);
-
-       if (he_dev->rbpl_pool)
-               dma_pool_destroy(he_dev->rbpl_pool);
+       dma_pool_destroy(he_dev->rbpl_pool);
 
        if (he_dev->rbrq_base)
                dma_free_coherent(&he_dev->pci_dev->dev, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq),
@@ -1594,8 +1592,7 @@ he_stop(struct he_dev *he_dev)
                dma_free_coherent(&he_dev->pci_dev->dev, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq),
                                  he_dev->tpdrq_base, he_dev->tpdrq_phys);
 
-       if (he_dev->tpd_pool)
-               dma_pool_destroy(he_dev->tpd_pool);
+       dma_pool_destroy(he_dev->tpd_pool);
 
        if (he_dev->pci_dev) {
                pci_read_config_word(he_dev->pci_dev, PCI_COMMAND, &command);
index 74e18b0a6d8945ac6df8537d394729354769e6da..3d7fb6516f74f83cd9276b4d5ff4d0a19d403241 100644 (file)
@@ -805,7 +805,12 @@ static void solos_bh(unsigned long card_arg)
                                        continue;
                                }
 
-                               skb = alloc_skb(size + 1, GFP_ATOMIC);
+                               /* Use netdev_alloc_skb() because it adds NET_SKB_PAD of
+                                * headroom, and ensures we can route packets back out an
+                                * Ethernet interface (for example) without having to
+                                * reallocate. Adding NET_IP_ALIGN also ensures that both
+                                * PPPoATM and PPPoEoBR2684 packets end up aligned. */
+                               skb = netdev_alloc_skb_ip_align(NULL, size + 1);
                                if (!skb) {
                                        if (net_ratelimit())
                                                dev_warn(&card->dev->dev, "Failed to allocate sk_buff for RX\n");
@@ -869,7 +874,10 @@ static void solos_bh(unsigned long card_arg)
                /* Allocate RX skbs for any ports which need them */
                if (card->using_dma && card->atmdev[port] &&
                    !card->rx_skb[port]) {
-                       struct sk_buff *skb = alloc_skb(RX_DMA_SIZE, GFP_ATOMIC);
+                       /* Unlike the MMIO case (qv) we can't add NET_IP_ALIGN
+                        * here; the FPGA can only DMA to addresses which are
+                        * aligned to 4 bytes. */
+                       struct sk_buff *skb = dev_alloc_skb(RX_DMA_SIZE);
                        if (skb) {
                                SKB_CB(skb)->dma_addr =
                                        dma_map_single(&card->dev->dev, skb->data,
index 764280a917761e9bf3360111bb92709d676c69e4..e9fd32e91668992e478f31423c1e56be0724e1d2 100644 (file)
@@ -148,7 +148,11 @@ static void cache_shared_cpu_map_remove(unsigned int cpu)
 
                        if (sibling == cpu) /* skip itself */
                                continue;
+
                        sib_cpu_ci = get_cpu_cacheinfo(sibling);
+                       if (!sib_cpu_ci->info_list)
+                               continue;
+
                        sib_leaf = sib_cpu_ci->info_list + index;
                        cpumask_clear_cpu(cpu, &sib_leaf->shared_cpu_map);
                        cpumask_clear_cpu(sibling, &this_leaf->shared_cpu_map);
@@ -159,6 +163,9 @@ static void cache_shared_cpu_map_remove(unsigned int cpu)
 
 static void free_cache_attributes(unsigned int cpu)
 {
+       if (!per_cpu_cacheinfo(cpu))
+               return;
+
        cache_shared_cpu_map_remove(cpu);
 
        kfree(per_cpu_cacheinfo(cpu));
@@ -514,8 +521,7 @@ static int cacheinfo_cpu_callback(struct notifier_block *nfb,
                break;
        case CPU_DEAD:
                cache_remove_dev(cpu);
-               if (per_cpu_cacheinfo(cpu))
-                       free_cache_attributes(cpu);
+               free_cache_attributes(cpu);
                break;
        }
        return notifier_from_errno(rc);
index 950fff9ce45397024ac5751b452cdd96a6da9907..a12ff9863d7e116ba9f15e21fe9c6fa4070b0f22 100644 (file)
@@ -187,7 +187,7 @@ int __init dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t base,
  * global one. Requires architecture specific dev_get_cma_area() helper
  * function.
  */
-struct page *dma_alloc_from_contiguous(struct device *dev, int count,
+struct page *dma_alloc_from_contiguous(struct device *dev, size_t count,
                                       unsigned int align)
 {
        if (align > CONFIG_CMA_ALIGNMENT)
index 1857a5dd08165584457efa044958e3ba84522847..134483daac25e6627234a5dac90a60687d4810dd 100644 (file)
@@ -63,20 +63,8 @@ static int platform_msi_init(struct irq_domain *domain,
                             unsigned int virq, irq_hw_number_t hwirq,
                             msi_alloc_info_t *arg)
 {
-       struct irq_data *data;
-
-       irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
-                                     info->chip, info->chip_data);
-
-       /*
-        * Save the MSI descriptor in handler_data so that the
-        * irq_write_msi_msg callback can retrieve it (and the
-        * associated device).
-        */
-       data = irq_domain_get_irq_data(domain, virq);
-       data->handler_data = arg->desc;
-
-       return 0;
+       return irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
+                                            info->chip, info->chip_data);
 }
 #else
 #define platform_msi_set_desc          NULL
@@ -97,7 +85,7 @@ static void platform_msi_update_dom_ops(struct msi_domain_info *info)
 
 static void platform_msi_write_msg(struct irq_data *data, struct msi_msg *msg)
 {
-       struct msi_desc *desc = irq_data_get_irq_handler_data(data);
+       struct msi_desc *desc = irq_data_get_msi_desc(data);
        struct platform_msi_priv_data *priv_data;
 
        priv_data = desc->platform.msi_priv_data;
index 2a4154a09e4dca0dc9af3aa09f9a395a313f60e8..85e17bacc834156664c5980c4f7ea7ef68e5d6b6 100644 (file)
@@ -77,13 +77,16 @@ static bool default_stop_ok(struct device *dev)
                                      dev_update_qos_constraint);
 
        if (constraint_ns > 0) {
-               constraint_ns -= td->start_latency_ns;
+               constraint_ns -= td->save_state_latency_ns +
+                               td->stop_latency_ns +
+                               td->start_latency_ns +
+                               td->restore_state_latency_ns;
                if (constraint_ns == 0)
                        return false;
        }
        td->effective_constraint_ns = constraint_ns;
-       td->cached_stop_ok = constraint_ns > td->stop_latency_ns ||
-                               constraint_ns == 0;
+       td->cached_stop_ok = constraint_ns >= 0;
+
        /*
         * The children have been suspended already, so we don't need to take
         * their stop latencies into account here.
@@ -126,18 +129,6 @@ static bool default_power_down_ok(struct dev_pm_domain *pd)
 
        off_on_time_ns = genpd->power_off_latency_ns +
                                genpd->power_on_latency_ns;
-       /*
-        * It doesn't make sense to remove power from the domain if saving
-        * the state of all devices in it and the power off/power on operations
-        * take too much time.
-        *
-        * All devices in this domain have been stopped already at this point.
-        */
-       list_for_each_entry(pdd, &genpd->dev_list, list_node) {
-               if (pdd->dev->driver)
-                       off_on_time_ns +=
-                               to_gpd_data(pdd)->td.save_state_latency_ns;
-       }
 
        min_off_time_ns = -1;
        /*
@@ -193,7 +184,6 @@ static bool default_power_down_ok(struct dev_pm_domain *pd)
                 * constraint_ns cannot be negative here, because the device has
                 * been suspended.
                 */
-               constraint_ns -= td->restore_state_latency_ns;
                if (constraint_ns <= off_on_time_ns)
                        return false;
 
index 28cd75c535b047f2c4276fed4308fa8159491007..7ae7cd990fbf79bf39de570a6a0fca5bd47cef94 100644 (file)
@@ -892,10 +892,17 @@ static int opp_get_microvolt(struct dev_pm_opp *opp, struct device *dev)
        u32 microvolt[3] = {0};
        int count, ret;
 
-       count = of_property_count_u32_elems(opp->np, "opp-microvolt");
-       if (!count)
+       /* Missing property isn't a problem, but an invalid entry is */
+       if (!of_find_property(opp->np, "opp-microvolt", NULL))
                return 0;
 
+       count = of_property_count_u32_elems(opp->np, "opp-microvolt");
+       if (count < 0) {
+               dev_err(dev, "%s: Invalid opp-microvolt property (%d)\n",
+                       __func__, count);
+               return count;
+       }
+
        /* There can be one or three elements here */
        if (count != 1 && count != 3) {
                dev_err(dev, "%s: Invalid number of elements in opp-microvolt property (%d)\n",
@@ -1063,7 +1070,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_add);
  * share a common logic which is isolated here.
  *
  * Return: -EINVAL for bad pointers, -ENOMEM if no memory available for the
- * copy operation, returns 0 if no modifcation was done OR modification was
+ * copy operation, returns 0 if no modification was done OR modification was
  * successful.
  *
  * Locking: The internal device_opp and opp structures are RCU protected.
@@ -1151,7 +1158,7 @@ unlock:
  * mutex locking or synchronize_rcu() blocking calls cannot be used.
  *
  * Return: -EINVAL for bad pointers, -ENOMEM if no memory available for the
- * copy operation, returns 0 if no modifcation was done OR modification was
+ * copy operation, returns 0 if no modification was done OR modification was
  * successful.
  */
 int dev_pm_opp_enable(struct device *dev, unsigned long freq)
@@ -1177,7 +1184,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_enable);
  * mutex locking or synchronize_rcu() blocking calls cannot be used.
  *
  * Return: -EINVAL for bad pointers, -ENOMEM if no memory available for the
- * copy operation, returns 0 if no modifcation was done OR modification was
+ * copy operation, returns 0 if no modification was done OR modification was
  * successful.
  */
 int dev_pm_opp_disable(struct device *dev, unsigned long freq)
index f42f2bac646623fc1db767bae3a5fff0ecf98aac..4c55cfbad19e95df8cb67864d78af960c073b4df 100644 (file)
@@ -32,8 +32,7 @@ static DEFINE_MUTEX(regmap_debugfs_early_lock);
 /* Calculate the length of a fixed format  */
 static size_t regmap_calc_reg_len(int max_val, char *buf, size_t buf_size)
 {
-       snprintf(buf, buf_size, "%x", max_val);
-       return strlen(buf);
+       return snprintf(NULL, 0, "%x", max_val);
 }
 
 static ssize_t regmap_name_read_file(struct file *file,
@@ -432,7 +431,7 @@ static ssize_t regmap_access_read_file(struct file *file,
                /* If we're in the region the user is trying to read */
                if (p >= *ppos) {
                        /* ...but not beyond it */
-                       if (buf_pos >= count - 1 - tot_len)
+                       if (buf_pos + tot_len + 1 >= count)
                                break;
 
                        /* Format the register */
index f9889b6bc02c316bed46e130c9f5c7ce38b7b93b..674f800a3b5760ad6374c98fa11e88097e30d160 100644 (file)
@@ -1486,17 +1486,16 @@ static void loop_handle_cmd(struct loop_cmd *cmd)
 {
        const bool write = cmd->rq->cmd_flags & REQ_WRITE;
        struct loop_device *lo = cmd->rq->q->queuedata;
-       int ret = -EIO;
+       int ret = 0;
 
-       if (write && (lo->lo_flags & LO_FLAGS_READ_ONLY))
+       if (write && (lo->lo_flags & LO_FLAGS_READ_ONLY)) {
+               ret = -EIO;
                goto failed;
+       }
 
        ret = do_req_filebacked(lo, cmd->rq);
-
  failed:
-       if (ret)
-               cmd->rq->errors = -EIO;
-       blk_mq_complete_request(cmd->rq);
+       blk_mq_complete_request(cmd->rq, ret ? -EIO : 0);
 }
 
 static void loop_queue_write_work(struct work_struct *work)
index 293495a75d3d8ce1e0f61e3571ddcc0c1fa14312..1b87623381e2b1183b5c9d57c870b7c10924f65e 100644 (file)
@@ -60,6 +60,7 @@ struct nbd_device {
        bool disconnect; /* a disconnect has been requested by user */
 
        struct timer_list timeout_timer;
+       spinlock_t tasks_lock;
        struct task_struct *task_recv;
        struct task_struct *task_send;
 
@@ -140,21 +141,23 @@ static void sock_shutdown(struct nbd_device *nbd)
 static void nbd_xmit_timeout(unsigned long arg)
 {
        struct nbd_device *nbd = (struct nbd_device *)arg;
-       struct task_struct *task;
+       unsigned long flags;
 
        if (list_empty(&nbd->queue_head))
                return;
 
        nbd->disconnect = true;
 
-       task = READ_ONCE(nbd->task_recv);
-       if (task)
-               force_sig(SIGKILL, task);
+       spin_lock_irqsave(&nbd->tasks_lock, flags);
+
+       if (nbd->task_recv)
+               force_sig(SIGKILL, nbd->task_recv);
 
-       task = READ_ONCE(nbd->task_send);
-       if (task)
+       if (nbd->task_send)
                force_sig(SIGKILL, nbd->task_send);
 
+       spin_unlock_irqrestore(&nbd->tasks_lock, flags);
+
        dev_err(nbd_to_dev(nbd), "Connection timed out, killed receiver and sender, shutting down connection\n");
 }
 
@@ -403,17 +406,24 @@ static int nbd_thread_recv(struct nbd_device *nbd)
 {
        struct request *req;
        int ret;
+       unsigned long flags;
 
        BUG_ON(nbd->magic != NBD_MAGIC);
 
        sk_set_memalloc(nbd->sock->sk);
 
+       spin_lock_irqsave(&nbd->tasks_lock, flags);
        nbd->task_recv = current;
+       spin_unlock_irqrestore(&nbd->tasks_lock, flags);
 
        ret = device_create_file(disk_to_dev(nbd->disk), &pid_attr);
        if (ret) {
                dev_err(disk_to_dev(nbd->disk), "device_create_file failed!\n");
+
+               spin_lock_irqsave(&nbd->tasks_lock, flags);
                nbd->task_recv = NULL;
+               spin_unlock_irqrestore(&nbd->tasks_lock, flags);
+
                return ret;
        }
 
@@ -429,7 +439,9 @@ static int nbd_thread_recv(struct nbd_device *nbd)
 
        device_remove_file(disk_to_dev(nbd->disk), &pid_attr);
 
+       spin_lock_irqsave(&nbd->tasks_lock, flags);
        nbd->task_recv = NULL;
+       spin_unlock_irqrestore(&nbd->tasks_lock, flags);
 
        if (signal_pending(current)) {
                siginfo_t info;
@@ -534,8 +546,11 @@ static int nbd_thread_send(void *data)
 {
        struct nbd_device *nbd = data;
        struct request *req;
+       unsigned long flags;
 
+       spin_lock_irqsave(&nbd->tasks_lock, flags);
        nbd->task_send = current;
+       spin_unlock_irqrestore(&nbd->tasks_lock, flags);
 
        set_user_nice(current, MIN_NICE);
        while (!kthread_should_stop() || !list_empty(&nbd->waiting_queue)) {
@@ -572,7 +587,15 @@ static int nbd_thread_send(void *data)
                nbd_handle_req(nbd, req);
        }
 
+       spin_lock_irqsave(&nbd->tasks_lock, flags);
        nbd->task_send = NULL;
+       spin_unlock_irqrestore(&nbd->tasks_lock, flags);
+
+       /* Clear maybe pending signals */
+       if (signal_pending(current)) {
+               siginfo_t info;
+               dequeue_signal_lock(current, &current->blocked, &info);
+       }
 
        return 0;
 }
@@ -1052,6 +1075,7 @@ static int __init nbd_init(void)
                nbd_dev[i].magic = NBD_MAGIC;
                INIT_LIST_HEAD(&nbd_dev[i].waiting_queue);
                spin_lock_init(&nbd_dev[i].queue_lock);
+               spin_lock_init(&nbd_dev[i].tasks_lock);
                INIT_LIST_HEAD(&nbd_dev[i].queue_head);
                mutex_init(&nbd_dev[i].tx_lock);
                init_timer(&nbd_dev[i].timeout_timer);
index 17269a3b85f282fd33df0c1f750559ea6c749ad7..1c9e4fe5aa440cbde62bb5e6c0cf0c397d8417a7 100644 (file)
@@ -289,7 +289,7 @@ static inline void null_handle_cmd(struct nullb_cmd *cmd)
        case NULL_IRQ_SOFTIRQ:
                switch (queue_mode)  {
                case NULL_Q_MQ:
-                       blk_mq_complete_request(cmd->rq);
+                       blk_mq_complete_request(cmd->rq, cmd->rq->errors);
                        break;
                case NULL_Q_RQ:
                        blk_complete_request(cmd->rq);
@@ -406,6 +406,22 @@ static struct blk_mq_ops null_mq_ops = {
        .complete       = null_softirq_done_fn,
 };
 
+static void cleanup_queue(struct nullb_queue *nq)
+{
+       kfree(nq->tag_map);
+       kfree(nq->cmds);
+}
+
+static void cleanup_queues(struct nullb *nullb)
+{
+       int i;
+
+       for (i = 0; i < nullb->nr_queues; i++)
+               cleanup_queue(&nullb->queues[i]);
+
+       kfree(nullb->queues);
+}
+
 static void null_del_dev(struct nullb *nullb)
 {
        list_del_init(&nullb->list);
@@ -415,6 +431,7 @@ static void null_del_dev(struct nullb *nullb)
        if (queue_mode == NULL_Q_MQ)
                blk_mq_free_tag_set(&nullb->tag_set);
        put_disk(nullb->disk);
+       cleanup_queues(nullb);
        kfree(nullb);
 }
 
@@ -459,22 +476,6 @@ static int setup_commands(struct nullb_queue *nq)
        return 0;
 }
 
-static void cleanup_queue(struct nullb_queue *nq)
-{
-       kfree(nq->tag_map);
-       kfree(nq->cmds);
-}
-
-static void cleanup_queues(struct nullb *nullb)
-{
-       int i;
-
-       for (i = 0; i < nullb->nr_queues; i++)
-               cleanup_queue(&nullb->queues[i]);
-
-       kfree(nullb->queues);
-}
-
 static int setup_queues(struct nullb *nullb)
 {
        nullb->queues = kzalloc(submit_queues * sizeof(struct nullb_queue),
@@ -588,8 +589,7 @@ static int null_add_dev(void)
        blk_queue_physical_block_size(nullb->q, bs);
 
        size = gb * 1024 * 1024 * 1024ULL;
-       sector_div(size, bs);
-       set_capacity(disk, size);
+       set_capacity(disk, size >> 9);
 
        disk->flags |= GENHD_FL_EXT_DEVT | GENHD_FL_SUPPRESS_PARTITION_INFO;
        disk->major             = null_major;
index b97fc3fe0916a6b6fd3fb2be32be44ce3c137b39..ccc0c1f93daa45fae2603dd8e36bd2dcc38a8217 100644 (file)
@@ -603,31 +603,34 @@ static void req_completion(struct nvme_queue *nvmeq, void *ctx,
        struct nvme_iod *iod = ctx;
        struct request *req = iod_get_private(iod);
        struct nvme_cmd_info *cmd_rq = blk_mq_rq_to_pdu(req);
-
        u16 status = le16_to_cpup(&cqe->status) >> 1;
+       bool requeue = false;
+       int error = 0;
 
        if (unlikely(status)) {
                if (!(status & NVME_SC_DNR || blk_noretry_request(req))
                    && (jiffies - req->start_time) < req->timeout) {
                        unsigned long flags;
 
+                       requeue = true;
                        blk_mq_requeue_request(req);
                        spin_lock_irqsave(req->q->queue_lock, flags);
                        if (!blk_queue_stopped(req->q))
                                blk_mq_kick_requeue_list(req->q);
                        spin_unlock_irqrestore(req->q->queue_lock, flags);
-                       return;
+                       goto release_iod;
                }
+
                if (req->cmd_type == REQ_TYPE_DRV_PRIV) {
                        if (cmd_rq->ctx == CMD_CTX_CANCELLED)
-                               req->errors = -EINTR;
+                               error = -EINTR;
                        else
-                               req->errors = status;
+                               error = status;
                } else {
-                       req->errors = nvme_error_status(status);
+                       error = nvme_error_status(status);
                }
-       } else
-               req->errors = 0;
+       }
+
        if (req->cmd_type == REQ_TYPE_DRV_PRIV) {
                u32 result = le32_to_cpup(&cqe->result);
                req->special = (void *)(uintptr_t)result;
@@ -636,8 +639,9 @@ static void req_completion(struct nvme_queue *nvmeq, void *ctx,
        if (cmd_rq->aborted)
                dev_warn(nvmeq->dev->dev,
                        "completing aborted command with status:%04x\n",
-                       status);
+                       error);
 
+release_iod:
        if (iod->nents) {
                dma_unmap_sg(nvmeq->dev->dev, iod->sg, iod->nents,
                        rq_data_dir(req) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
@@ -650,7 +654,8 @@ static void req_completion(struct nvme_queue *nvmeq, void *ctx,
        }
        nvme_free_iod(nvmeq->dev, iod);
 
-       blk_mq_complete_request(req);
+       if (likely(!requeue))
+               blk_mq_complete_request(req, error);
 }
 
 /* length is in bytes.  gfp flags indicates whether we may sleep. */
@@ -863,8 +868,7 @@ static int nvme_queue_rq(struct blk_mq_hw_ctx *hctx,
        if (ns && ns->ms && !blk_integrity_rq(req)) {
                if (!(ns->pi_type && ns->ms == 8) &&
                                        req->cmd_type != REQ_TYPE_DRV_PRIV) {
-                       req->errors = -EFAULT;
-                       blk_mq_complete_request(req);
+                       blk_mq_complete_request(req, -EFAULT);
                        return BLK_MQ_RQ_QUEUE_OK;
                }
        }
@@ -1806,7 +1810,7 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio)
 
        length = (io.nblocks + 1) << ns->lba_shift;
        meta_len = (io.nblocks + 1) * ns->ms;
-       metadata = (void __user *)(unsigned long)io.metadata;
+       metadata = (void __user *)(uintptr_t)io.metadata;
        write = io.opcode & 1;
 
        if (ns->ext) {
@@ -1846,7 +1850,7 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio)
        c.rw.metadata = cpu_to_le64(meta_dma);
 
        status = __nvme_submit_sync_cmd(ns->queue, &c, NULL,
-                       (void __user *)io.addr, length, NULL, 0);
+                       (void __user *)(uintptr_t)io.addr, length, NULL, 0);
  unmap:
        if (meta) {
                if (status == NVME_SC_SUCCESS && !write) {
@@ -1888,7 +1892,7 @@ static int nvme_user_cmd(struct nvme_dev *dev, struct nvme_ns *ns,
                timeout = msecs_to_jiffies(cmd.timeout_ms);
 
        status = __nvme_submit_sync_cmd(ns ? ns->queue : dev->admin_q, &c,
-                       NULL, (void __user *)cmd.addr, cmd.data_len,
+                       NULL, (void __user *)(uintptr_t)cmd.addr, cmd.data_len,
                        &cmd.result, timeout);
        if (status >= 0) {
                if (put_user(cmd.result, &ucmd->result))
@@ -2439,6 +2443,22 @@ static void nvme_scan_namespaces(struct nvme_dev *dev, unsigned nn)
        list_sort(NULL, &dev->namespaces, ns_cmp);
 }
 
+static void nvme_set_irq_hints(struct nvme_dev *dev)
+{
+       struct nvme_queue *nvmeq;
+       int i;
+
+       for (i = 0; i < dev->online_queues; i++) {
+               nvmeq = dev->queues[i];
+
+               if (!nvmeq->tags || !(*nvmeq->tags))
+                       continue;
+
+               irq_set_affinity_hint(dev->entry[nvmeq->cq_vector].vector,
+                                       blk_mq_tags_cpumask(*nvmeq->tags));
+       }
+}
+
 static void nvme_dev_scan(struct work_struct *work)
 {
        struct nvme_dev *dev = container_of(work, struct nvme_dev, scan_work);
@@ -2450,6 +2470,7 @@ static void nvme_dev_scan(struct work_struct *work)
                return;
        nvme_scan_namespaces(dev, le32_to_cpup(&ctrl->nn));
        kfree(ctrl);
+       nvme_set_irq_hints(dev);
 }
 
 /*
@@ -2953,22 +2974,6 @@ static const struct file_operations nvme_dev_fops = {
        .compat_ioctl   = nvme_dev_ioctl,
 };
 
-static void nvme_set_irq_hints(struct nvme_dev *dev)
-{
-       struct nvme_queue *nvmeq;
-       int i;
-
-       for (i = 0; i < dev->online_queues; i++) {
-               nvmeq = dev->queues[i];
-
-               if (!nvmeq->tags || !(*nvmeq->tags))
-                       continue;
-
-               irq_set_affinity_hint(dev->entry[nvmeq->cq_vector].vector,
-                                       blk_mq_tags_cpumask(*nvmeq->tags));
-       }
-}
-
 static int nvme_dev_start(struct nvme_dev *dev)
 {
        int result;
@@ -3010,8 +3015,6 @@ static int nvme_dev_start(struct nvme_dev *dev)
        if (result)
                goto free_tags;
 
-       nvme_set_irq_hints(dev);
-
        dev->event_limit = 1;
        return result;
 
@@ -3062,7 +3065,6 @@ static int nvme_dev_resume(struct nvme_dev *dev)
        } else {
                nvme_unfreeze_queues(dev);
                nvme_dev_add(dev);
-               nvme_set_irq_hints(dev);
        }
        return 0;
 }
index d93a0372b37b5c7b4cb214e7013e64897c3a9aba..128e7df5b807222ba2d6f50148cb164919a308f7 100644 (file)
@@ -96,6 +96,8 @@ static int atomic_dec_return_safe(atomic_t *v)
 #define RBD_MINORS_PER_MAJOR           256
 #define RBD_SINGLE_MAJOR_PART_SHIFT    4
 
+#define RBD_MAX_PARENT_CHAIN_LEN       16
+
 #define RBD_SNAP_DEV_NAME_PREFIX       "snap_"
 #define RBD_MAX_SNAP_NAME_LEN  \
                        (NAME_MAX - (sizeof (RBD_SNAP_DEV_NAME_PREFIX) - 1))
@@ -426,7 +428,7 @@ static ssize_t rbd_add_single_major(struct bus_type *bus, const char *buf,
                                    size_t count);
 static ssize_t rbd_remove_single_major(struct bus_type *bus, const char *buf,
                                       size_t count);
-static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping);
+static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth);
 static void rbd_spec_put(struct rbd_spec *spec);
 
 static int rbd_dev_id_to_minor(int dev_id)
@@ -1863,9 +1865,11 @@ static void rbd_osd_req_callback(struct ceph_osd_request *osd_req,
                rbd_osd_read_callback(obj_request);
                break;
        case CEPH_OSD_OP_SETALLOCHINT:
-               rbd_assert(osd_req->r_ops[1].op == CEPH_OSD_OP_WRITE);
+               rbd_assert(osd_req->r_ops[1].op == CEPH_OSD_OP_WRITE ||
+                          osd_req->r_ops[1].op == CEPH_OSD_OP_WRITEFULL);
                /* fall through */
        case CEPH_OSD_OP_WRITE:
+       case CEPH_OSD_OP_WRITEFULL:
                rbd_osd_write_callback(obj_request);
                break;
        case CEPH_OSD_OP_STAT:
@@ -2401,7 +2405,10 @@ static void rbd_img_obj_request_fill(struct rbd_obj_request *obj_request,
                                opcode = CEPH_OSD_OP_ZERO;
                }
        } else if (op_type == OBJ_OP_WRITE) {
-               opcode = CEPH_OSD_OP_WRITE;
+               if (!offset && length == object_size)
+                       opcode = CEPH_OSD_OP_WRITEFULL;
+               else
+                       opcode = CEPH_OSD_OP_WRITE;
                osd_req_op_alloc_hint_init(osd_request, num_ops,
                                        object_size, object_size);
                num_ops++;
@@ -3760,6 +3767,7 @@ static int rbd_init_disk(struct rbd_device *rbd_dev)
        /* set io sizes to object size */
        segment_size = rbd_obj_bytes(&rbd_dev->header);
        blk_queue_max_hw_sectors(q, segment_size / SECTOR_SIZE);
+       q->limits.max_sectors = queue_max_hw_sectors(q);
        blk_queue_max_segments(q, segment_size / SECTOR_SIZE);
        blk_queue_max_segment_size(q, segment_size);
        blk_queue_io_min(q, segment_size);
@@ -3772,6 +3780,9 @@ static int rbd_init_disk(struct rbd_device *rbd_dev)
        blk_queue_max_discard_sectors(q, segment_size / SECTOR_SIZE);
        q->limits.discard_zeroes_data = 1;
 
+       if (!ceph_test_opt(rbd_dev->rbd_client->client, NOCRC))
+               q->backing_dev_info.capabilities |= BDI_CAP_STABLE_WRITES;
+
        disk->queue = q;
 
        q->queuedata = rbd_dev;
@@ -5125,44 +5136,51 @@ out_err:
        return ret;
 }
 
-static int rbd_dev_probe_parent(struct rbd_device *rbd_dev)
+/*
+ * @depth is rbd_dev_image_probe() -> rbd_dev_probe_parent() ->
+ * rbd_dev_image_probe() recursion depth, which means it's also the
+ * length of the already discovered part of the parent chain.
+ */
+static int rbd_dev_probe_parent(struct rbd_device *rbd_dev, int depth)
 {
        struct rbd_device *parent = NULL;
-       struct rbd_spec *parent_spec;
-       struct rbd_client *rbdc;
        int ret;
 
        if (!rbd_dev->parent_spec)
                return 0;
-       /*
-        * We need to pass a reference to the client and the parent
-        * spec when creating the parent rbd_dev.  Images related by
-        * parent/child relationships always share both.
-        */
-       parent_spec = rbd_spec_get(rbd_dev->parent_spec);
-       rbdc = __rbd_get_client(rbd_dev->rbd_client);
 
-       ret = -ENOMEM;
-       parent = rbd_dev_create(rbdc, parent_spec, NULL);
-       if (!parent)
+       if (++depth > RBD_MAX_PARENT_CHAIN_LEN) {
+               pr_info("parent chain is too long (%d)\n", depth);
+               ret = -EINVAL;
+               goto out_err;
+       }
+
+       parent = rbd_dev_create(rbd_dev->rbd_client, rbd_dev->parent_spec,
+                               NULL);
+       if (!parent) {
+               ret = -ENOMEM;
                goto out_err;
+       }
 
-       ret = rbd_dev_image_probe(parent, false);
+       /*
+        * Images related by parent/child relationships always share
+        * rbd_client and spec/parent_spec, so bump their refcounts.
+        */
+       __rbd_get_client(rbd_dev->rbd_client);
+       rbd_spec_get(rbd_dev->parent_spec);
+
+       ret = rbd_dev_image_probe(parent, depth);
        if (ret < 0)
                goto out_err;
+
        rbd_dev->parent = parent;
        atomic_set(&rbd_dev->parent_ref, 1);
-
        return 0;
+
 out_err:
-       if (parent) {
-               rbd_dev_unparent(rbd_dev);
+       rbd_dev_unparent(rbd_dev);
+       if (parent)
                rbd_dev_destroy(parent);
-       } else {
-               rbd_put_client(rbdc);
-               rbd_spec_put(parent_spec);
-       }
-
        return ret;
 }
 
@@ -5280,7 +5298,7 @@ static void rbd_dev_image_release(struct rbd_device *rbd_dev)
  * parent), initiate a watch on its header object before using that
  * object to get detailed information about the rbd image.
  */
-static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping)
+static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth)
 {
        int ret;
 
@@ -5298,7 +5316,7 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping)
        if (ret)
                goto err_out_format;
 
-       if (mapping) {
+       if (!depth) {
                ret = rbd_dev_header_watch_sync(rbd_dev);
                if (ret) {
                        if (ret == -ENOENT)
@@ -5319,7 +5337,7 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping)
         * Otherwise this is a parent image, identified by pool, image
         * and snap ids - need to fill in names for those ids.
         */
-       if (mapping)
+       if (!depth)
                ret = rbd_spec_fill_snap_id(rbd_dev);
        else
                ret = rbd_spec_fill_names(rbd_dev);
@@ -5341,12 +5359,12 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping)
                 * Need to warn users if this image is the one being
                 * mapped and has a parent.
                 */
-               if (mapping && rbd_dev->parent_spec)
+               if (!depth && rbd_dev->parent_spec)
                        rbd_warn(rbd_dev,
                                 "WARNING: kernel layering is EXPERIMENTAL!");
        }
 
-       ret = rbd_dev_probe_parent(rbd_dev);
+       ret = rbd_dev_probe_parent(rbd_dev, depth);
        if (ret)
                goto err_out_probe;
 
@@ -5357,7 +5375,7 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping)
 err_out_probe:
        rbd_dev_unprobe(rbd_dev);
 err_out_watch:
-       if (mapping)
+       if (!depth)
                rbd_dev_header_unwatch_sync(rbd_dev);
 out_header_name:
        kfree(rbd_dev->header_name);
@@ -5420,7 +5438,7 @@ static ssize_t do_rbd_add(struct bus_type *bus,
        spec = NULL;            /* rbd_dev now owns this */
        rbd_opts = NULL;        /* rbd_dev now owns this */
 
-       rc = rbd_dev_image_probe(rbd_dev, true);
+       rc = rbd_dev_image_probe(rbd_dev, 0);
        if (rc < 0)
                goto err_out_rbd_dev;
 
index e93899cc6f60be0bd13b45dde3b8d697b7a733c8..6ca35495a5becdbac067cb4338981191fd6bc56a 100644 (file)
@@ -144,7 +144,7 @@ static void virtblk_done(struct virtqueue *vq)
        do {
                virtqueue_disable_cb(vq);
                while ((vbr = virtqueue_get_buf(vblk->vqs[qid].vq, &len)) != NULL) {
-                       blk_mq_complete_request(vbr->req);
+                       blk_mq_complete_request(vbr->req, vbr->req->errors);
                        req_done = true;
                }
                if (unlikely(virtqueue_is_broken(vq)))
index deb3f001791f159c5c7ebce19814de31e3106a5e..767657565de64e73f61304741fe9f39c496a2892 100644 (file)
@@ -212,6 +212,9 @@ static int xen_blkif_map(struct xen_blkif *blkif, grant_ref_t *gref,
 
 static int xen_blkif_disconnect(struct xen_blkif *blkif)
 {
+       struct pending_req *req, *n;
+       int i = 0, j;
+
        if (blkif->xenblkd) {
                kthread_stop(blkif->xenblkd);
                wake_up(&blkif->shutdown_wq);
@@ -238,13 +241,28 @@ static int xen_blkif_disconnect(struct xen_blkif *blkif)
        /* Remove all persistent grants and the cache of ballooned pages. */
        xen_blkbk_free_caches(blkif);
 
+       /* Check that there is no request in use */
+       list_for_each_entry_safe(req, n, &blkif->pending_free, free_list) {
+               list_del(&req->free_list);
+
+               for (j = 0; j < MAX_INDIRECT_SEGMENTS; j++)
+                       kfree(req->segments[j]);
+
+               for (j = 0; j < MAX_INDIRECT_PAGES; j++)
+                       kfree(req->indirect_pages[j]);
+
+               kfree(req);
+               i++;
+       }
+
+       WARN_ON(i != (XEN_BLKIF_REQS_PER_PAGE * blkif->nr_ring_pages));
+       blkif->nr_ring_pages = 0;
+
        return 0;
 }
 
 static void xen_blkif_free(struct xen_blkif *blkif)
 {
-       struct pending_req *req, *n;
-       int i = 0, j;
 
        xen_blkif_disconnect(blkif);
        xen_vbd_free(&blkif->vbd);
@@ -257,22 +275,6 @@ static void xen_blkif_free(struct xen_blkif *blkif)
        BUG_ON(!list_empty(&blkif->free_pages));
        BUG_ON(!RB_EMPTY_ROOT(&blkif->persistent_gnts));
 
-       /* Check that there is no request in use */
-       list_for_each_entry_safe(req, n, &blkif->pending_free, free_list) {
-               list_del(&req->free_list);
-
-               for (j = 0; j < MAX_INDIRECT_SEGMENTS; j++)
-                       kfree(req->segments[j]);
-
-               for (j = 0; j < MAX_INDIRECT_PAGES; j++)
-                       kfree(req->indirect_pages[j]);
-
-               kfree(req);
-               i++;
-       }
-
-       WARN_ON(i != (XEN_BLKIF_REQS_PER_PAGE * blkif->nr_ring_pages));
-
        kmem_cache_free(xen_blkif_cachep, blkif);
 }
 
index 0823a96902f87fa90d2e35a425183ea0de2e0049..a69c02dadec05684f2a49eefe98033e8ebbc0c3e 100644 (file)
@@ -1142,6 +1142,7 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
        RING_IDX i, rp;
        unsigned long flags;
        struct blkfront_info *info = (struct blkfront_info *)dev_id;
+       int error;
 
        spin_lock_irqsave(&info->io_lock, flags);
 
@@ -1182,37 +1183,37 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
                        continue;
                }
 
-               req->errors = (bret->status == BLKIF_RSP_OKAY) ? 0 : -EIO;
+               error = (bret->status == BLKIF_RSP_OKAY) ? 0 : -EIO;
                switch (bret->operation) {
                case BLKIF_OP_DISCARD:
                        if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) {
                                struct request_queue *rq = info->rq;
                                printk(KERN_WARNING "blkfront: %s: %s op failed\n",
                                           info->gd->disk_name, op_name(bret->operation));
-                               req->errors = -EOPNOTSUPP;
+                               error = -EOPNOTSUPP;
                                info->feature_discard = 0;
                                info->feature_secdiscard = 0;
                                queue_flag_clear(QUEUE_FLAG_DISCARD, rq);
                                queue_flag_clear(QUEUE_FLAG_SECDISCARD, rq);
                        }
-                       blk_mq_complete_request(req);
+                       blk_mq_complete_request(req, error);
                        break;
                case BLKIF_OP_FLUSH_DISKCACHE:
                case BLKIF_OP_WRITE_BARRIER:
                        if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) {
                                printk(KERN_WARNING "blkfront: %s: %s op failed\n",
                                       info->gd->disk_name, op_name(bret->operation));
-                               req->errors = -EOPNOTSUPP;
+                               error = -EOPNOTSUPP;
                        }
                        if (unlikely(bret->status == BLKIF_RSP_ERROR &&
                                     info->shadow[id].req.u.rw.nr_segments == 0)) {
                                printk(KERN_WARNING "blkfront: %s: empty %s op failed\n",
                                       info->gd->disk_name, op_name(bret->operation));
-                               req->errors = -EOPNOTSUPP;
+                               error = -EOPNOTSUPP;
                        }
-                       if (unlikely(req->errors)) {
-                               if (req->errors == -EOPNOTSUPP)
-                                       req->errors = 0;
+                       if (unlikely(error)) {
+                               if (error == -EOPNOTSUPP)
+                                       error = 0;
                                info->feature_flush = 0;
                                xlvbd_flush(info);
                        }
@@ -1223,7 +1224,7 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
                                dev_dbg(&info->xbdev->dev, "Bad return from blkdev data "
                                        "request: %x\n", bret->status);
 
-                       blk_mq_complete_request(req);
+                       blk_mq_complete_request(req, error);
                        break;
                default:
                        BUG();
@@ -1955,7 +1956,8 @@ static void blkback_changed(struct xenbus_device *dev,
                        break;
                /* Missed the backend's Closing state -- fallthrough */
        case XenbusStateClosing:
-               blkfront_closing(info);
+               if (info)
+                       blkfront_closing(info);
                break;
        }
 }
index 965d1afb0eaa72558a1c6c36869e791733ec7350..5cb13ca3a3acac2aa16a104e9731770066ff03de 100644 (file)
@@ -330,12 +330,14 @@ void zcomp_destroy(struct zcomp *comp)
  * allocate new zcomp and initialize it. return compressing
  * backend pointer or ERR_PTR if things went bad. ERR_PTR(-EINVAL)
  * if requested algorithm is not supported, ERR_PTR(-ENOMEM) in
- * case of allocation error.
+ * case of allocation error, or any other error potentially
+ * returned by functions zcomp_strm_{multi,single}_create.
  */
 struct zcomp *zcomp_create(const char *compress, int max_strm)
 {
        struct zcomp *comp;
        struct zcomp_backend *backend;
+       int error;
 
        backend = find_backend(compress);
        if (!backend)
@@ -347,12 +349,12 @@ struct zcomp *zcomp_create(const char *compress, int max_strm)
 
        comp->backend = backend;
        if (max_strm > 1)
-               zcomp_strm_multi_create(comp, max_strm);
+               error = zcomp_strm_multi_create(comp, max_strm);
        else
-               zcomp_strm_single_create(comp);
-       if (!comp->stream) {
+               error = zcomp_strm_single_create(comp);
+       if (error) {
                kfree(comp);
-               return ERR_PTR(-ENOMEM);
+               return ERR_PTR(error);
        }
        return comp;
 }
index 1a82f3a17681b77926a11c29ba23cbdc27d8b6b5..0ebca8ba7bc4103eeeb48c2fe245404091e0c9d3 100644 (file)
@@ -36,7 +36,6 @@ config ARM_CCI400_PORT_CTRL
 
 config ARM_CCI500_PMU
        bool "ARM CCI500 PMU support"
-       default y
        depends on (ARM && CPU_V7) || ARM64
        depends on PERF_EVENTS
        select ARM_CCI_PMU
index 7d9879e166cf4c4346402cb353ef3cd002483740..7082c7268845639399d9ceab44471937011e1705 100644 (file)
@@ -1184,11 +1184,12 @@ static int arm_ccn_pmu_cpu_notifier(struct notifier_block *nb,
                if (!cpumask_test_and_clear_cpu(cpu, &dt->cpu))
                        break;
                target = cpumask_any_but(cpu_online_mask, cpu);
-               if (target < 0)
+               if (target >= nr_cpu_ids)
                        break;
                perf_pmu_migrate_context(&dt->pmu, cpu, target);
                cpumask_set_cpu(target, &dt->cpu);
-               WARN_ON(irq_set_affinity(ccn->irq, &dt->cpu) != 0);
+               if (ccn->irq)
+                       WARN_ON(irq_set_affinity(ccn->irq, &dt->cpu) != 0);
        default:
                break;
        }
index c37cf754a9856cafae20f0739ae354673a21cf31..3c77645405e52019f01304ee2ee5c985f9a90865 100644 (file)
@@ -344,11 +344,12 @@ static int xgene_rng_probe(struct platform_device *pdev)
        if (IS_ERR(ctx->csr_base))
                return PTR_ERR(ctx->csr_base);
 
-       ctx->irq = platform_get_irq(pdev, 0);
-       if (ctx->irq < 0) {
+       rc = platform_get_irq(pdev, 0);
+       if (rc < 0) {
                dev_err(&pdev->dev, "No IRQ resource\n");
-               return ctx->irq;
+               return rc;
        }
+       ctx->irq = rc;
 
        dev_dbg(&pdev->dev, "APM X-Gene RNG BASE %p ALARM IRQ %d",
                ctx->csr_base, ctx->irq);
index 43e2c3ad6c3111ae6d0a83f027b75344c087f5f2..0ebcf449778abc18e9956733ebb55db2e5dc77f9 100644 (file)
@@ -2437,7 +2437,8 @@ static int __clk_init(struct device *dev, struct clk *clk_user)
        hlist_for_each_entry_safe(orphan, tmp2, &clk_orphan_list, child_node) {
                if (orphan->num_parents && orphan->ops->get_parent) {
                        i = orphan->ops->get_parent(orphan->hw);
-                       if (!strcmp(core->name, orphan->parent_names[i]))
+                       if (i >= 0 && i < orphan->num_parents &&
+                           !strcmp(core->name, orphan->parent_names[i]))
                                clk_core_reparent(orphan, core);
                        continue;
                }
index c0eaf0973bd2bca88e269dbca7f44fd3fcdaf3c7..779b6ff0c7ad4040a680a2155964bd3016363767 100644 (file)
@@ -333,7 +333,8 @@ int clk_add_alias(const char *alias, const char *alias_dev_name,
        if (IS_ERR(r))
                return PTR_ERR(r);
 
-       l = clkdev_create(r, alias, "%s", alias_dev_name);
+       l = clkdev_create(r, alias, alias_dev_name ? "%s" : NULL,
+                         alias_dev_name);
        clk_put(r);
 
        return l ? 0 : -ENODEV;
index 2a38eb4a25527604ec0cbd867ab5d6fbfbc4b648..6cf38dc1c9291e843f140e187b5dd0f0aadf6d4b 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/err.h>
 #include <linux/device.h>
 #include <linux/of_address.h>
+#include <linux/slab.h>
 
 static DEFINE_SPINLOCK(clklock);
 
index 2c16807341dce86b386cb662aa1a52418d311665..e434854486127a5287fd7b73f92fa3dc7c5151cc 100644 (file)
@@ -1,6 +1,12 @@
 config COMMON_CLK_HI6220
        bool "Hi6220 Clock Driver"
-       depends on (ARCH_HISI || COMPILE_TEST) && MAILBOX
+       depends on ARCH_HISI || COMPILE_TEST
        default ARCH_HISI
        help
          Build the Hisilicon Hi6220 clock driver based on the common clock framework.
+
+config STUB_CLK_HI6220
+       bool "Hi6220 Stub Clock Driver"
+       depends on COMMON_CLK_HI6220 && MAILBOX
+       help
+         Build the Hisilicon Hi6220 stub clock driver.
index 4a1001a11f04502d1b0b003ec5a7b3785946f313..74dba31590f9a39e122b1aa589cb869b685d3e18 100644 (file)
@@ -7,4 +7,5 @@ obj-y   += clk.o clkgate-separated.o clkdivider-hi6220.o
 obj-$(CONFIG_ARCH_HI3xxx)      += clk-hi3620.o
 obj-$(CONFIG_ARCH_HIP04)       += clk-hip04.o
 obj-$(CONFIG_ARCH_HIX5HD2)     += clk-hix5hd2.o
-obj-$(CONFIG_COMMON_CLK_HI6220)        += clk-hi6220.o clk-hi6220-stub.o
+obj-$(CONFIG_COMMON_CLK_HI6220)        += clk-hi6220.o
+obj-$(CONFIG_STUB_CLK_HI6220)  += clk-hi6220-stub.o
index 5837eb8a212fbdcd8446ff9da77f393cc05c128a..85da8b9832568b2e4daab35eea661d4d99a5ac26 100644 (file)
@@ -197,6 +197,7 @@ static void __init of_cpu_clk_setup(struct device_node *node)
        for_each_node_by_type(dn, "cpu") {
                struct clk_init_data init;
                struct clk *clk;
+               struct clk *parent_clk;
                char *clk_name = kzalloc(5, GFP_KERNEL);
                int cpu, err;
 
@@ -208,8 +209,9 @@ static void __init of_cpu_clk_setup(struct device_node *node)
                        goto bail_out;
 
                sprintf(clk_name, "cpu%d", cpu);
+               parent_clk = of_clk_get(node, 0);
 
-               cpuclk[cpu].parent_name = of_clk_get_parent_name(node, 0);
+               cpuclk[cpu].parent_name = __clk_get_name(parent_clk);
                cpuclk[cpu].clk_name = clk_name;
                cpuclk[cpu].cpu = cpu;
                cpuclk[cpu].reg_base = clock_complex_base;
index ed02bbc7b11f303a3d265003074ef022e545ddcf..abb47608713bc39a8fddbdf915f29955b10a497f 100644 (file)
@@ -716,6 +716,8 @@ static const char *const rk3188_critical_clocks[] __initconst = {
        "aclk_cpu",
        "aclk_peri",
        "hclk_peri",
+       "pclk_cpu",
+       "pclk_peri",
 };
 
 static void __init rk3188_common_clk_init(struct device_node *np)
@@ -744,8 +746,6 @@ static void __init rk3188_common_clk_init(struct device_node *np)
 
        rockchip_clk_register_branches(common_clk_branches,
                                  ARRAY_SIZE(common_clk_branches));
-       rockchip_clk_protect_critical(rk3188_critical_clocks,
-                                     ARRAY_SIZE(rk3188_critical_clocks));
 
        rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0),
                                  ROCKCHIP_SOFTRST_HIWORD_MASK);
@@ -765,6 +765,8 @@ static void __init rk3066a_clk_init(struct device_node *np)
                        mux_armclk_p, ARRAY_SIZE(mux_armclk_p),
                        &rk3066_cpuclk_data, rk3066_cpuclk_rates,
                        ARRAY_SIZE(rk3066_cpuclk_rates));
+       rockchip_clk_protect_critical(rk3188_critical_clocks,
+                                     ARRAY_SIZE(rk3188_critical_clocks));
 }
 CLK_OF_DECLARE(rk3066a_cru, "rockchip,rk3066a-cru", rk3066a_clk_init);
 
@@ -801,6 +803,9 @@ static void __init rk3188a_clk_init(struct device_node *np)
                pr_warn("%s: missing clocks to reparent aclk_cpu_pre to gpll\n",
                        __func__);
        }
+
+       rockchip_clk_protect_critical(rk3188_critical_clocks,
+                                     ARRAY_SIZE(rk3188_critical_clocks));
 }
 CLK_OF_DECLARE(rk3188a_cru, "rockchip,rk3188a-cru", rk3188a_clk_init);
 
index 9c5d61e698ef027fc129ab38a05d868e083b9407..7e6b783e6eee54c0fa53a85d664b5d2ddae6f819 100644 (file)
@@ -818,6 +818,10 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = {
        GATE(0, "sclk_timer00", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 0, GFLAGS),
 };
 
+static const char *const rk3368_critical_clocks[] __initconst = {
+       "pclk_pd_pmu",
+};
+
 static void __init rk3368_clk_init(struct device_node *np)
 {
        void __iomem *reg_base;
@@ -862,6 +866,8 @@ static void __init rk3368_clk_init(struct device_node *np)
                                   RK3368_GRF_SOC_STATUS0);
        rockchip_clk_register_branches(rk3368_clk_branches,
                                  ARRAY_SIZE(rk3368_clk_branches));
+       rockchip_clk_protect_critical(rk3368_critical_clocks,
+                                     ARRAY_SIZE(rk3368_critical_clocks));
 
        rockchip_clk_register_armclk(ARMCLKB, "armclkb",
                        mux_armclkb_p, ARRAY_SIZE(mux_armclkb_p),
index 7c1e1f58e2da2e7dc7909fce407bc477651add3a..2fe37f708dc70828ffa10fc165ecc830fff49c86 100644 (file)
@@ -164,7 +164,7 @@ static int exynos_cpuclk_pre_rate_change(struct clk_notifier_data *ndata,
         * the values for DIV_COPY and DIV_HPM dividers need not be set.
         */
        div0 = cfg_data->div0;
-       if (test_bit(CLK_CPU_HAS_DIV1, &cpuclk->flags)) {
+       if (cpuclk->flags & CLK_CPU_HAS_DIV1) {
                div1 = cfg_data->div1;
                if (readl(base + E4210_SRC_CPU) & E4210_MUX_HPM_MASK)
                        div1 = readl(base + E4210_DIV_CPU1) &
@@ -185,7 +185,7 @@ static int exynos_cpuclk_pre_rate_change(struct clk_notifier_data *ndata,
                alt_div = DIV_ROUND_UP(alt_prate, tmp_rate) - 1;
                WARN_ON(alt_div >= MAX_DIV);
 
-               if (test_bit(CLK_CPU_NEEDS_DEBUG_ALT_DIV, &cpuclk->flags)) {
+               if (cpuclk->flags & CLK_CPU_NEEDS_DEBUG_ALT_DIV) {
                        /*
                         * In Exynos4210, ATB clock parent is also mout_core. So
                         * ATB clock also needs to be mantained at safe speed.
@@ -206,7 +206,7 @@ static int exynos_cpuclk_pre_rate_change(struct clk_notifier_data *ndata,
        writel(div0, base + E4210_DIV_CPU0);
        wait_until_divider_stable(base + E4210_DIV_STAT_CPU0, DIV_MASK_ALL);
 
-       if (test_bit(CLK_CPU_HAS_DIV1, &cpuclk->flags)) {
+       if (cpuclk->flags & CLK_CPU_HAS_DIV1) {
                writel(div1, base + E4210_DIV_CPU1);
                wait_until_divider_stable(base + E4210_DIV_STAT_CPU1,
                                DIV_MASK_ALL);
@@ -225,7 +225,7 @@ static int exynos_cpuclk_post_rate_change(struct clk_notifier_data *ndata,
        unsigned long mux_reg;
 
        /* find out the divider values to use for clock data */
-       if (test_bit(CLK_CPU_NEEDS_DEBUG_ALT_DIV, &cpuclk->flags)) {
+       if (cpuclk->flags & CLK_CPU_NEEDS_DEBUG_ALT_DIV) {
                while ((cfg_data->prate * 1000) != ndata->new_rate) {
                        if (cfg_data->prate == 0)
                                return -EINVAL;
@@ -240,7 +240,7 @@ static int exynos_cpuclk_post_rate_change(struct clk_notifier_data *ndata,
        writel(mux_reg & ~(1 << 16), base + E4210_SRC_CPU);
        wait_until_mux_stable(base + E4210_STAT_CPU, 16, 1);
 
-       if (test_bit(CLK_CPU_NEEDS_DEBUG_ALT_DIV, &cpuclk->flags)) {
+       if (cpuclk->flags & CLK_CPU_NEEDS_DEBUG_ALT_DIV) {
                div |= (cfg_data->div0 & E4210_DIV0_ATB_MASK);
                div_mask |= E4210_DIV0_ATB_MASK;
        }
index 83ccf142ff2acaea7b5d4f3cf9d8f6475d1f6093..576cd0354d48237b807cb884f0ab64905641b1af 100644 (file)
@@ -307,7 +307,7 @@ static const struct clkgen_quadfs_data st_fs660c32_F_416 = {
        .get_rate       = clk_fs660c32_dig_get_rate,
 };
 
-static const struct clkgen_quadfs_data st_fs660c32_C_407 = {
+static const struct clkgen_quadfs_data st_fs660c32_C = {
        .nrst_present = true,
        .nrst   = { CLKGEN_FIELD(0x2f0, 0x1, 0),
                    CLKGEN_FIELD(0x2f0, 0x1, 1),
@@ -350,7 +350,7 @@ static const struct clkgen_quadfs_data st_fs660c32_C_407 = {
        .get_rate       = clk_fs660c32_dig_get_rate,
 };
 
-static const struct clkgen_quadfs_data st_fs660c32_D_407 = {
+static const struct clkgen_quadfs_data st_fs660c32_D = {
        .nrst_present = true,
        .nrst   = { CLKGEN_FIELD(0x2a0, 0x1, 0),
                    CLKGEN_FIELD(0x2a0, 0x1, 1),
@@ -1077,11 +1077,11 @@ static const struct of_device_id quadfs_of_match[] = {
        },
        {
                .compatible = "st,stih407-quadfs660-C",
-               .data = &st_fs660c32_C_407
+               .data = &st_fs660c32_C
        },
        {
                .compatible = "st,stih407-quadfs660-D",
-               .data = &st_fs660c32_D_407
+               .data = &st_fs660c32_D
        },
        {}
 };
index 47a38a994cac7a29113c086cb928e7957180e1fd..b2a332cf8985706574f89acc4d46d8fe17f2166c 100644 (file)
@@ -193,7 +193,7 @@ static const struct clkgen_pll_data st_pll3200c32_407_a0 = {
        .ops            = &stm_pll3200c32_ops,
 };
 
-static const struct clkgen_pll_data st_pll3200c32_407_c0_0 = {
+static const struct clkgen_pll_data st_pll3200c32_cx_0 = {
        /* 407 C0 PLL0 */
        .pdn_status     = CLKGEN_FIELD(0x2a0,   0x1,                    8),
        .locked_status  = CLKGEN_FIELD(0x2a0,   0x1,                    24),
@@ -205,7 +205,7 @@ static const struct clkgen_pll_data st_pll3200c32_407_c0_0 = {
        .ops            = &stm_pll3200c32_ops,
 };
 
-static const struct clkgen_pll_data st_pll3200c32_407_c0_1 = {
+static const struct clkgen_pll_data st_pll3200c32_cx_1 = {
        /* 407 C0 PLL1 */
        .pdn_status     = CLKGEN_FIELD(0x2c8,   0x1,                    8),
        .locked_status  = CLKGEN_FIELD(0x2c8,   0x1,                    24),
@@ -624,12 +624,12 @@ static const struct of_device_id c32_pll_of_match[] = {
                .data = &st_pll3200c32_407_a0,
        },
        {
-               .compatible = "st,stih407-plls-c32-c0_0",
-               .data = &st_pll3200c32_407_c0_0,
+               .compatible = "st,plls-c32-cx_0",
+               .data = &st_pll3200c32_cx_0,
        },
        {
-               .compatible = "st,stih407-plls-c32-c0_1",
-               .data = &st_pll3200c32_407_c0_1,
+               .compatible = "st,plls-c32-cx_1",
+               .data = &st_pll3200c32_cx_1,
        },
        {
                .compatible = "st,stih407-plls-c32-a9",
index c2ff859ee0e8be75ead40cdd0af59f331b79d7c8..c4e3a52e225bcea0583d3eed0308a523b12ebec3 100644 (file)
@@ -682,11 +682,17 @@ static int find_lut_index_for_rate(struct tegra_dfll *td, unsigned long rate)
        struct dev_pm_opp *opp;
        int i, uv;
 
+       rcu_read_lock();
+
        opp = dev_pm_opp_find_freq_ceil(td->soc->dev, &rate);
-       if (IS_ERR(opp))
+       if (IS_ERR(opp)) {
+               rcu_read_unlock();
                return PTR_ERR(opp);
+       }
        uv = dev_pm_opp_get_voltage(opp);
 
+       rcu_read_unlock();
+
        for (i = 0; i < td->i2c_lut_size; i++) {
                if (regulator_list_voltage(td->vdd_reg, td->i2c_lut[i]) == uv)
                        return i;
index 676ee8f6d8136729a9665cfb9c29e7faed123781..8831e1a05367ad9c7473e3ee723adc3f29dc9936 100644 (file)
@@ -374,7 +374,6 @@ static struct ti_dt_clk omap3xxx_clks[] = {
        DT_CLK(NULL, "gpio2_ick", "gpio2_ick"),
        DT_CLK(NULL, "wdt3_ick", "wdt3_ick"),
        DT_CLK(NULL, "uart3_ick", "uart3_ick"),
-       DT_CLK(NULL, "uart4_ick", "uart4_ick"),
        DT_CLK(NULL, "gpt9_ick", "gpt9_ick"),
        DT_CLK(NULL, "gpt8_ick", "gpt8_ick"),
        DT_CLK(NULL, "gpt7_ick", "gpt7_ick"),
@@ -519,6 +518,7 @@ static struct ti_dt_clk am35xx_clks[] = {
 static struct ti_dt_clk omap36xx_clks[] = {
        DT_CLK(NULL, "omap_192m_alwon_fck", "omap_192m_alwon_fck"),
        DT_CLK(NULL, "uart4_fck", "uart4_fck"),
+       DT_CLK(NULL, "uart4_ick", "uart4_ick"),
        { .node_name = NULL },
 };
 
index 9b5b289e633456206e81268d00bc212a7f9f62cc..a911d7de33778d7bc7648e59f0ee60c1a6c83027 100644 (file)
@@ -18,7 +18,6 @@
 
 #include "clock.h"
 
-#define DRA7_DPLL_ABE_DEFFREQ                          180633600
 #define DRA7_DPLL_GMAC_DEFFREQ                         1000000000
 #define DRA7_DPLL_USB_DEFFREQ                          960000000
 
@@ -313,27 +312,12 @@ static struct ti_dt_clk dra7xx_clks[] = {
 int __init dra7xx_dt_clk_init(void)
 {
        int rc;
-       struct clk *abe_dpll_mux, *sys_clkin2, *dpll_ck, *hdcp_ck;
+       struct clk *dpll_ck, *hdcp_ck;
 
        ti_dt_clocks_register(dra7xx_clks);
 
        omap2_clk_disable_autoidle_all();
 
-       abe_dpll_mux = clk_get_sys(NULL, "abe_dpll_sys_clk_mux");
-       sys_clkin2 = clk_get_sys(NULL, "sys_clkin2");
-       dpll_ck = clk_get_sys(NULL, "dpll_abe_ck");
-
-       rc = clk_set_parent(abe_dpll_mux, sys_clkin2);
-       if (!rc)
-               rc = clk_set_rate(dpll_ck, DRA7_DPLL_ABE_DEFFREQ);
-       if (rc)
-               pr_err("%s: failed to configure ABE DPLL!\n", __func__);
-
-       dpll_ck = clk_get_sys(NULL, "dpll_abe_m2x2_ck");
-       rc = clk_set_rate(dpll_ck, DRA7_DPLL_ABE_DEFFREQ * 2);
-       if (rc)
-               pr_err("%s: failed to configure ABE DPLL m2x2!\n", __func__);
-
        dpll_ck = clk_get_sys(NULL, "dpll_gmac_ck");
        rc = clk_set_rate(dpll_ck, DRA7_DPLL_GMAC_DEFFREQ);
        if (rc)
index 90d7d8a21c4918d52b910fab900e78acd68c5aad..1ddc288fce4eb123e63d941971bc94bff41f69a5 100644 (file)
@@ -222,7 +222,7 @@ int omap2_dflt_clk_enable(struct clk_hw *hw)
                }
        }
 
-       if (unlikely(!clk->enable_reg)) {
+       if (unlikely(IS_ERR(clk->enable_reg))) {
                pr_err("%s: %s missing enable_reg\n", __func__,
                       clk_hw_get_name(hw));
                ret = -EINVAL;
@@ -264,7 +264,7 @@ void omap2_dflt_clk_disable(struct clk_hw *hw)
        u32 v;
 
        clk = to_clk_hw_omap(hw);
-       if (!clk->enable_reg) {
+       if (IS_ERR(clk->enable_reg)) {
                /*
                 * 'independent' here refers to a clock which is not
                 * controlled by its parent.
index 29ea50ac366ab9c9399951286beb3ff09984d68c..a2cb6fae92958b7319c55ee20ef21e26268ffbea 100644 (file)
@@ -60,7 +60,7 @@ static struct clock_event_device __percpu *gt_evt;
  *  different to the 32-bit upper value read previously, go back to step 2.
  *  Otherwise the 64-bit timer counter value is correct.
  */
-static u64 gt_counter_read(void)
+static u64 notrace _gt_counter_read(void)
 {
        u64 counter;
        u32 lower;
@@ -79,6 +79,11 @@ static u64 gt_counter_read(void)
        return counter;
 }
 
+static u64 gt_counter_read(void)
+{
+       return _gt_counter_read();
+}
+
 /**
  * To ensure that updates to comparator value register do not set the
  * Interrupt Status Register proceed as follows:
@@ -201,7 +206,7 @@ static struct clocksource gt_clocksource = {
 #ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
 static u64 notrace gt_sched_clock_read(void)
 {
-       return gt_counter_read();
+       return _gt_counter_read();
 }
 #endif
 
index ef434699c80a090ee1bbb0de41b38170bddc188b..10202f1fdfd7b2afc6ccf9cd044cecdc2d3d66a7 100644 (file)
@@ -118,7 +118,7 @@ static inline void ftm_reset_counter(void __iomem *base)
        ftm_writel(0x00, base + FTM_CNT);
 }
 
-static u64 ftm_read_sched_clock(void)
+static u64 notrace ftm_read_sched_clock(void)
 {
        return ftm_readl(priv->clksrc_base + FTM_CNT);
 }
index bb2c2b05096455066826a13d5ad1156248f5e64e..d3c1742ded1af7655c3e2e77031ab3801ea84761 100644 (file)
@@ -148,7 +148,7 @@ static void __init rk_timer_init(struct device_node *np)
        bc_timer.freq = clk_get_rate(timer_clk);
 
        irq = irq_of_parse_and_map(np, 0);
-       if (irq == NO_IRQ) {
+       if (!irq) {
                pr_err("Failed to map interrupts for '%s'\n", TIMER_NAME);
                return;
        }
index bc90e13338cc6e961d3d3e4c4bdc611c2dd05436..9502bc4c3f6d9a17ec7616bf743c5bfc26c3f638 100644 (file)
@@ -307,7 +307,7 @@ static void samsung_clocksource_resume(struct clocksource *cs)
        samsung_time_start(pwm.source_id, true);
 }
 
-static cycle_t samsung_clocksource_read(struct clocksource *c)
+static cycle_t notrace samsung_clocksource_read(struct clocksource *c)
 {
        return ~readl_relaxed(pwm.source_reg);
 }
index f1985da8113f481fb870c4b91eeef62b962300ad..53aa7e92a7d77b7efc052466e8904efc110cc2eb 100644 (file)
@@ -280,7 +280,9 @@ static int sh_mtu2_clock_event_shutdown(struct clock_event_device *ced)
 {
        struct sh_mtu2_channel *ch = ced_to_sh_mtu2(ced);
 
-       sh_mtu2_disable(ch);
+       if (clockevent_state_periodic(ced))
+               sh_mtu2_disable(ch);
+
        return 0;
 }
 
index 18d4266c2986c65d1f2d3cd55e0d4986dfb9b4d6..bba6799000541d360081b41e4e87ee8d9bf7596a 100644 (file)
@@ -67,7 +67,8 @@ static inline void gpt_writel(void __iomem *base, u32 value, u32 offset,
        writel(value, base + 0x20 * gpt_id + offset);
 }
 
-static cycle_t pistachio_clocksource_read_cycles(struct clocksource *cs)
+static cycle_t notrace
+pistachio_clocksource_read_cycles(struct clocksource *cs)
 {
        struct pistachio_clocksource *pcs = to_pistachio_clocksource(cs);
        u32 counter, overflw;
index e73947f0f86db3c1b9656c9b3418c9151f7f2954..a536eeb634d885fccf5b92f0d0cbeeec7f88baf2 100644 (file)
@@ -143,7 +143,7 @@ static irqreturn_t digicolor_timer_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static u64 digicolor_timer_sched_read(void)
+static u64 notrace digicolor_timer_sched_read(void)
 {
        return ~readl(dc_timer_dev.base + COUNT(TIMER_B));
 }
index edacf3902e107d9ac60c84cdaba4f4ad1822213c..1cea08cf603eb30d5028e157dc8927aef4a004a9 100644 (file)
@@ -152,7 +152,7 @@ static void __init keystone_timer_init(struct device_node *np)
        int irq, error;
 
        irq  = irq_of_parse_and_map(np, 0);
-       if (irq == NO_IRQ) {
+       if (!irq) {
                pr_err("%s: failed to map interrupts\n", __func__);
                return;
        }
index 78de982cc640bd93a5ea9b834e9c7049061a24a2..2854c663e8b5b978ae463d1d96c218c79da77a5e 100644 (file)
@@ -73,7 +73,7 @@ static irqreturn_t sirfsoc_timer_interrupt(int irq, void *dev_id)
 }
 
 /* read 64-bit timer counter */
-static cycle_t sirfsoc_timer_read(struct clocksource *cs)
+static cycle_t notrace sirfsoc_timer_read(struct clocksource *cs)
 {
        u64 cycles;
 
index f07ba99321716c02628affeafca70100642a1df2..a0e6c68536a18d8dbc76eb7f239bea31ca24240f 100644 (file)
@@ -52,7 +52,7 @@ static inline void pit_irq_acknowledge(void)
        __raw_writel(PITTFLG_TIF, clkevt_base + PITTFLG);
 }
 
-static u64 pit_read_sched_clock(void)
+static u64 notrace pit_read_sched_clock(void)
 {
        return ~__raw_readl(clksrc_base + PITCVAL);
 }
index 15b921a9248c8f7b0e90bb01fe41d06c32e898bc..cec1ee2d2f744b968fe653f47dc5067dfe4dccb1 100644 (file)
@@ -149,6 +149,9 @@ static ssize_t show_freqdomain_cpus(struct cpufreq_policy *policy, char *buf)
 {
        struct acpi_cpufreq_data *data = policy->driver_data;
 
+       if (unlikely(!data))
+               return -ENODEV;
+
        return cpufreq_show_cpus(data->freqdomain_cpus, buf);
 }
 
@@ -375,12 +378,11 @@ static unsigned int get_cur_freq_on_cpu(unsigned int cpu)
 
        pr_debug("get_cur_freq_on_cpu (%d)\n", cpu);
 
-       policy = cpufreq_cpu_get(cpu);
+       policy = cpufreq_cpu_get_raw(cpu);
        if (unlikely(!policy))
                return 0;
 
        data = policy->driver_data;
-       cpufreq_cpu_put(policy);
        if (unlikely(!data || !data->freq_table))
                return 0;
 
index 6633b3fa996e06091089297f05e5bb710b995134..25c4c15103a0cd8759e006eaa10d9f9edbfb5872 100644 (file)
@@ -238,13 +238,13 @@ int cpufreq_generic_init(struct cpufreq_policy *policy,
 }
 EXPORT_SYMBOL_GPL(cpufreq_generic_init);
 
-/* Only for cpufreq core internal use */
-static struct cpufreq_policy *cpufreq_cpu_get_raw(unsigned int cpu)
+struct cpufreq_policy *cpufreq_cpu_get_raw(unsigned int cpu)
 {
        struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu);
 
        return policy && cpumask_test_cpu(cpu, policy->cpus) ? policy : NULL;
 }
+EXPORT_SYMBOL_GPL(cpufreq_cpu_get_raw);
 
 unsigned int cpufreq_generic_get(unsigned int cpu)
 {
@@ -1436,8 +1436,10 @@ static void cpufreq_offline_finish(unsigned int cpu)
         * since this is a core component, and is essential for the
         * subsequent light-weight ->init() to succeed.
         */
-       if (cpufreq_driver->exit)
+       if (cpufreq_driver->exit) {
                cpufreq_driver->exit(policy);
+               policy->freq_table = NULL;
+       }
 }
 
 /**
index 3af9dd7332e6927d8dd860b5af410fba738bff4a..aa33b92b3e3e8866345e9893e3b0a880b8b1a17a 100644 (file)
@@ -776,6 +776,11 @@ static inline void intel_pstate_sample(struct cpudata *cpu)
        local_irq_save(flags);
        rdmsrl(MSR_IA32_APERF, aperf);
        rdmsrl(MSR_IA32_MPERF, mperf);
+       if (cpu->prev_mperf == mperf) {
+               local_irq_restore(flags);
+               return;
+       }
+
        tsc = rdtsc();
        local_irq_restore(flags);
 
index 07bc7aa6b224aeeb7ada29b08aec61966d3b3b2e..d234719065a5f2e39c3e81681dc0bd184e803033 100644 (file)
@@ -461,7 +461,7 @@ config CRYPTO_DEV_QCE
 
 config CRYPTO_DEV_VMX
        bool "Support for VMX cryptographic acceleration instructions"
-       depends on PPC64
+       depends on PPC64 && VSX
        help
          Support for VMX cryptographic acceleration instructions.
 
index b60698b30d30a2e30b24b3cc625a9821254fc980..bc2a55bc35e4727290319b462008c695b7e2923e 100644 (file)
@@ -687,6 +687,33 @@ static inline u32 mv_cesa_get_int_mask(struct mv_cesa_engine *engine)
 
 int mv_cesa_queue_req(struct crypto_async_request *req);
 
+/*
+ * Helper function that indicates whether a crypto request needs to be
+ * cleaned up or not after being enqueued using mv_cesa_queue_req().
+ */
+static inline int mv_cesa_req_needs_cleanup(struct crypto_async_request *req,
+                                           int ret)
+{
+       /*
+        * The queue still had some space, the request was queued
+        * normally, so there's no need to clean it up.
+        */
+       if (ret == -EINPROGRESS)
+               return false;
+
+       /*
+        * The queue had not space left, but since the request is
+        * flagged with CRYPTO_TFM_REQ_MAY_BACKLOG, it was added to
+        * the backlog and will be processed later. There's no need to
+        * clean it up.
+        */
+       if (ret == -EBUSY && req->flags & CRYPTO_TFM_REQ_MAY_BACKLOG)
+               return false;
+
+       /* Request wasn't queued, we need to clean it up */
+       return true;
+}
+
 /* TDMA functions */
 
 static inline void mv_cesa_req_dma_iter_init(struct mv_cesa_dma_iter *iter,
index 0745cf3b9c0e43de808270b396cb8c1ff06a821d..3df2f4e7adb29a681f18a4f77acdf9df2f5e411b 100644 (file)
@@ -189,7 +189,6 @@ static inline void mv_cesa_ablkcipher_prepare(struct crypto_async_request *req,
 {
        struct ablkcipher_request *ablkreq = ablkcipher_request_cast(req);
        struct mv_cesa_ablkcipher_req *creq = ablkcipher_request_ctx(ablkreq);
-
        creq->req.base.engine = engine;
 
        if (creq->req.base.type == CESA_DMA_REQ)
@@ -431,7 +430,7 @@ static int mv_cesa_des_op(struct ablkcipher_request *req,
                return ret;
 
        ret = mv_cesa_queue_req(&req->base);
-       if (ret && ret != -EINPROGRESS)
+       if (mv_cesa_req_needs_cleanup(&req->base, ret))
                mv_cesa_ablkcipher_cleanup(req);
 
        return ret;
@@ -551,7 +550,7 @@ static int mv_cesa_des3_op(struct ablkcipher_request *req,
                return ret;
 
        ret = mv_cesa_queue_req(&req->base);
-       if (ret && ret != -EINPROGRESS)
+       if (mv_cesa_req_needs_cleanup(&req->base, ret))
                mv_cesa_ablkcipher_cleanup(req);
 
        return ret;
@@ -693,7 +692,7 @@ static int mv_cesa_aes_op(struct ablkcipher_request *req,
                return ret;
 
        ret = mv_cesa_queue_req(&req->base);
-       if (ret && ret != -EINPROGRESS)
+       if (mv_cesa_req_needs_cleanup(&req->base, ret))
                mv_cesa_ablkcipher_cleanup(req);
 
        return ret;
index ae9272eb9c1ac23ce7461a82ffd165c711d1886f..e8d0d712813746bd9360f4726e8cffb18110ae02 100644 (file)
@@ -739,10 +739,8 @@ static int mv_cesa_ahash_update(struct ahash_request *req)
                return 0;
 
        ret = mv_cesa_queue_req(&req->base);
-       if (ret && ret != -EINPROGRESS) {
+       if (mv_cesa_req_needs_cleanup(&req->base, ret))
                mv_cesa_ahash_cleanup(req);
-               return ret;
-       }
 
        return ret;
 }
@@ -766,7 +764,7 @@ static int mv_cesa_ahash_final(struct ahash_request *req)
                return 0;
 
        ret = mv_cesa_queue_req(&req->base);
-       if (ret && ret != -EINPROGRESS)
+       if (mv_cesa_req_needs_cleanup(&req->base, ret))
                mv_cesa_ahash_cleanup(req);
 
        return ret;
@@ -791,7 +789,7 @@ static int mv_cesa_ahash_finup(struct ahash_request *req)
                return 0;
 
        ret = mv_cesa_queue_req(&req->base);
-       if (ret && ret != -EINPROGRESS)
+       if (mv_cesa_req_needs_cleanup(&req->base, ret))
                mv_cesa_ahash_cleanup(req);
 
        return ret;
index a57b4194de2845aaee3eb77d9e7bd268cf63184f..0a5ca0ba5d64c88974da25ab9b19050cb07fe77f 100644 (file)
@@ -88,6 +88,9 @@ static void adf_dev_restore(struct adf_accel_dev *accel_dev)
        struct pci_dev *parent = pdev->bus->self;
        uint16_t bridge_ctl = 0;
 
+       if (accel_dev->is_vf)
+               return;
+
        dev_info(&GET_DEV(accel_dev), "Resetting device qat_dev%d\n",
                 accel_dev->accel_id);
 
index e070c316e8b76a7384efa33a6a34ec99fb9a8849..a19ee127edcafd3c70ad9e6ee8a86b1823f020f7 100644 (file)
@@ -104,7 +104,7 @@ static int sun4i_ss_opti_poll(struct ablkcipher_request *areq)
                        sg_miter_next(&mo);
                        oo = 0;
                }
-       } while (mo.length > 0);
+       } while (oleft > 0);
 
        if (areq->info) {
                for (i = 0; i < 4 && i < ivsize / 4; i++) {
index ca1b362d77e2329c9b6c0d511f754fdf839da095..ca848cc6a8fd1313bc56e5b93674b3d795814779 100644 (file)
@@ -53,7 +53,7 @@ static struct devfreq *find_device_devfreq(struct device *dev)
 {
        struct devfreq *tmp_devfreq;
 
-       if (unlikely(IS_ERR_OR_NULL(dev))) {
+       if (IS_ERR_OR_NULL(dev)) {
                pr_err("DEVFREQ: %s: Invalid parameters\n", __func__);
                return ERR_PTR(-EINVAL);
        }
@@ -133,7 +133,7 @@ static struct devfreq_governor *find_devfreq_governor(const char *name)
 {
        struct devfreq_governor *tmp_governor;
 
-       if (unlikely(IS_ERR_OR_NULL(name))) {
+       if (IS_ERR_OR_NULL(name)) {
                pr_err("DEVFREQ: %s: Invalid parameters\n", __func__);
                return ERR_PTR(-EINVAL);
        }
@@ -177,10 +177,10 @@ int update_devfreq(struct devfreq *devfreq)
                return err;
 
        /*
-        * Adjust the freuqency with user freq and QoS.
+        * Adjust the frequency with user freq and QoS.
         *
-        * List from the highest proiority
-        * max_freq (probably called by thermal when it's too hot)
+        * List from the highest priority
+        * max_freq
         * min_freq
         */
 
@@ -482,7 +482,7 @@ struct devfreq *devfreq_add_device(struct device *dev,
                                                devfreq->profile->max_state *
                                                devfreq->profile->max_state,
                                                GFP_KERNEL);
-       devfreq->time_in_state = devm_kzalloc(dev, sizeof(unsigned int) *
+       devfreq->time_in_state = devm_kzalloc(dev, sizeof(unsigned long) *
                                                devfreq->profile->max_state,
                                                GFP_KERNEL);
        devfreq->last_stat_updated = jiffies;
@@ -492,7 +492,7 @@ struct devfreq *devfreq_add_device(struct device *dev,
        if (err) {
                put_device(&devfreq->dev);
                mutex_unlock(&devfreq->lock);
-               goto err_dev;
+               goto err_out;
        }
 
        mutex_unlock(&devfreq->lock);
@@ -518,7 +518,6 @@ struct devfreq *devfreq_add_device(struct device *dev,
 err_init:
        list_del(&devfreq->node);
        device_unregister(&devfreq->dev);
-err_dev:
        kfree(devfreq);
 err_out:
        return ERR_PTR(err);
@@ -795,8 +794,10 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
                ret = PTR_ERR(governor);
                goto out;
        }
-       if (df->governor == governor)
+       if (df->governor == governor) {
+               ret = 0;
                goto out;
+       }
 
        if (df->governor) {
                ret = df->governor->event_handler(df, DEVFREQ_GOV_STOP, NULL);
index f9901f52a225ca40e8d87056c1021c134838efe3..f312485f145110ab31537f9df3225e8ac1021cf8 100644 (file)
@@ -319,7 +319,8 @@ static int exynos_ppmu_v2_get_event(struct devfreq_event_dev *edev,
        case PPMU_PMNCNT3:
                pmcnt_high = __raw_readl(info->ppmu.base + PPMU_V2_PMCNT3_HIGH);
                pmcnt_low = __raw_readl(info->ppmu.base + PPMU_V2_PMCNT3_LOW);
-               load_count = (u64)((pmcnt_high & 0xff) << 32) + (u64)pmcnt_low;
+               load_count = ((u64)((pmcnt_high & 0xff)) << 32)
+                          + (u64)pmcnt_low;
                break;
        }
        edata->load_count = load_count;
index 0720ba84ca9277df895168a788cae9d3d41bc40b..ae72ba5e78dfce046804a7dc5b7a08017d8a25c7 100644 (file)
 static int devfreq_simple_ondemand_func(struct devfreq *df,
                                        unsigned long *freq)
 {
-       struct devfreq_dev_status stat;
-       int err = df->profile->get_dev_status(df->dev.parent, &stat);
+       int err;
+       struct devfreq_dev_status *stat;
        unsigned long long a, b;
        unsigned int dfso_upthreshold = DFSO_UPTHRESHOLD;
        unsigned int dfso_downdifferential = DFSO_DOWNDIFFERENCTIAL;
        struct devfreq_simple_ondemand_data *data = df->data;
        unsigned long max = (df->max_freq) ? df->max_freq : UINT_MAX;
 
+       err = devfreq_update_stats(df);
        if (err)
                return err;
 
+       stat = &df->last_status;
+
        if (data) {
                if (data->upthreshold)
                        dfso_upthreshold = data->upthreshold;
@@ -43,41 +46,41 @@ static int devfreq_simple_ondemand_func(struct devfreq *df,
                return -EINVAL;
 
        /* Assume MAX if it is going to be divided by zero */
-       if (stat.total_time == 0) {
+       if (stat->total_time == 0) {
                *freq = max;
                return 0;
        }
 
        /* Prevent overflow */
-       if (stat.busy_time >= (1 << 24) || stat.total_time >= (1 << 24)) {
-               stat.busy_time >>= 7;
-               stat.total_time >>= 7;
+       if (stat->busy_time >= (1 << 24) || stat->total_time >= (1 << 24)) {
+               stat->busy_time >>= 7;
+               stat->total_time >>= 7;
        }
 
        /* Set MAX if it's busy enough */
-       if (stat.busy_time * 100 >
-           stat.total_time * dfso_upthreshold) {
+       if (stat->busy_time * 100 >
+           stat->total_time * dfso_upthreshold) {
                *freq = max;
                return 0;
        }
 
        /* Set MAX if we do not know the initial frequency */
-       if (stat.current_frequency == 0) {
+       if (stat->current_frequency == 0) {
                *freq = max;
                return 0;
        }
 
        /* Keep the current frequency */
-       if (stat.busy_time * 100 >
-           stat.total_time * (dfso_upthreshold - dfso_downdifferential)) {
-               *freq = stat.current_frequency;
+       if (stat->busy_time * 100 >
+           stat->total_time * (dfso_upthreshold - dfso_downdifferential)) {
+               *freq = stat->current_frequency;
                return 0;
        }
 
        /* Set the desired frequency based on the load */
-       a = stat.busy_time;
-       a *= stat.current_frequency;
-       b = div_u64(a, stat.total_time);
+       a = stat->busy_time;
+       a *= stat->current_frequency;
+       b = div_u64(a, stat->total_time);
        b *= 100;
        b = div_u64(b, (dfso_upthreshold - dfso_downdifferential / 2));
        *freq = (unsigned long) b;
index 13a1a6e8108c87e5b8c7653118c1d7798b4c6ac8..848b93ee930fd8ec204a332755c57b18457bfede 100644 (file)
@@ -541,18 +541,20 @@ static struct devfreq_dev_profile tegra_devfreq_profile = {
 static int tegra_governor_get_target(struct devfreq *devfreq,
                                     unsigned long *freq)
 {
-       struct devfreq_dev_status stat;
+       struct devfreq_dev_status *stat;
        struct tegra_devfreq *tegra;
        struct tegra_devfreq_device *dev;
        unsigned long target_freq = 0;
        unsigned int i;
        int err;
 
-       err = devfreq->profile->get_dev_status(devfreq->dev.parent, &stat);
+       err = devfreq_update_stats(devfreq);
        if (err)
                return err;
 
-       tegra = stat.private_data;
+       stat = &devfreq->last_status;
+
+       tegra = stat->private_data;
 
        for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) {
                dev = &tegra->devices[i];
index a165b4bfd3300e97d409f2053b71adb276392336..dd24375b76ddcba72409d3c5c1285f19c172a45f 100644 (file)
@@ -455,6 +455,15 @@ static struct at_xdmac_desc *at_xdmac_alloc_desc(struct dma_chan *chan,
        return desc;
 }
 
+void at_xdmac_init_used_desc(struct at_xdmac_desc *desc)
+{
+       memset(&desc->lld, 0, sizeof(desc->lld));
+       INIT_LIST_HEAD(&desc->descs_list);
+       desc->direction = DMA_TRANS_NONE;
+       desc->xfer_size = 0;
+       desc->active_xfer = false;
+}
+
 /* Call must be protected by lock. */
 static struct at_xdmac_desc *at_xdmac_get_desc(struct at_xdmac_chan *atchan)
 {
@@ -466,7 +475,7 @@ static struct at_xdmac_desc *at_xdmac_get_desc(struct at_xdmac_chan *atchan)
                desc = list_first_entry(&atchan->free_descs_list,
                                        struct at_xdmac_desc, desc_node);
                list_del(&desc->desc_node);
-               desc->active_xfer = false;
+               at_xdmac_init_used_desc(desc);
        }
 
        return desc;
@@ -875,14 +884,14 @@ at_xdmac_interleaved_queue_desc(struct dma_chan *chan,
 
        if (xt->src_inc) {
                if (xt->src_sgl)
-                       chan_cc |=  AT_XDMAC_CC_SAM_UBS_DS_AM;
+                       chan_cc |=  AT_XDMAC_CC_SAM_UBS_AM;
                else
                        chan_cc |=  AT_XDMAC_CC_SAM_INCREMENTED_AM;
        }
 
        if (xt->dst_inc) {
                if (xt->dst_sgl)
-                       chan_cc |=  AT_XDMAC_CC_DAM_UBS_DS_AM;
+                       chan_cc |=  AT_XDMAC_CC_DAM_UBS_AM;
                else
                        chan_cc |=  AT_XDMAC_CC_DAM_INCREMENTED_AM;
        }
index 3ff284c8e3d5aef72f229017c883c73cbe13403f..09479d4be4db3d776fd1f3400724d13f26808428 100644 (file)
@@ -554,10 +554,18 @@ struct dma_chan *dma_get_slave_channel(struct dma_chan *chan)
        mutex_lock(&dma_list_mutex);
 
        if (chan->client_count == 0) {
+               struct dma_device *device = chan->device;
+
+               dma_cap_set(DMA_PRIVATE, device->cap_mask);
+               device->privatecnt++;
                err = dma_chan_get(chan);
-               if (err)
+               if (err) {
                        pr_debug("%s: failed to get %s: (%d)\n",
                                __func__, dma_chan_name(chan), err);
+                       chan = NULL;
+                       if (--device->privatecnt == 0)
+                               dma_cap_clear(DMA_PRIVATE, device->cap_mask);
+               }
        } else
                chan = NULL;
 
index cf1c87fa1edd557eb57f53dd41c11c02a440ea82..bedce038c6e281bb1e1bf6ba89585c14d532a5b2 100644 (file)
@@ -1591,7 +1591,6 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata)
        INIT_LIST_HEAD(&dw->dma.channels);
        for (i = 0; i < nr_channels; i++) {
                struct dw_dma_chan      *dwc = &dw->chan[i];
-               int                     r = nr_channels - i - 1;
 
                dwc->chan.device = &dw->dma;
                dma_cookie_init(&dwc->chan);
@@ -1603,7 +1602,7 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata)
 
                /* 7 is highest priority & 0 is lowest. */
                if (pdata->chan_priority == CHAN_PRIORITY_ASCENDING)
-                       dwc->priority = r;
+                       dwc->priority = nr_channels - i - 1;
                else
                        dwc->priority = i;
 
@@ -1622,6 +1621,7 @@ int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata)
                /* Hardware configuration */
                if (autocfg) {
                        unsigned int dwc_params;
+                       unsigned int r = DW_DMA_MAX_NR_CHANNELS - i - 1;
                        void __iomem *addr = chip->regs + r * sizeof(u32);
 
                        dwc_params = dma_read_byaddr(addr, DWC_PARAMS);
index 18c14e1f1414e650969ff3c9e34431072b3abd83..48d6d9e94f6763c91bcf069848d9ef13e2eed48d 100644 (file)
@@ -355,23 +355,23 @@ static size_t idma64_active_desc_size(struct idma64_chan *idma64c)
        struct idma64_desc *desc = idma64c->desc;
        struct idma64_hw_desc *hw;
        size_t bytes = desc->length;
-       u64 llp;
-       u32 ctlhi;
+       u64 llp = channel_readq(idma64c, LLP);
+       u32 ctlhi = channel_readl(idma64c, CTL_HI);
        unsigned int i = 0;
 
-       llp = channel_readq(idma64c, LLP);
        do {
                hw = &desc->hw[i];
-       } while ((hw->llp != llp) && (++i < desc->ndesc));
+               if (hw->llp == llp)
+                       break;
+               bytes -= hw->len;
+       } while (++i < desc->ndesc);
 
        if (!i)
                return bytes;
 
-       do {
-               bytes -= desc->hw[--i].len;
-       } while (i);
+       /* The current chunk is not fully transfered yet */
+       bytes += desc->hw[--i].len;
 
-       ctlhi = channel_readl(idma64c, CTL_HI);
        return bytes - IDMA64C_CTLH_BLOCK_TS(ctlhi);
 }
 
index 4768a829253a5438a38e00b5be2eedc02af71fea..2bf37e68ad0f1529e472a141031d56586ac21e21 100644 (file)
@@ -266,7 +266,7 @@ int ipu_irq_unmap(unsigned int source)
 }
 
 /* Chained IRQ handler for IPU function and error interrupt */
-static void ipu_irq_handler(unsigned int __irq, struct irq_desc *desc)
+static void ipu_irq_handler(struct irq_desc *desc)
 {
        struct ipu *ipu = irq_desc_get_handler_data(desc);
        u32 status;
index 5cb61ce01036fef2dc5248d11f99859e2dcb9d86..fc4156afa070306cd2fee4502f361717f364706b 100644 (file)
@@ -473,8 +473,10 @@ static void pxad_free_phy(struct pxad_chan *chan)
                return;
 
        /* clear the channel mapping in DRCMR */
-       reg = pxad_drcmr(chan->drcmr);
-       writel_relaxed(0, chan->phy->base + reg);
+       if (chan->drcmr <= DRCMR_CHLNUM) {
+               reg = pxad_drcmr(chan->drcmr);
+               writel_relaxed(0, chan->phy->base + reg);
+       }
 
        spin_lock_irqsave(&pdev->phy_lock, flags);
        for (i = 0; i < 32; i++)
@@ -516,8 +518,10 @@ static void phy_enable(struct pxad_phy *phy, bool misaligned)
                "%s(); phy=%p(%d) misaligned=%d\n", __func__,
                phy, phy->idx, misaligned);
 
-       reg = pxad_drcmr(phy->vchan->drcmr);
-       writel_relaxed(DRCMR_MAPVLD | phy->idx, phy->base + reg);
+       if (phy->vchan->drcmr <= DRCMR_CHLNUM) {
+               reg = pxad_drcmr(phy->vchan->drcmr);
+               writel_relaxed(DRCMR_MAPVLD | phy->idx, phy->base + reg);
+       }
 
        dalgn = phy_readl_relaxed(phy, DALGN);
        if (misaligned)
@@ -887,6 +891,7 @@ pxad_tx_prep(struct virt_dma_chan *vc, struct virt_dma_desc *vd,
        struct dma_async_tx_descriptor *tx;
        struct pxad_chan *chan = container_of(vc, struct pxad_chan, vc);
 
+       INIT_LIST_HEAD(&vd->node);
        tx = vchan_tx_prep(vc, vd, tx_flags);
        tx->tx_submit = pxad_tx_submit;
        dev_dbg(&chan->vc.chan.dev->device,
@@ -910,14 +915,18 @@ static void pxad_get_config(struct pxad_chan *chan,
                width = chan->cfg.src_addr_width;
                dev_addr = chan->cfg.src_addr;
                *dev_src = dev_addr;
-               *dcmd |= PXA_DCMD_INCTRGADDR | PXA_DCMD_FLOWSRC;
+               *dcmd |= PXA_DCMD_INCTRGADDR;
+               if (chan->drcmr <= DRCMR_CHLNUM)
+                       *dcmd |= PXA_DCMD_FLOWSRC;
        }
        if (dir == DMA_MEM_TO_DEV) {
                maxburst = chan->cfg.dst_maxburst;
                width = chan->cfg.dst_addr_width;
                dev_addr = chan->cfg.dst_addr;
                *dev_dst = dev_addr;
-               *dcmd |= PXA_DCMD_INCSRCADDR | PXA_DCMD_FLOWTRG;
+               *dcmd |= PXA_DCMD_INCSRCADDR;
+               if (chan->drcmr <= DRCMR_CHLNUM)
+                       *dcmd |= PXA_DCMD_FLOWTRG;
        }
        if (dir == DMA_MEM_TO_MEM)
                *dcmd |= PXA_DCMD_BURST32 | PXA_DCMD_INCTRGADDR |
@@ -1177,6 +1186,16 @@ static unsigned int pxad_residue(struct pxad_chan *chan,
        else
                curr = phy_readl_relaxed(chan->phy, DTADR);
 
+       /*
+        * curr has to be actually read before checking descriptor
+        * completion, so that a curr inside a status updater
+        * descriptor implies the following test returns true, and
+        * preventing reordering of curr load and the test.
+        */
+       rmb();
+       if (is_desc_completed(vd))
+               goto out;
+
        for (i = 0; i < sw_desc->nb_desc - 1; i++) {
                hw_desc = sw_desc->hw_desc[i];
                if (sw_desc->hw_desc[0]->dcmd & PXA_DCMD_INCSRCADDR)
index a1a500d96ff2788db7355a65284a9a3b54c0a1e0..1661d518224a7e4e57ca6c8c717096b5a87333e1 100644 (file)
@@ -599,13 +599,13 @@ get_next_cyclic_promise(struct sun4i_dma_contract *contract)
 static void sun4i_dma_free_contract(struct virt_dma_desc *vd)
 {
        struct sun4i_dma_contract *contract = to_sun4i_dma_contract(vd);
-       struct sun4i_dma_promise *promise;
+       struct sun4i_dma_promise *promise, *tmp;
 
        /* Free all the demands and completed demands */
-       list_for_each_entry(promise, &contract->demands, list)
+       list_for_each_entry_safe(promise, tmp, &contract->demands, list)
                kfree(promise);
 
-       list_for_each_entry(promise, &contract->completed_demands, list)
+       list_for_each_entry_safe(promise, tmp, &contract->completed_demands, list)
                kfree(promise);
 
        kfree(contract);
index b23e8d52d1263abc11cc126e9e0b80e1dcc5cc1b..8d57b1b12e411ef902d26af984e7d34a741a4cf2 100644 (file)
@@ -59,7 +59,6 @@
 #define XGENE_DMA_RING_MEM_RAM_SHUTDOWN                0xD070
 #define XGENE_DMA_RING_BLK_MEM_RDY             0xD074
 #define XGENE_DMA_RING_BLK_MEM_RDY_VAL         0xFFFFFFFF
-#define XGENE_DMA_RING_DESC_CNT(v)             (((v) & 0x0001FFFE) >> 1)
 #define XGENE_DMA_RING_ID_GET(owner, num)      (((owner) << 6) | (num))
 #define XGENE_DMA_RING_DST_ID(v)               ((1 << 10) | (v))
 #define XGENE_DMA_RING_CMD_OFFSET              0x2C
@@ -379,14 +378,6 @@ static u8 xgene_dma_encode_xor_flyby(u32 src_cnt)
        return flyby_type[src_cnt];
 }
 
-static u32 xgene_dma_ring_desc_cnt(struct xgene_dma_ring *ring)
-{
-       u32 __iomem *cmd_base = ring->cmd_base;
-       u32 ring_state = ioread32(&cmd_base[1]);
-
-       return XGENE_DMA_RING_DESC_CNT(ring_state);
-}
-
 static void xgene_dma_set_src_buffer(__le64 *ext8, size_t *len,
                                     dma_addr_t *paddr)
 {
@@ -659,15 +650,12 @@ static void xgene_dma_clean_running_descriptor(struct xgene_dma_chan *chan,
        dma_pool_free(chan->desc_pool, desc, desc->tx.phys);
 }
 
-static int xgene_chan_xfer_request(struct xgene_dma_ring *ring,
-                                  struct xgene_dma_desc_sw *desc_sw)
+static void xgene_chan_xfer_request(struct xgene_dma_chan *chan,
+                                   struct xgene_dma_desc_sw *desc_sw)
 {
+       struct xgene_dma_ring *ring = &chan->tx_ring;
        struct xgene_dma_desc_hw *desc_hw;
 
-       /* Check if can push more descriptor to hw for execution */
-       if (xgene_dma_ring_desc_cnt(ring) > (ring->slots - 2))
-               return -EBUSY;
-
        /* Get hw descriptor from DMA tx ring */
        desc_hw = &ring->desc_hw[ring->head];
 
@@ -694,11 +682,13 @@ static int xgene_chan_xfer_request(struct xgene_dma_ring *ring,
                memcpy(desc_hw, &desc_sw->desc2, sizeof(*desc_hw));
        }
 
+       /* Increment the pending transaction count */
+       chan->pending += ((desc_sw->flags &
+                         XGENE_DMA_FLAG_64B_DESC) ? 2 : 1);
+
        /* Notify the hw that we have descriptor ready for execution */
        iowrite32((desc_sw->flags & XGENE_DMA_FLAG_64B_DESC) ?
                  2 : 1, ring->cmd);
-
-       return 0;
 }
 
 /**
@@ -710,7 +700,6 @@ static int xgene_chan_xfer_request(struct xgene_dma_ring *ring,
 static void xgene_chan_xfer_ld_pending(struct xgene_dma_chan *chan)
 {
        struct xgene_dma_desc_sw *desc_sw, *_desc_sw;
-       int ret;
 
        /*
         * If the list of pending descriptors is empty, then we
@@ -735,18 +724,13 @@ static void xgene_chan_xfer_ld_pending(struct xgene_dma_chan *chan)
                if (chan->pending >= chan->max_outstanding)
                        return;
 
-               ret = xgene_chan_xfer_request(&chan->tx_ring, desc_sw);
-               if (ret)
-                       return;
+               xgene_chan_xfer_request(chan, desc_sw);
 
                /*
                 * Delete this element from ld pending queue and append it to
                 * ld running queue
                 */
                list_move_tail(&desc_sw->node, &chan->ld_running);
-
-               /* Increment the pending transaction count */
-               chan->pending++;
        }
 }
 
@@ -821,7 +805,8 @@ static void xgene_dma_cleanup_descriptors(struct xgene_dma_chan *chan)
                 * Decrement the pending transaction count
                 * as we have processed one
                 */
-               chan->pending--;
+               chan->pending -= ((desc_sw->flags &
+                                 XGENE_DMA_FLAG_64B_DESC) ? 2 : 1);
 
                /*
                 * Delete this node from ld running queue and append it to
@@ -1421,15 +1406,18 @@ static int xgene_dma_create_ring_one(struct xgene_dma_chan *chan,
                                     struct xgene_dma_ring *ring,
                                     enum xgene_dma_ring_cfgsize cfgsize)
 {
+       int ret;
+
        /* Setup DMA ring descriptor variables */
        ring->pdma = chan->pdma;
        ring->cfgsize = cfgsize;
        ring->num = chan->pdma->ring_num++;
        ring->id = XGENE_DMA_RING_ID_GET(ring->owner, ring->buf_num);
 
-       ring->size = xgene_dma_get_ring_size(chan, cfgsize);
-       if (ring->size <= 0)
-               return ring->size;
+       ret = xgene_dma_get_ring_size(chan, cfgsize);
+       if (ret <= 0)
+               return ret;
+       ring->size = ret;
 
        /* Allocate memory for DMA ring descriptor */
        ring->desc_vaddr = dma_zalloc_coherent(chan->dev, ring->size,
@@ -1482,7 +1470,7 @@ static int xgene_dma_create_chan_rings(struct xgene_dma_chan *chan)
                 tx_ring->id, tx_ring->num, tx_ring->desc_vaddr);
 
        /* Set the max outstanding request possible to this channel */
-       chan->max_outstanding = rx_ring->slots;
+       chan->max_outstanding = tx_ring->slots;
 
        return ret;
 }
index 39915a6b7986e2fba00d285370f57f27ed3eeb9a..c017fcd8e07c29b65b7a480a1b817b4645c40f33 100644 (file)
@@ -739,7 +739,7 @@ static struct dma_chan *zx_of_dma_simple_xlate(struct of_phandle_args *dma_spec,
        struct dma_chan *chan;
        struct zx_dma_chan *c;
 
-       if (request > d->dma_requests)
+       if (request >= d->dma_requests)
                return NULL;
 
        chan = dma_get_any_slave_channel(&d->slave);
index a07addde297be4576a9306d170feb5e9b910a6d8..8dd0af1d50bc4e544b167555c828ed9ec5e716e2 100644 (file)
@@ -159,7 +159,7 @@ static int find_cable_index_by_name(struct extcon_dev *edev, const char *name)
 static bool is_extcon_changed(u32 prev, u32 new, int idx, bool *attached)
 {
        if (((prev >> idx) & 0x1) != ((new >> idx) & 0x1)) {
-               *attached = new ? true : false;
+               *attached = ((new >> idx) & 0x1) ? true : false;
                return true;
        }
 
index d8de6a8dd4de156e395cd36e6f25690bb347b613..665efca59487a3eb4d341570002794e09f7bd11a 100644 (file)
@@ -139,6 +139,14 @@ config QCOM_SCM
        bool
        depends on ARM || ARM64
 
+config QCOM_SCM_32
+       def_bool y
+       depends on QCOM_SCM && ARM
+
+config QCOM_SCM_64
+       def_bool y
+       depends on QCOM_SCM && ARM64
+
 source "drivers/firmware/broadcom/Kconfig"
 source "drivers/firmware/google/Kconfig"
 source "drivers/firmware/efi/Kconfig"
index 000830fc6707e88c8ae59961616e4e84468f1fb3..2ee83474a3c1fec73d8e587465c9b5fb71b333b3 100644 (file)
@@ -13,7 +13,8 @@ obj-$(CONFIG_ISCSI_IBFT_FIND) += iscsi_ibft_find.o
 obj-$(CONFIG_ISCSI_IBFT)       += iscsi_ibft.o
 obj-$(CONFIG_FIRMWARE_MEMMAP)  += memmap.o
 obj-$(CONFIG_QCOM_SCM)         += qcom_scm.o
-obj-$(CONFIG_QCOM_SCM)         += qcom_scm-32.o
+obj-$(CONFIG_QCOM_SCM_64)      += qcom_scm-64.o
+obj-$(CONFIG_QCOM_SCM_32)      += qcom_scm-32.o
 CFLAGS_qcom_scm-32.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1)
 
 obj-y                          += broadcom/
index e29560e6b40b0e5f28a141e7c88ceba1bdfa22ff..950c87f5d279335210088e4154eda135b24304d5 100644 (file)
@@ -13,6 +13,7 @@
  */
 
 #include <linux/efi.h>
+#include <linux/sort.h>
 #include <asm/efi.h>
 
 #include "efistub.h"
@@ -305,6 +306,44 @@ fail:
  */
 #define EFI_RT_VIRTUAL_BASE    0x40000000
 
+static int cmp_mem_desc(const void *l, const void *r)
+{
+       const efi_memory_desc_t *left = l, *right = r;
+
+       return (left->phys_addr > right->phys_addr) ? 1 : -1;
+}
+
+/*
+ * Returns whether region @left ends exactly where region @right starts,
+ * or false if either argument is NULL.
+ */
+static bool regions_are_adjacent(efi_memory_desc_t *left,
+                                efi_memory_desc_t *right)
+{
+       u64 left_end;
+
+       if (left == NULL || right == NULL)
+               return false;
+
+       left_end = left->phys_addr + left->num_pages * EFI_PAGE_SIZE;
+
+       return left_end == right->phys_addr;
+}
+
+/*
+ * Returns whether region @left and region @right have compatible memory type
+ * mapping attributes, and are both EFI_MEMORY_RUNTIME regions.
+ */
+static bool regions_have_compatible_memory_type_attrs(efi_memory_desc_t *left,
+                                                     efi_memory_desc_t *right)
+{
+       static const u64 mem_type_mask = EFI_MEMORY_WB | EFI_MEMORY_WT |
+                                        EFI_MEMORY_WC | EFI_MEMORY_UC |
+                                        EFI_MEMORY_RUNTIME;
+
+       return ((left->attribute ^ right->attribute) & mem_type_mask) == 0;
+}
+
 /*
  * efi_get_virtmap() - create a virtual mapping for the EFI memory map
  *
@@ -317,33 +356,52 @@ void efi_get_virtmap(efi_memory_desc_t *memory_map, unsigned long map_size,
                     int *count)
 {
        u64 efi_virt_base = EFI_RT_VIRTUAL_BASE;
-       efi_memory_desc_t *out = runtime_map;
+       efi_memory_desc_t *in, *prev = NULL, *out = runtime_map;
        int l;
 
-       for (l = 0; l < map_size; l += desc_size) {
-               efi_memory_desc_t *in = (void *)memory_map + l;
+       /*
+        * To work around potential issues with the Properties Table feature
+        * introduced in UEFI 2.5, which may split PE/COFF executable images
+        * in memory into several RuntimeServicesCode and RuntimeServicesData
+        * regions, we need to preserve the relative offsets between adjacent
+        * EFI_MEMORY_RUNTIME regions with the same memory type attributes.
+        * The easiest way to find adjacent regions is to sort the memory map
+        * before traversing it.
+        */
+       sort(memory_map, map_size / desc_size, desc_size, cmp_mem_desc, NULL);
+
+       for (l = 0; l < map_size; l += desc_size, prev = in) {
                u64 paddr, size;
 
+               in = (void *)memory_map + l;
                if (!(in->attribute & EFI_MEMORY_RUNTIME))
                        continue;
 
+               paddr = in->phys_addr;
+               size = in->num_pages * EFI_PAGE_SIZE;
+
                /*
                 * Make the mapping compatible with 64k pages: this allows
                 * a 4k page size kernel to kexec a 64k page size kernel and
                 * vice versa.
                 */
-               paddr = round_down(in->phys_addr, SZ_64K);
-               size = round_up(in->num_pages * EFI_PAGE_SIZE +
-                               in->phys_addr - paddr, SZ_64K);
-
-               /*
-                * Avoid wasting memory on PTEs by choosing a virtual base that
-                * is compatible with section mappings if this region has the
-                * appropriate size and physical alignment. (Sections are 2 MB
-                * on 4k granule kernels)
-                */
-               if (IS_ALIGNED(in->phys_addr, SZ_2M) && size >= SZ_2M)
-                       efi_virt_base = round_up(efi_virt_base, SZ_2M);
+               if (!regions_are_adjacent(prev, in) ||
+                   !regions_have_compatible_memory_type_attrs(prev, in)) {
+
+                       paddr = round_down(in->phys_addr, SZ_64K);
+                       size += in->phys_addr - paddr;
+
+                       /*
+                        * Avoid wasting memory on PTEs by choosing a virtual
+                        * base that is compatible with section mappings if this
+                        * region has the appropriate size and physical
+                        * alignment. (Sections are 2 MB on 4k granule kernels)
+                        */
+                       if (IS_ALIGNED(in->phys_addr, SZ_2M) && size >= SZ_2M)
+                               efi_virt_base = round_up(efi_virt_base, SZ_2M);
+                       else
+                               efi_virt_base = round_up(efi_virt_base, SZ_64K);
+               }
 
                in->virt_addr = efi_virt_base + in->phys_addr - paddr;
                efi_virt_base += size;
index e334a01cf92f8243392ddd66616c8563306ccf5d..6b6548fda0895ecb0ca7e9a60699d7100e335566 100644 (file)
@@ -5,10 +5,6 @@
 /* error code which can't be mistaken for valid address */
 #define EFI_ERROR      (~0UL)
 
-#undef memcpy
-#undef memset
-#undef memmove
-
 void efi_char16_printk(efi_system_table_t *, efi_char16_t *);
 
 efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg, void *__image,
diff --git a/drivers/firmware/qcom_scm-64.c b/drivers/firmware/qcom_scm-64.c
new file mode 100644 (file)
index 0000000..bb6555f
--- /dev/null
@@ -0,0 +1,63 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
+ */
+
+#include <linux/io.h>
+#include <linux/errno.h>
+#include <linux/qcom_scm.h>
+
+/**
+ * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus
+ * @entry: Entry point function for the cpus
+ * @cpus: The cpumask of cpus that will use the entry point
+ *
+ * Set the cold boot address of the cpus. Any cpu outside the supported
+ * range would be removed from the cpu present mask.
+ */
+int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
+{
+       return -ENOTSUPP;
+}
+
+/**
+ * qcom_scm_set_warm_boot_addr() - Set the warm boot address for cpus
+ * @entry: Entry point function for the cpus
+ * @cpus: The cpumask of cpus that will use the entry point
+ *
+ * Set the Linux entry point for the SCM to transfer control to when coming
+ * out of a power down. CPU power down may be executed on cpuidle or hotplug.
+ */
+int __qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
+{
+       return -ENOTSUPP;
+}
+
+/**
+ * qcom_scm_cpu_power_down() - Power down the cpu
+ * @flags - Flags to flush cache
+ *
+ * This is an end point to power down cpu. If there was a pending interrupt,
+ * the control would return from this function, otherwise, the cpu jumps to the
+ * warm boot entry point set for this cpu upon reset.
+ */
+void __qcom_scm_cpu_power_down(u32 flags)
+{
+}
+
+int __qcom_scm_is_call_available(u32 svc_id, u32 cmd_id)
+{
+       return -ENOTSUPP;
+}
+
+int __qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp)
+{
+       return -ENOTSUPP;
+}
index b4fc9e4d24c6b15857e2a2cd3c1000e0473af8f9..8949b3f6f74d207f0bc935af11dd76cf956b49ba 100644 (file)
@@ -356,7 +356,7 @@ config GPIO_PXA
 
 config GPIO_RCAR
        tristate "Renesas R-Car GPIO"
-       depends on ARM && (ARCH_SHMOBILE || COMPILE_TEST)
+       depends on ARCH_SHMOBILE || COMPILE_TEST
        select GPIOLIB_IRQCHIP
        help
          Say yes here to support GPIO on Renesas R-Car SoCs.
index 9b7e0b3db387218865004332c8313616026d7ae4..1b44941574fa6965d68e474b9197907e71473692 100644 (file)
@@ -201,8 +201,7 @@ static int altera_gpio_direction_output(struct gpio_chip *gc,
        return 0;
 }
 
-static void altera_gpio_irq_edge_handler(unsigned int irq,
-                                       struct irq_desc *desc)
+static void altera_gpio_irq_edge_handler(struct irq_desc *desc)
 {
        struct altera_gpio_chip *altera_gc;
        struct irq_chip *chip;
@@ -231,8 +230,7 @@ static void altera_gpio_irq_edge_handler(unsigned int irq,
 }
 
 
-static void altera_gpio_irq_leveL_high_handler(unsigned int irq,
-                                             struct irq_desc *desc)
+static void altera_gpio_irq_leveL_high_handler(struct irq_desc *desc)
 {
        struct altera_gpio_chip *altera_gc;
        struct irq_chip *chip;
index 31b90ac15204b9bf987f0cfc5e454ff90637dc78..33a1f9779b86bb1e422d3144f69c600409e9221d 100644 (file)
@@ -433,7 +433,7 @@ static int bcm_kona_gpio_irq_set_type(struct irq_data *d, unsigned int type)
        return 0;
 }
 
-static void bcm_kona_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void bcm_kona_gpio_irq_handler(struct irq_desc *desc)
 {
        void __iomem *reg_base;
        int bit, bank_id;
index 9ea86d2ac05462bb832f5fe14cae4c2b9132c2c1..4c64627c6bb5db745a3efff6d64eef9d8416e331 100644 (file)
@@ -236,7 +236,7 @@ static void brcmstb_gpio_irq_bank_handler(struct brcmstb_gpio_bank *bank)
 }
 
 /* Each UPG GIO block has one IRQ for all banks */
-static void brcmstb_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void brcmstb_gpio_irq_handler(struct irq_desc *desc)
 {
        struct gpio_chip *gc = irq_desc_get_handler_data(desc);
        struct brcmstb_gpio_priv *priv = brcmstb_gpio_gc_to_priv(gc);
index 94b0ab7097216560c5b867663425bd1f5ad04d92..5e715388803db555d7180fc9b6c3b24f1c7f48dc 100644 (file)
@@ -326,8 +326,7 @@ static struct irq_chip gpio_irqchip = {
        .flags          = IRQCHIP_SET_TYPE_MASKED,
 };
 
-static void
-gpio_irq_handler(unsigned __irq, struct irq_desc *desc)
+static void gpio_irq_handler(struct irq_desc *desc)
 {
        unsigned int irq = irq_desc_get_irq(desc);
        struct davinci_gpio_regs __iomem *g;
index c5be4b9b8baf7330ba8a87c99332b23e534fe135..fcd5b0acfc7286af365f163fe647e13263dd4606 100644 (file)
@@ -147,7 +147,7 @@ static u32 dwapb_do_irq(struct dwapb_gpio *gpio)
        return ret;
 }
 
-static void dwapb_irq_handler(u32 irq, struct irq_desc *desc)
+static void dwapb_irq_handler(struct irq_desc *desc)
 {
        struct dwapb_gpio *gpio = irq_desc_get_handler_data(desc);
        struct irq_chip *chip = irq_desc_get_chip(desc);
index 9d90366ea2599920f64556caa38cc225b3296b83..3e3947b35c8378fac9e6f485e8c89895f5c84d97 100644 (file)
@@ -78,7 +78,7 @@ static void ep93xx_gpio_int_debounce(unsigned int irq, bool enable)
                EP93XX_GPIO_REG(int_debounce_register_offset[port]));
 }
 
-static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void ep93xx_gpio_ab_irq_handler(struct irq_desc *desc)
 {
        unsigned char status;
        int i;
@@ -100,8 +100,7 @@ static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc)
        }
 }
 
-static void ep93xx_gpio_f_irq_handler(unsigned int __irq,
-                                     struct irq_desc *desc)
+static void ep93xx_gpio_f_irq_handler(struct irq_desc *desc)
 {
        /*
         * map discontiguous hw irq range to continuous sw irq range:
index aa28c65eb6b4f3a98e7aa6d5a1a1eac28d1c0c06..70097472b02cc7cb9332f9e59cac750720e21c54 100644 (file)
@@ -301,7 +301,7 @@ static const struct pci_device_id intel_gpio_ids[] = {
 };
 MODULE_DEVICE_TABLE(pci, intel_gpio_ids);
 
-static void intel_mid_irq_handler(unsigned irq, struct irq_desc *desc)
+static void intel_mid_irq_handler(struct irq_desc *desc)
 {
        struct gpio_chip *gc = irq_desc_get_handler_data(desc);
        struct intel_mid_gpio *priv = to_intel_gpio_priv(gc);
index 153af464c7a780e7ef57c8ba15e3e7d7b5307ede..127c37b380ae21c1d8ff85a3913ab11e1b76613f 100644 (file)
@@ -234,7 +234,7 @@ static int lp_gpio_direction_output(struct gpio_chip *chip,
        return 0;
 }
 
-static void lp_gpio_irq_handler(unsigned hwirq, struct irq_desc *desc)
+static void lp_gpio_irq_handler(struct irq_desc *desc)
 {
        struct irq_data *data = irq_desc_get_irq_data(desc);
        struct gpio_chip *gc = irq_desc_get_handler_data(desc);
index 8ef7a12de98375e1dcb285799a6213b93a78551f..48ef368347ab2cd63cdb1d4f922572c608af9e89 100644 (file)
@@ -194,7 +194,7 @@ static int mpc8xxx_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
                return -ENXIO;
 }
 
-static void mpc8xxx_gpio_irq_cascade(unsigned int irq, struct irq_desc *desc)
+static void mpc8xxx_gpio_irq_cascade(struct irq_desc *desc)
 {
        struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_desc_get_handler_data(desc);
        struct irq_chip *chip = irq_desc_get_chip(desc);
index 7bcfb87a5fa6812a51465d5c510a4c8a61c5d7d4..22523aae8abe597b0dacee0d63b7197288d2bd9d 100644 (file)
@@ -232,7 +232,7 @@ static struct irq_chip msic_irqchip = {
        .irq_bus_sync_unlock    = msic_bus_sync_unlock,
 };
 
-static void msic_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+static void msic_gpio_irq_handler(struct irq_desc *desc)
 {
        struct irq_data *data = irq_desc_get_irq_data(desc);
        struct msic_gpio *mg = irq_data_get_irq_handler_data(data);
index d2012cfb5571819f6b6e4526c40625e9e94d8076..4b4222145f1029fb6c706517f43547f292d66613 100644 (file)
@@ -305,7 +305,7 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type)
  * which have been set as summary IRQ lines and which are triggered,
  * and to call their interrupt handlers.
  */
-static void msm_summary_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void msm_summary_irq_handler(struct irq_desc *desc)
 {
        unsigned long i;
        struct irq_chip *chip = irq_desc_get_chip(desc);
index b396bf3bf29464c210e5ab0add53d95a9f134eb4..df418b81456dfdc5f7a876221cc6c9a2ef80c380 100644 (file)
@@ -458,7 +458,7 @@ static int mvebu_gpio_irq_set_type(struct irq_data *d, unsigned int type)
        return 0;
 }
 
-static void mvebu_gpio_irq_handler(unsigned int __irq, struct irq_desc *desc)
+static void mvebu_gpio_irq_handler(struct irq_desc *desc)
 {
        struct mvebu_gpio_chip *mvchip = irq_desc_get_handler_data(desc);
        struct irq_chip *chip = irq_desc_get_chip(desc);
index b752b560126e71c0066fd66f659641155b39ad71..b8dd847443c50750429a0d2a4b00407351490fd7 100644 (file)
@@ -272,7 +272,7 @@ static void mxc_gpio_irq_handler(struct mxc_gpio_port *port, u32 irq_stat)
 }
 
 /* MX1 and MX3 has one interrupt *per* gpio port */
-static void mx3_gpio_irq_handler(u32 irq, struct irq_desc *desc)
+static void mx3_gpio_irq_handler(struct irq_desc *desc)
 {
        u32 irq_stat;
        struct mxc_gpio_port *port = irq_desc_get_handler_data(desc);
@@ -288,7 +288,7 @@ static void mx3_gpio_irq_handler(u32 irq, struct irq_desc *desc)
 }
 
 /* MX2 has one interrupt *for all* gpio ports */
-static void mx2_gpio_irq_handler(u32 irq, struct irq_desc *desc)
+static void mx2_gpio_irq_handler(struct irq_desc *desc)
 {
        u32 irq_msk, irq_stat;
        struct mxc_gpio_port *port;
@@ -339,13 +339,15 @@ static int gpio_set_wake_irq(struct irq_data *d, u32 enable)
        return 0;
 }
 
-static void mxc_gpio_init_gc(struct mxc_gpio_port *port, int irq_base)
+static int mxc_gpio_init_gc(struct mxc_gpio_port *port, int irq_base)
 {
        struct irq_chip_generic *gc;
        struct irq_chip_type *ct;
 
        gc = irq_alloc_generic_chip("gpio-mxc", 1, irq_base,
                                    port->base, handle_level_irq);
+       if (!gc)
+               return -ENOMEM;
        gc->private = port;
 
        ct = gc->chip_types;
@@ -360,6 +362,8 @@ static void mxc_gpio_init_gc(struct mxc_gpio_port *port, int irq_base)
 
        irq_setup_generic_chip(gc, IRQ_MSK(32), IRQ_GC_INIT_NESTED_LOCK,
                               IRQ_NOREQUEST, 0);
+
+       return 0;
 }
 
 static void mxc_gpio_get_hw(struct platform_device *pdev)
@@ -477,12 +481,16 @@ static int mxc_gpio_probe(struct platform_device *pdev)
        }
 
        /* gpio-mxc can be a generic irq chip */
-       mxc_gpio_init_gc(port, irq_base);
+       err = mxc_gpio_init_gc(port, irq_base);
+       if (err < 0)
+               goto out_irqdomain_remove;
 
        list_add_tail(&port->node, &mxc_gpio_ports);
 
        return 0;
 
+out_irqdomain_remove:
+       irq_domain_remove(port->domain);
 out_irqdesc_free:
        irq_free_descs(irq_base, 32);
 out_gpiochip_remove:
index b7f383eb18d91e2f82831e4813b987d74d18d77b..a4288f428819a3175d2e74cb2feec138ffacb4dc 100644 (file)
@@ -154,7 +154,7 @@ static void mxs_flip_edge(struct mxs_gpio_port *port, u32 gpio)
 }
 
 /* MXS has one interrupt *per* gpio port */
-static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc)
+static void mxs_gpio_irq_handler(struct irq_desc *desc)
 {
        u32 irq_stat;
        struct mxs_gpio_port *port = irq_desc_get_handler_data(desc);
@@ -196,13 +196,16 @@ static int mxs_gpio_set_wake_irq(struct irq_data *d, unsigned int enable)
        return 0;
 }
 
-static void __init mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base)
+static int __init mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base)
 {
        struct irq_chip_generic *gc;
        struct irq_chip_type *ct;
 
        gc = irq_alloc_generic_chip("gpio-mxs", 1, irq_base,
                                    port->base, handle_level_irq);
+       if (!gc)
+               return -ENOMEM;
+
        gc->private = port;
 
        ct = gc->chip_types;
@@ -216,6 +219,8 @@ static void __init mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base)
 
        irq_setup_generic_chip(gc, IRQ_MSK(32), IRQ_GC_INIT_NESTED_LOCK,
                               IRQ_NOREQUEST, 0);
+
+       return 0;
 }
 
 static int mxs_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
@@ -317,7 +322,9 @@ static int mxs_gpio_probe(struct platform_device *pdev)
        }
 
        /* gpio-mxs can be a generic irq chip */
-       mxs_gpio_init_gc(port, irq_base);
+       err = mxs_gpio_init_gc(port, irq_base);
+       if (err < 0)
+               goto out_irqdomain_remove;
 
        /* setup one handler for each entry */
        irq_set_chained_handler_and_data(port->irq, mxs_gpio_irq_handler,
@@ -343,6 +350,8 @@ static int mxs_gpio_probe(struct platform_device *pdev)
 
 out_bgpio_remove:
        bgpio_remove(&port->bgc);
+out_irqdomain_remove:
+       irq_domain_remove(port->domain);
 out_irqdesc_free:
        irq_free_descs(irq_base, 32);
        return err;
index 2ae0d47e955443f7f1aec2f51c522466aa54ce30..5236db161e76047db31bf8c8e5ae7299f12fd06d 100644 (file)
@@ -709,7 +709,7 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset)
  * line's interrupt handler has been run, we may miss some nested
  * interrupts.
  */
-static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void omap_gpio_irq_handler(struct irq_desc *desc)
 {
        void __iomem *isr_reg = NULL;
        u32 isr;
@@ -1098,7 +1098,6 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)
        } else {
                bank->chip.label = "gpio";
                bank->chip.base = gpio;
-               gpio += bank->width;
        }
        bank->chip.ngpio = bank->width;
 
@@ -1108,6 +1107,9 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)
                return ret;
        }
 
+       if (!bank->is_mpuio)
+               gpio += bank->width;
+
 #ifdef CONFIG_ARCH_OMAP1
        /*
         * REVISIT: Once we have OMAP1 supporting SPARSE_IRQ, we can drop
@@ -1253,8 +1255,11 @@ static int omap_gpio_probe(struct platform_device *pdev)
        omap_gpio_mod_init(bank);
 
        ret = omap_gpio_chip_init(bank, irqc);
-       if (ret)
+       if (ret) {
+               pm_runtime_put_sync(bank->dev);
+               pm_runtime_disable(bank->dev);
                return ret;
+       }
 
        omap_gpio_show_rev(bank);
 
index 04756130437f193c12e6e6033ed5b6fff6be6b43..229ef653e0f8f631172e1956ad4c9f9c74c50b02 100644 (file)
@@ -187,7 +187,7 @@ static int pl061_irq_type(struct irq_data *d, unsigned trigger)
        return 0;
 }
 
-static void pl061_irq_handler(unsigned irq, struct irq_desc *desc)
+static void pl061_irq_handler(struct irq_desc *desc)
 {
        unsigned long pending;
        int offset;
index 55a11de3d5b741f1038fd4b50fb9300cc8be7813..df2ce550f30929c1a20d1aca81e538a367f8f97b 100644 (file)
@@ -401,7 +401,7 @@ static int pxa_gpio_irq_type(struct irq_data *d, unsigned int type)
        return 0;
 }
 
-static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
+static void pxa_gpio_demux_handler(struct irq_desc *desc)
 {
        struct pxa_gpio_chip *c;
        int loop, gpio, gpio_base, n;
index 67bd2f5d89e8f3d67efab99b8f3799351c263987..990fa9023e2228a82d1138cb8f25bfeb75dab23d 100644 (file)
@@ -172,8 +172,7 @@ static struct irq_domain *sa1100_gpio_irqdomain;
  * irq_controller_lock held, and IRQs disabled.  Decode the IRQ
  * and call the handler.
  */
-static void
-sa1100_gpio_handler(unsigned int __irq, struct irq_desc *desc)
+static void sa1100_gpio_handler(struct irq_desc *desc)
 {
        unsigned int irq, mask;
 
index 458d9d7952b840af2d7d2666ef3567dac8244403..9c6b96707c9f286a9bbf13c756beab7d4cedbace 100644 (file)
@@ -706,4 +706,3 @@ module_exit(sx150x_exit);
 MODULE_AUTHOR("Gregory Bean <gbean@codeaurora.org>");
 MODULE_DESCRIPTION("Driver for Semtech SX150X I2C GPIO Expanders");
 MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("i2c:sx150x");
index 9b14aafb576da8dc664cd75679379fe04ff4ace7..027e5f47dd28738f04e6347f1807c6b28b34e618 100644 (file)
@@ -266,7 +266,7 @@ static void tegra_gpio_irq_shutdown(struct irq_data *d)
        gpiochip_unlock_as_irq(&tegra_gpio_chip, gpio);
 }
 
-static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void tegra_gpio_irq_handler(struct irq_desc *desc)
 {
        int port;
        int pin;
index 5a492054589fa472c41f4f7ae7fc8b33b38843ce..30653e6319e9899cd2bd2e36ff5e00b0261dda62 100644 (file)
@@ -192,7 +192,7 @@ out:
        return ret;
 }
 
-static void timbgpio_irq(unsigned int irq, struct irq_desc *desc)
+static void timbgpio_irq(struct irq_desc *desc)
 {
        struct timbgpio *tgpio = irq_desc_get_handler_data(desc);
        struct irq_data *data = irq_desc_get_irq_data(desc);
index bbac92ae4c328ab96eef76785e4189e7b3de08a5..87bb1b1eee8deacaa4f9cdb9ccc81166025393e5 100644 (file)
@@ -375,7 +375,7 @@ static int gpio_set_irq_wake(struct irq_data *data, unsigned int on)
 #define gpio_set_irq_wake NULL
 #endif
 
-static void tz1090_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void tz1090_gpio_irq_handler(struct irq_desc *desc)
 {
        irq_hw_number_t hw;
        unsigned int irq_stat, irq_no;
@@ -400,7 +400,7 @@ static void tz1090_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
                                == IRQ_TYPE_EDGE_BOTH)
                        tz1090_gpio_irq_next_edge(bank, hw);
 
-               generic_handle_irq_desc(irq_no, child_desc);
+               generic_handle_irq_desc(child_desc);
        }
 }
 
index 3d5714d4f405dd50731da6a11d8f24398d7c36d8..069f9e4b7daae0b5afe7bef0543b822191de22f3 100644 (file)
@@ -120,7 +120,7 @@ static int vf610_gpio_direction_output(struct gpio_chip *chip, unsigned gpio,
        return pinctrl_gpio_direction_output(chip->base + gpio);
 }
 
-static void vf610_gpio_irq_handler(u32 irq, struct irq_desc *desc)
+static void vf610_gpio_irq_handler(struct irq_desc *desc)
 {
        struct vf610_gpio_port *port = irq_desc_get_handler_data(desc);
        struct irq_chip *chip = irq_desc_get_chip(desc);
@@ -176,9 +176,9 @@ static int vf610_gpio_irq_set_type(struct irq_data *d, u32 type)
        port->irqc[d->hwirq] = irqc;
 
        if (type & IRQ_TYPE_LEVEL_MASK)
-               __irq_set_handler_locked(d->irq, handle_level_irq);
+               irq_set_handler_locked(d, handle_level_irq);
        else
-               __irq_set_handler_locked(d->irq, handle_edge_irq);
+               irq_set_handler_locked(d, handle_edge_irq);
 
        return 0;
 }
index 12ee1969298cc1bb82eb9438ed148f1f41cda9d8..4b8a2691070537cde2affdce5ff7624d032ce193 100644 (file)
@@ -177,7 +177,7 @@ static int zx_irq_type(struct irq_data *d, unsigned trigger)
        return 0;
 }
 
-static void zx_irq_handler(unsigned irq, struct irq_desc *desc)
+static void zx_irq_handler(struct irq_desc *desc)
 {
        unsigned long pending;
        int offset;
index 27348e7cb705909adafa01b4490b2866e125caae..1d1a5865ede90449d8e2b4abba88f14f6c225b82 100644 (file)
@@ -514,7 +514,7 @@ static void zynq_gpio_handle_bank_irq(struct zynq_gpio *gpio,
  * application for that pin.
  * Note: A bug is reported if no handler is set for the gpio pin.
  */
-static void zynq_gpio_irqhandler(unsigned int irq, struct irq_desc *desc)
+static void zynq_gpio_irqhandler(struct irq_desc *desc)
 {
        u32 int_sts, int_enb;
        unsigned int bank_num;
index 980c1f87866ac268b3dc8046faec602e57ca32c9..5db3445552b176d2c11ca8b225ef88b4b80d22eb 100644 (file)
@@ -1174,15 +1174,16 @@ EXPORT_SYMBOL_GPL(gpiod_is_active_low);
  * that the GPIO was actually requested.
  */
 
-static bool _gpiod_get_raw_value(const struct gpio_desc *desc)
+static int _gpiod_get_raw_value(const struct gpio_desc *desc)
 {
        struct gpio_chip        *chip;
-       bool value;
        int offset;
+       int value;
 
        chip = desc->chip;
        offset = gpio_chip_hwgpio(desc);
-       value = chip->get ? chip->get(chip, offset) : false;
+       value = chip->get ? chip->get(chip, offset) : -EIO;
+       value = value < 0 ? value : !!value;
        trace_gpio_value(desc_to_gpio(desc), 1, value);
        return value;
 }
@@ -1192,7 +1193,7 @@ static bool _gpiod_get_raw_value(const struct gpio_desc *desc)
  * @desc: gpio whose value will be returned
  *
  * Return the GPIO's raw value, i.e. the value of the physical line disregarding
- * its ACTIVE_LOW status.
+ * its ACTIVE_LOW status, or negative errno on failure.
  *
  * This function should be called from contexts where we cannot sleep, and will
  * complain if the GPIO chip functions potentially sleep.
@@ -1212,7 +1213,7 @@ EXPORT_SYMBOL_GPL(gpiod_get_raw_value);
  * @desc: gpio whose value will be returned
  *
  * Return the GPIO's logical value, i.e. taking the ACTIVE_LOW status into
- * account.
+ * account, or negative errno on failure.
  *
  * This function should be called from contexts where we cannot sleep, and will
  * complain if the GPIO chip functions potentially sleep.
@@ -1226,6 +1227,9 @@ int gpiod_get_value(const struct gpio_desc *desc)
        WARN_ON(desc->chip->can_sleep);
 
        value = _gpiod_get_raw_value(desc);
+       if (value < 0)
+               return value;
+
        if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
                value = !value;
 
@@ -1548,7 +1552,7 @@ EXPORT_SYMBOL_GPL(gpiochip_unlock_as_irq);
  * @desc: gpio whose value will be returned
  *
  * Return the GPIO's raw value, i.e. the value of the physical line disregarding
- * its ACTIVE_LOW status.
+ * its ACTIVE_LOW status, or negative errno on failure.
  *
  * This function is to be called from contexts that can sleep.
  */
@@ -1566,7 +1570,7 @@ EXPORT_SYMBOL_GPL(gpiod_get_raw_value_cansleep);
  * @desc: gpio whose value will be returned
  *
  * Return the GPIO's logical value, i.e. taking the ACTIVE_LOW status into
- * account.
+ * account, or negative errno on failure.
  *
  * This function is to be called from contexts that can sleep.
  */
@@ -1579,6 +1583,9 @@ int gpiod_get_value_cansleep(const struct gpio_desc *desc)
                return 0;
 
        value = _gpiod_get_raw_value(desc);
+       if (value < 0)
+               return value;
+
        if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
                value = !value;
 
index 668939a14206b4113991b69636915d562ea3d55c..0d13e6368b96de2ace3b4373a7aebd20f5cd3826 100644 (file)
@@ -82,6 +82,7 @@ extern int amdgpu_vm_block_size;
 extern int amdgpu_enable_scheduler;
 extern int amdgpu_sched_jobs;
 extern int amdgpu_sched_hw_submission;
+extern int amdgpu_enable_semaphores;
 
 #define AMDGPU_WAIT_IDLE_TIMEOUT_IN_MS         3000
 #define AMDGPU_MAX_USEC_TIMEOUT                        100000  /* 100 ms */
@@ -432,7 +433,7 @@ int amdgpu_fence_driver_init(struct amdgpu_device *adev);
 void amdgpu_fence_driver_fini(struct amdgpu_device *adev);
 void amdgpu_fence_driver_force_completion(struct amdgpu_device *adev);
 
-void amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring);
+int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring);
 int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring,
                                   struct amdgpu_irq_src *irq_src,
                                   unsigned irq_type);
@@ -890,7 +891,7 @@ struct amdgpu_ring {
        struct amdgpu_device            *adev;
        const struct amdgpu_ring_funcs  *funcs;
        struct amdgpu_fence_driver      fence_drv;
-       struct amd_gpu_scheduler        *scheduler;
+       struct amd_gpu_scheduler        sched;
 
        spinlock_t              fence_lock;
        struct mutex            *ring_lock;
@@ -1201,8 +1202,6 @@ struct amdgpu_gfx {
        struct amdgpu_irq_src           priv_inst_irq;
        /* gfx status */
        uint32_t gfx_current_status;
-       /* sync signal for const engine */
-       unsigned ce_sync_offs;
        /* ce ram size*/
        unsigned ce_ram_size;
 };
@@ -1274,8 +1273,10 @@ struct amdgpu_job {
        uint32_t                num_ibs;
        struct mutex            job_lock;
        struct amdgpu_user_fence uf;
-       int (*free_job)(struct amdgpu_job *sched_job);
+       int (*free_job)(struct amdgpu_job *job);
 };
+#define to_amdgpu_job(sched_job)               \
+               container_of((sched_job), struct amdgpu_job, base)
 
 static inline u32 amdgpu_get_ib_value(struct amdgpu_cs_parser *p, uint32_t ib_idx, int idx)
 {
@@ -1653,6 +1654,7 @@ struct amdgpu_pm {
        u8                      fan_max_rpm;
        /* dpm */
        bool                    dpm_enabled;
+       bool                    sysfs_initialized;
        struct amdgpu_dpm       dpm;
        const struct firmware   *fw;    /* SMC firmware */
        uint32_t                fw_version;
index 496ed2192ebad6ef2114f66b1b9c20591fab85b0..84d68d658f8a03653f3a60898671f775a210e904 100644 (file)
@@ -183,7 +183,7 @@ int alloc_gtt_mem(struct kgd_dev *kgd, size_t size,
                return -ENOMEM;
 
        r = amdgpu_bo_create(rdev, size, PAGE_SIZE, true, AMDGPU_GEM_DOMAIN_GTT,
-                       AMDGPU_GEM_CREATE_CPU_GTT_USWC, NULL, &(*mem)->bo);
+                            AMDGPU_GEM_CREATE_CPU_GTT_USWC, NULL, NULL, &(*mem)->bo);
        if (r) {
                dev_err(rdev->dev,
                        "failed to allocate BO for amdkfd (%d)\n", r);
index 77f1d7c6ea3af627324b147e63b21b6cbdd16302..9416e0f5c1db2bf8c5601ddee999b1ade5efabc0 100644 (file)
@@ -672,8 +672,12 @@ int amdgpu_atombios_get_clock_info(struct amdgpu_device *adev)
                /* disp clock */
                adev->clock.default_dispclk =
                        le32_to_cpu(firmware_info->info_21.ulDefaultDispEngineClkFreq);
-               if (adev->clock.default_dispclk == 0)
-                       adev->clock.default_dispclk = 54000; /* 540 Mhz */
+               /* set a reasonable default for DP */
+               if (adev->clock.default_dispclk < 53900) {
+                       DRM_INFO("Changing default dispclk from %dMhz to 600Mhz\n",
+                                adev->clock.default_dispclk / 100);
+                       adev->clock.default_dispclk = 60000;
+               }
                adev->clock.dp_extclk =
                        le16_to_cpu(firmware_info->info_21.usUniphyDPModeExtClkFreq);
                adev->clock.current_dispclk = adev->clock.default_dispclk;
index 98d59ee640cef0218677e6b31b6a24a3929c4c5b..cd639c362df3ae97fe16f4fcce8050a4df1f94d7 100644 (file)
@@ -79,7 +79,8 @@ static void amdgpu_benchmark_move(struct amdgpu_device *adev, unsigned size,
        int time;
 
        n = AMDGPU_BENCHMARK_ITERATIONS;
-       r = amdgpu_bo_create(adev, size, PAGE_SIZE, true, sdomain, 0, NULL, &sobj);
+       r = amdgpu_bo_create(adev, size, PAGE_SIZE, true, sdomain, 0, NULL,
+                            NULL, &sobj);
        if (r) {
                goto out_cleanup;
        }
@@ -91,7 +92,8 @@ static void amdgpu_benchmark_move(struct amdgpu_device *adev, unsigned size,
        if (r) {
                goto out_cleanup;
        }
-       r = amdgpu_bo_create(adev, size, PAGE_SIZE, true, ddomain, 0, NULL, &dobj);
+       r = amdgpu_bo_create(adev, size, PAGE_SIZE, true, ddomain, 0, NULL,
+                            NULL, &dobj);
        if (r) {
                goto out_cleanup;
        }
index 6b1243f9f86d784fec716415122a37fa61113cf8..8e995148f56e263ecde7e5e7a390645b585f2c52 100644 (file)
@@ -86,7 +86,7 @@ static int amdgpu_cgs_gmap_kmem(void *cgs_device, void *kmem,
 
        struct sg_table *sg = drm_prime_pages_to_sg(&kmem_page, npages);
        ret = amdgpu_bo_create(adev, size, PAGE_SIZE, false,
-                              AMDGPU_GEM_DOMAIN_GTT, 0, sg, &bo);
+                              AMDGPU_GEM_DOMAIN_GTT, 0, sg, NULL, &bo);
        if (ret)
                return ret;
        ret = amdgpu_bo_reserve(bo, false);
@@ -197,7 +197,8 @@ static int amdgpu_cgs_alloc_gpu_mem(void *cgs_device,
 
        ret = amdgpu_bo_create_restricted(adev, size, PAGE_SIZE,
                                          true, domain, flags,
-                                         NULL, &placement, &obj);
+                                         NULL, &placement, NULL,
+                                         &obj);
        if (ret) {
                DRM_ERROR("(%d) bo create failed\n", ret);
                return ret;
@@ -207,44 +208,6 @@ static int amdgpu_cgs_alloc_gpu_mem(void *cgs_device,
        return ret;
 }
 
-static int amdgpu_cgs_import_gpu_mem(void *cgs_device, int dmabuf_fd,
-                                    cgs_handle_t *handle)
-{
-       CGS_FUNC_ADEV;
-       int r;
-       uint32_t dma_handle;
-       struct drm_gem_object *obj;
-       struct amdgpu_bo *bo;
-       struct drm_device *dev = adev->ddev;
-       struct drm_file *file_priv = NULL, *priv;
-
-       mutex_lock(&dev->struct_mutex);
-       list_for_each_entry(priv, &dev->filelist, lhead) {
-               rcu_read_lock();
-               if (priv->pid == get_pid(task_pid(current)))
-                       file_priv = priv;
-               rcu_read_unlock();
-               if (file_priv)
-                       break;
-       }
-       mutex_unlock(&dev->struct_mutex);
-       r = dev->driver->prime_fd_to_handle(dev,
-                                           file_priv, dmabuf_fd,
-                                           &dma_handle);
-       spin_lock(&file_priv->table_lock);
-
-       /* Check if we currently have a reference on the object */
-       obj = idr_find(&file_priv->object_idr, dma_handle);
-       if (obj == NULL) {
-               spin_unlock(&file_priv->table_lock);
-               return -EINVAL;
-       }
-       spin_unlock(&file_priv->table_lock);
-       bo = gem_to_amdgpu_bo(obj);
-       *handle = (cgs_handle_t)bo;
-       return 0;
-}
-
 static int amdgpu_cgs_free_gpu_mem(void *cgs_device, cgs_handle_t handle)
 {
        struct amdgpu_bo *obj = (struct amdgpu_bo *)handle;
@@ -809,7 +772,6 @@ static const struct cgs_ops amdgpu_cgs_ops = {
 };
 
 static const struct cgs_os_ops amdgpu_cgs_os_ops = {
-       amdgpu_cgs_import_gpu_mem,
        amdgpu_cgs_add_irq_source,
        amdgpu_cgs_irq_get,
        amdgpu_cgs_irq_put
index 3b355aeb62fd353320fd47260bb05263e0e998ab..fd16652aa277c75d8ed5ca28e9088c153699addd 100644 (file)
@@ -154,42 +154,42 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
 {
        union drm_amdgpu_cs *cs = data;
        uint64_t *chunk_array_user;
-       uint64_t *chunk_array = NULL;
+       uint64_t *chunk_array;
        struct amdgpu_fpriv *fpriv = p->filp->driver_priv;
-       unsigned size, i;
-       int r = 0;
+       unsigned size;
+       int i;
+       int ret;
 
-       if (!cs->in.num_chunks)
-               goto out;
+       if (cs->in.num_chunks == 0)
+               return 0;
+
+       chunk_array = kmalloc_array(cs->in.num_chunks, sizeof(uint64_t), GFP_KERNEL);
+       if (!chunk_array)
+               return -ENOMEM;
 
        p->ctx = amdgpu_ctx_get(fpriv, cs->in.ctx_id);
        if (!p->ctx) {
-               r = -EINVAL;
-               goto out;
+               ret = -EINVAL;
+               goto free_chunk;
        }
+
        p->bo_list = amdgpu_bo_list_get(fpriv, cs->in.bo_list_handle);
 
        /* get chunks */
        INIT_LIST_HEAD(&p->validated);
-       chunk_array = kmalloc_array(cs->in.num_chunks, sizeof(uint64_t), GFP_KERNEL);
-       if (chunk_array == NULL) {
-               r = -ENOMEM;
-               goto out;
-       }
-
-       chunk_array_user = (uint64_t __user *)(cs->in.chunks);
+       chunk_array_user = (uint64_t __user *)(unsigned long)(cs->in.chunks);
        if (copy_from_user(chunk_array, chunk_array_user,
                           sizeof(uint64_t)*cs->in.num_chunks)) {
-               r = -EFAULT;
-               goto out;
+               ret = -EFAULT;
+               goto put_bo_list;
        }
 
        p->nchunks = cs->in.num_chunks;
        p->chunks = kmalloc_array(p->nchunks, sizeof(struct amdgpu_cs_chunk),
                            GFP_KERNEL);
-       if (p->chunks == NULL) {
-               r = -ENOMEM;
-               goto out;
+       if (!p->chunks) {
+               ret = -ENOMEM;
+               goto put_bo_list;
        }
 
        for (i = 0; i < p->nchunks; i++) {
@@ -197,28 +197,30 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
                struct drm_amdgpu_cs_chunk user_chunk;
                uint32_t __user *cdata;
 
-               chunk_ptr = (void __user *)chunk_array[i];
+               chunk_ptr = (void __user *)(unsigned long)chunk_array[i];
                if (copy_from_user(&user_chunk, chunk_ptr,
                                       sizeof(struct drm_amdgpu_cs_chunk))) {
-                       r = -EFAULT;
-                       goto out;
+                       ret = -EFAULT;
+                       i--;
+                       goto free_partial_kdata;
                }
                p->chunks[i].chunk_id = user_chunk.chunk_id;
                p->chunks[i].length_dw = user_chunk.length_dw;
 
                size = p->chunks[i].length_dw;
-               cdata = (void __user *)user_chunk.chunk_data;
+               cdata = (void __user *)(unsigned long)user_chunk.chunk_data;
                p->chunks[i].user_ptr = cdata;
 
                p->chunks[i].kdata = drm_malloc_ab(size, sizeof(uint32_t));
                if (p->chunks[i].kdata == NULL) {
-                       r = -ENOMEM;
-                       goto out;
+                       ret = -ENOMEM;
+                       i--;
+                       goto free_partial_kdata;
                }
                size *= sizeof(uint32_t);
                if (copy_from_user(p->chunks[i].kdata, cdata, size)) {
-                       r = -EFAULT;
-                       goto out;
+                       ret = -EFAULT;
+                       goto free_partial_kdata;
                }
 
                switch (p->chunks[i].chunk_id) {
@@ -238,15 +240,15 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
                                gobj = drm_gem_object_lookup(p->adev->ddev,
                                                             p->filp, handle);
                                if (gobj == NULL) {
-                                       r = -EINVAL;
-                                       goto out;
+                                       ret = -EINVAL;
+                                       goto free_partial_kdata;
                                }
 
                                p->uf.bo = gem_to_amdgpu_bo(gobj);
                                p->uf.offset = fence_data->offset;
                        } else {
-                               r = -EINVAL;
-                               goto out;
+                               ret = -EINVAL;
+                               goto free_partial_kdata;
                        }
                        break;
 
@@ -254,19 +256,35 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
                        break;
 
                default:
-                       r = -EINVAL;
-                       goto out;
+                       ret = -EINVAL;
+                       goto free_partial_kdata;
                }
        }
 
 
        p->ibs = kcalloc(p->num_ibs, sizeof(struct amdgpu_ib), GFP_KERNEL);
-       if (!p->ibs)
-               r = -ENOMEM;
+       if (!p->ibs) {
+               ret = -ENOMEM;
+               goto free_all_kdata;
+       }
 
-out:
        kfree(chunk_array);
-       return r;
+       return 0;
+
+free_all_kdata:
+       i = p->nchunks - 1;
+free_partial_kdata:
+       for (; i >= 0; i--)
+               drm_free_large(p->chunks[i].kdata);
+       kfree(p->chunks);
+put_bo_list:
+       if (p->bo_list)
+               amdgpu_bo_list_put(p->bo_list);
+       amdgpu_ctx_put(p->ctx);
+free_chunk:
+       kfree(chunk_array);
+
+       return ret;
 }
 
 /* Returns how many bytes TTM can move per IB.
@@ -321,25 +339,17 @@ static u64 amdgpu_cs_get_threshold_for_moves(struct amdgpu_device *adev)
        return max(bytes_moved_threshold, 1024*1024ull);
 }
 
-int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p)
+int amdgpu_cs_list_validate(struct amdgpu_device *adev,
+                           struct amdgpu_vm *vm,
+                           struct list_head *validated)
 {
-       struct amdgpu_fpriv *fpriv = p->filp->driver_priv;
-       struct amdgpu_vm *vm = &fpriv->vm;
-       struct amdgpu_device *adev = p->adev;
        struct amdgpu_bo_list_entry *lobj;
-       struct list_head duplicates;
        struct amdgpu_bo *bo;
        u64 bytes_moved = 0, initial_bytes_moved;
        u64 bytes_moved_threshold = amdgpu_cs_get_threshold_for_moves(adev);
        int r;
 
-       INIT_LIST_HEAD(&duplicates);
-       r = ttm_eu_reserve_buffers(&p->ticket, &p->validated, true, &duplicates);
-       if (unlikely(r != 0)) {
-               return r;
-       }
-
-       list_for_each_entry(lobj, &p->validated, tv.head) {
+       list_for_each_entry(lobj, validated, tv.head) {
                bo = lobj->robj;
                if (!bo->pin_count) {
                        u32 domain = lobj->prefered_domains;
@@ -373,7 +383,6 @@ int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p)
                                        domain = lobj->allowed_domains;
                                        goto retry;
                                }
-                               ttm_eu_backoff_reservation(&p->ticket, &p->validated);
                                return r;
                        }
                }
@@ -386,6 +395,7 @@ static int amdgpu_cs_parser_relocs(struct amdgpu_cs_parser *p)
 {
        struct amdgpu_fpriv *fpriv = p->filp->driver_priv;
        struct amdgpu_cs_buckets buckets;
+       struct list_head duplicates;
        bool need_mmap_lock = false;
        int i, r;
 
@@ -405,8 +415,22 @@ static int amdgpu_cs_parser_relocs(struct amdgpu_cs_parser *p)
        if (need_mmap_lock)
                down_read(&current->mm->mmap_sem);
 
-       r = amdgpu_cs_list_validate(p);
+       INIT_LIST_HEAD(&duplicates);
+       r = ttm_eu_reserve_buffers(&p->ticket, &p->validated, true, &duplicates);
+       if (unlikely(r != 0))
+               goto error_reserve;
+
+       r = amdgpu_cs_list_validate(p->adev, &fpriv->vm, &p->validated);
+       if (r)
+               goto error_validate;
+
+       r = amdgpu_cs_list_validate(p->adev, &fpriv->vm, &duplicates);
+
+error_validate:
+       if (r)
+               ttm_eu_backoff_reservation(&p->ticket, &p->validated);
 
+error_reserve:
        if (need_mmap_lock)
                up_read(&current->mm->mmap_sem);
 
@@ -772,15 +796,15 @@ static int amdgpu_cs_dependencies(struct amdgpu_device *adev,
        return 0;
 }
 
-static int amdgpu_cs_free_job(struct amdgpu_job *sched_job)
+static int amdgpu_cs_free_job(struct amdgpu_job *job)
 {
        int i;
-       if (sched_job->ibs)
-               for (i = 0; i < sched_job->num_ibs; i++)
-                       amdgpu_ib_free(sched_job->adev, &sched_job->ibs[i]);
-       kfree(sched_job->ibs);
-       if (sched_job->uf.bo)
-               drm_gem_object_unreference_unlocked(&sched_job->uf.bo->gem_base);
+       if (job->ibs)
+               for (i = 0; i < job->num_ibs; i++)
+                       amdgpu_ib_free(job->adev, &job->ibs[i]);
+       kfree(job->ibs);
+       if (job->uf.bo)
+               drm_gem_object_unreference_unlocked(&job->uf.bo->gem_base);
        return 0;
 }
 
@@ -804,7 +828,7 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
        r = amdgpu_cs_parser_init(parser, data);
        if (r) {
                DRM_ERROR("Failed to initialize parser !\n");
-               amdgpu_cs_parser_fini(parser, r, false);
+               kfree(parser);
                up_read(&adev->exclusive_lock);
                r = amdgpu_cs_handle_lockup(adev, r);
                return r;
@@ -842,7 +866,7 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
                job = kzalloc(sizeof(struct amdgpu_job), GFP_KERNEL);
                if (!job)
                        return -ENOMEM;
-               job->base.sched = ring->scheduler;
+               job->base.sched = &ring->sched;
                job->base.s_entity = &parser->ctx->rings[ring->idx].entity;
                job->adev = parser->adev;
                job->ibs = parser->ibs;
@@ -857,7 +881,7 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
 
                job->free_job = amdgpu_cs_free_job;
                mutex_lock(&job->job_lock);
-               r = amd_sched_entity_push_job((struct amd_sched_job *)job);
+               r = amd_sched_entity_push_job(&job->base);
                if (r) {
                        mutex_unlock(&job->job_lock);
                        amdgpu_cs_free_job(job);
index 20cbc4eb5a6f7f7bfc75b4c80f010eee061d8499..e0b80ccdfe8ae690e790237b5d6777b30c1d072e 100644 (file)
@@ -43,10 +43,10 @@ int amdgpu_ctx_init(struct amdgpu_device *adev, bool kernel,
                for (i = 0; i < adev->num_rings; i++) {
                        struct amd_sched_rq *rq;
                        if (kernel)
-                               rq = &adev->rings[i]->scheduler->kernel_rq;
+                               rq = &adev->rings[i]->sched.kernel_rq;
                        else
-                               rq = &adev->rings[i]->scheduler->sched_rq;
-                       r = amd_sched_entity_init(adev->rings[i]->scheduler,
+                               rq = &adev->rings[i]->sched.sched_rq;
+                       r = amd_sched_entity_init(&adev->rings[i]->sched,
                                                  &ctx->rings[i].entity,
                                                  rq, amdgpu_sched_jobs);
                        if (r)
@@ -55,7 +55,7 @@ int amdgpu_ctx_init(struct amdgpu_device *adev, bool kernel,
 
                if (i < adev->num_rings) {
                        for (j = 0; j < i; j++)
-                               amd_sched_entity_fini(adev->rings[j]->scheduler,
+                               amd_sched_entity_fini(&adev->rings[j]->sched,
                                                      &ctx->rings[j].entity);
                        kfree(ctx);
                        return r;
@@ -75,7 +75,7 @@ void amdgpu_ctx_fini(struct amdgpu_ctx *ctx)
 
        if (amdgpu_enable_scheduler) {
                for (i = 0; i < adev->num_rings; i++)
-                       amd_sched_entity_fini(adev->rings[i]->scheduler,
+                       amd_sched_entity_fini(&adev->rings[i]->sched,
                                              &ctx->rings[i].entity);
        }
 }
index 6ff6ae945794a24167d6403a48bb8aa57d2fa4a2..6068d8207d108413bdbe3b33035ca85b685e1ec3 100644 (file)
@@ -246,7 +246,7 @@ static int amdgpu_vram_scratch_init(struct amdgpu_device *adev)
                r = amdgpu_bo_create(adev, AMDGPU_GPU_PAGE_SIZE,
                                     PAGE_SIZE, true, AMDGPU_GEM_DOMAIN_VRAM,
                                     AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
-                                    NULL, &adev->vram_scratch.robj);
+                                    NULL, NULL, &adev->vram_scratch.robj);
                if (r) {
                        return r;
                }
@@ -449,7 +449,8 @@ static int amdgpu_wb_init(struct amdgpu_device *adev)
 
        if (adev->wb.wb_obj == NULL) {
                r = amdgpu_bo_create(adev, AMDGPU_MAX_WB * 4, PAGE_SIZE, true,
-                                    AMDGPU_GEM_DOMAIN_GTT, 0,  NULL, &adev->wb.wb_obj);
+                                    AMDGPU_GEM_DOMAIN_GTT, 0,  NULL, NULL,
+                                    &adev->wb.wb_obj);
                if (r) {
                        dev_warn(adev->dev, "(%d) create WB bo failed\n", r);
                        return r;
@@ -1650,9 +1651,11 @@ int amdgpu_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon)
        drm_kms_helper_poll_disable(dev);
 
        /* turn off display hw */
+       drm_modeset_lock_all(dev);
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
                drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
        }
+       drm_modeset_unlock_all(dev);
 
        /* unpin the front buffers */
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
@@ -1747,9 +1750,11 @@ int amdgpu_resume_kms(struct drm_device *dev, bool resume, bool fbcon)
        if (fbcon) {
                drm_helper_resume_force_mode(dev);
                /* turn on display hw */
+               drm_modeset_lock_all(dev);
                list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
                        drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
                }
+               drm_modeset_unlock_all(dev);
        }
 
        drm_kms_helper_poll_enable(dev);
index e3d70772b53104f1f6a48020088d8391d10985b3..6c9e0902a41438920ddfcbdde9408b3792b41b0e 100644 (file)
@@ -85,8 +85,6 @@ static void amdgpu_flip_work_func(struct work_struct *__work)
        /* We borrow the event spin lock for protecting flip_status */
        spin_lock_irqsave(&crtc->dev->event_lock, flags);
 
-       /* set the proper interrupt */
-       amdgpu_irq_get(adev, &adev->pageflip_irq, work->crtc_id);
        /* do the flip (mmio) */
        adev->mode_info.funcs->page_flip(adev, work->crtc_id, work->base);
        /* set the flip status */
@@ -186,10 +184,6 @@ int amdgpu_crtc_page_flip(struct drm_crtc *crtc,
                goto cleanup;
        }
 
-       fence_get(work->excl);
-       for (i = 0; i < work->shared_count; ++i)
-               fence_get(work->shared[i]);
-
        amdgpu_bo_get_tiling_flags(new_rbo, &tiling_flags);
        amdgpu_bo_unreserve(new_rbo);
 
index 0fcc0bd1622cf3e60ce47c8dfcd83db633dc4214..b190c2a83680260dba3cfccca1fa6fad6ee6feae 100644 (file)
@@ -79,6 +79,7 @@ int amdgpu_exp_hw_support = 0;
 int amdgpu_enable_scheduler = 0;
 int amdgpu_sched_jobs = 16;
 int amdgpu_sched_hw_submission = 2;
+int amdgpu_enable_semaphores = 1;
 
 MODULE_PARM_DESC(vramlimit, "Restrict VRAM for testing, in megabytes");
 module_param_named(vramlimit, amdgpu_vram_limit, int, 0600);
@@ -152,6 +153,9 @@ module_param_named(sched_jobs, amdgpu_sched_jobs, int, 0444);
 MODULE_PARM_DESC(sched_hw_submission, "the max number of HW submissions (default 2)");
 module_param_named(sched_hw_submission, amdgpu_sched_hw_submission, int, 0444);
 
+MODULE_PARM_DESC(enable_semaphores, "Enable semaphores (1 = enable (default), 0 = disable)");
+module_param_named(enable_semaphores, amdgpu_enable_semaphores, int, 0644);
+
 static struct pci_device_id pciidlist[] = {
 #ifdef CONFIG_DRM_AMDGPU_CIK
        /* Kaveri */
@@ -238,11 +242,11 @@ static struct pci_device_id pciidlist[] = {
        {0x1002, 0x985F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MULLINS|AMD_IS_MOBILITY|AMD_IS_APU},
 #endif
        /* topaz */
-       {0x1002, 0x6900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ},
-       {0x1002, 0x6901, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ},
-       {0x1002, 0x6902, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ},
-       {0x1002, 0x6903, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ},
-       {0x1002, 0x6907, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ},
+       {0x1002, 0x6900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT},
+       {0x1002, 0x6901, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT},
+       {0x1002, 0x6902, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT},
+       {0x1002, 0x6903, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT},
+       {0x1002, 0x6907, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TOPAZ|AMD_EXP_HW_SUPPORT},
        /* tonga */
        {0x1002, 0x6920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TONGA},
        {0x1002, 0x6921, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TONGA},
index 8a122b1b77861028c123301726b8bb440537ad55..96290d9cddcab6ad8f0e9e8927a71ff97a093c80 100644 (file)
@@ -402,3 +402,19 @@ bool amdgpu_fbdev_robj_is_fb(struct amdgpu_device *adev, struct amdgpu_bo *robj)
                return true;
        return false;
 }
+
+void amdgpu_fbdev_restore_mode(struct amdgpu_device *adev)
+{
+       struct amdgpu_fbdev *afbdev = adev->mode_info.rfbdev;
+       struct drm_fb_helper *fb_helper;
+       int ret;
+
+       if (!afbdev)
+               return;
+
+       fb_helper = &afbdev->helper;
+
+       ret = drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper);
+       if (ret)
+               DRM_DEBUG("failed to restore crtc mode\n");
+}
index 1be2bd6d07eac6593274038967b484d9525f04e3..b3fc26c59787f37acf3daff3d17917abf085e3be 100644 (file)
@@ -609,9 +609,9 @@ int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring,
  * Init the fence driver for the requested ring (all asics).
  * Helper function for amdgpu_fence_driver_init().
  */
-void amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring)
+int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring)
 {
-       int i;
+       int i, r;
 
        ring->fence_drv.cpu_addr = NULL;
        ring->fence_drv.gpu_addr = 0;
@@ -625,15 +625,19 @@ void amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring)
                        amdgpu_fence_check_lockup);
        ring->fence_drv.ring = ring;
 
+       init_waitqueue_head(&ring->fence_drv.fence_queue);
+
        if (amdgpu_enable_scheduler) {
-               ring->scheduler = amd_sched_create(&amdgpu_sched_ops,
-                                                  ring->idx,
-                                                  amdgpu_sched_hw_submission,
-                                                  (void *)ring->adev);
-               if (!ring->scheduler)
-                       DRM_ERROR("Failed to create scheduler on ring %d.\n",
-                                 ring->idx);
+               r = amd_sched_init(&ring->sched, &amdgpu_sched_ops,
+                                  amdgpu_sched_hw_submission, ring->name);
+               if (r) {
+                       DRM_ERROR("Failed to create scheduler on ring %s.\n",
+                                 ring->name);
+                       return r;
+               }
        }
+
+       return 0;
 }
 
 /**
@@ -681,8 +685,7 @@ void amdgpu_fence_driver_fini(struct amdgpu_device *adev)
                wake_up_all(&ring->fence_drv.fence_queue);
                amdgpu_irq_put(adev, ring->fence_drv.irq_src,
                               ring->fence_drv.irq_type);
-               if (ring->scheduler)
-                       amd_sched_destroy(ring->scheduler);
+               amd_sched_fini(&ring->sched);
                ring->fence_drv.initialized = false;
        }
        mutex_unlock(&adev->ring_lock);
index cbd3a486c5c2c0bc8ce29f965dec462eb88f6569..7312d729d30013d3e741f3dbda39f58f7d8d6357 100644 (file)
@@ -127,7 +127,7 @@ int amdgpu_gart_table_vram_alloc(struct amdgpu_device *adev)
                r = amdgpu_bo_create(adev, adev->gart.table_size,
                                     PAGE_SIZE, true, AMDGPU_GEM_DOMAIN_VRAM,
                                     AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
-                                    NULL, &adev->gart.robj);
+                                    NULL, NULL, &adev->gart.robj);
                if (r) {
                        return r;
                }
index 5839fab374bf62dac0a5781a4617da0e5335aafd..7297ca3a0ba795d37bd7f294705411611e2cf2ef 100644 (file)
@@ -69,7 +69,8 @@ int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size,
                }
        }
 retry:
-       r = amdgpu_bo_create(adev, size, alignment, kernel, initial_domain, flags, NULL, &robj);
+       r = amdgpu_bo_create(adev, size, alignment, kernel, initial_domain,
+                            flags, NULL, NULL, &robj);
        if (r) {
                if (r != -ERESTARTSYS) {
                        if (initial_domain == AMDGPU_GEM_DOMAIN_VRAM) {
@@ -426,6 +427,10 @@ int amdgpu_gem_metadata_ioctl(struct drm_device *dev, void *data,
                                           &args->data.data_size_bytes,
                                           &args->data.flags);
        } else if (args->op == AMDGPU_GEM_METADATA_OP_SET_METADATA) {
+               if (args->data.data_size_bytes > sizeof(args->data.data)) {
+                       r = -EINVAL;
+                       goto unreserve;
+               }
                r = amdgpu_bo_set_tiling_flags(robj, args->data.tiling_info);
                if (!r)
                        r = amdgpu_bo_set_metadata(robj, args->data.data,
@@ -433,6 +438,7 @@ int amdgpu_gem_metadata_ioctl(struct drm_device *dev, void *data,
                                                   args->data.flags);
        }
 
+unreserve:
        amdgpu_bo_unreserve(robj);
 out:
        drm_gem_object_unreference_unlocked(gobj);
@@ -454,11 +460,12 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev,
        struct ttm_validate_buffer tv, *entry;
        struct amdgpu_bo_list_entry *vm_bos;
        struct ww_acquire_ctx ticket;
-       struct list_head list;
+       struct list_head list, duplicates;
        unsigned domain;
        int r;
 
        INIT_LIST_HEAD(&list);
+       INIT_LIST_HEAD(&duplicates);
 
        tv.bo = &bo_va->bo->tbo;
        tv.shared = true;
@@ -468,7 +475,8 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev,
        if (!vm_bos)
                return;
 
-       r = ttm_eu_reserve_buffers(&ticket, &list, true, NULL);
+       /* Provide duplicates to avoid -EALREADY */
+       r = ttm_eu_reserve_buffers(&ticket, &list, true, &duplicates);
        if (r)
                goto error_free;
 
@@ -651,7 +659,7 @@ int amdgpu_mode_dumb_create(struct drm_file *file_priv,
        int r;
 
        args->pitch = amdgpu_align_pitch(adev, args->width, args->bpp, 0) * ((args->bpp + 1) / 8);
-       args->size = args->pitch * args->height;
+       args->size = (u64)args->pitch * args->height;
        args->size = ALIGN(args->size, PAGE_SIZE);
 
        r = amdgpu_gem_object_create(adev, args->size, 0,
index 5c8a803acedcb7e798ad5edf8eb797a9b45eca31..534fc04e80fd5a2aeba6aae78862f73be586dbcc 100644 (file)
@@ -43,7 +43,7 @@ static int amdgpu_ih_ring_alloc(struct amdgpu_device *adev)
                r = amdgpu_bo_create(adev, adev->irq.ih.ring_size,
                                     PAGE_SIZE, true,
                                     AMDGPU_GEM_DOMAIN_GTT, 0,
-                                    NULL, &adev->irq.ih.ring_obj);
+                                    NULL, NULL, &adev->irq.ih.ring_obj);
                if (r) {
                        DRM_ERROR("amdgpu: failed to create ih ring buffer (%d).\n", r);
                        return r;
index 0aba8e9bc8a04dfa5251274e653e01d6d584c28f..7c42ff6700809e5783eb92d2de5c678c1e5c6681 100644 (file)
@@ -140,7 +140,7 @@ void amdgpu_irq_preinstall(struct drm_device *dev)
  */
 int amdgpu_irq_postinstall(struct drm_device *dev)
 {
-       dev->max_vblank_count = 0x001fffff;
+       dev->max_vblank_count = 0x00ffffff;
        return 0;
 }
 
index 22367939ebf1ad150cb3fe56a7470f0739d0dbcc..5d11e798230ce759af5d13d5c318aa77cfe755d2 100644 (file)
@@ -390,7 +390,7 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
                                    min((size_t)size, sizeof(vram_gtt))) ? -EFAULT : 0;
        }
        case AMDGPU_INFO_READ_MMR_REG: {
-               unsigned n, alloc_size = info->read_mmr_reg.count * 4;
+               unsigned n, alloc_size;
                uint32_t *regs;
                unsigned se_num = (info->read_mmr_reg.instance >>
                                   AMDGPU_INFO_MMR_SE_INDEX_SHIFT) &
@@ -406,9 +406,10 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
                if (sh_num == AMDGPU_INFO_MMR_SH_INDEX_MASK)
                        sh_num = 0xffffffff;
 
-               regs = kmalloc(alloc_size, GFP_KERNEL);
+               regs = kmalloc_array(info->read_mmr_reg.count, sizeof(*regs), GFP_KERNEL);
                if (!regs)
                        return -ENOMEM;
+               alloc_size = info->read_mmr_reg.count * sizeof(*regs);
 
                for (i = 0; i < info->read_mmr_reg.count; i++)
                        if (amdgpu_asic_read_register(adev, se_num, sh_num,
@@ -484,7 +485,7 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
  * Outdated mess for old drm with Xorg being in charge (void function now).
  */
 /**
- * amdgpu_driver_firstopen_kms - drm callback for last close
+ * amdgpu_driver_lastclose_kms - drm callback for last close
  *
  * @dev: drm dev pointer
  *
@@ -492,6 +493,9 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
  */
 void amdgpu_driver_lastclose_kms(struct drm_device *dev)
 {
+       struct amdgpu_device *adev = dev->dev_private;
+
+       amdgpu_fbdev_restore_mode(adev);
        vga_switcheroo_process_delayed_switch();
 }
 
index 64efe5b52e6500f840f0ad7edbdc6a9f64db6f66..7bd470d9ac30556825260575671c24a3229f28d6 100644 (file)
@@ -567,6 +567,7 @@ void amdgpu_fbdev_fini(struct amdgpu_device *adev);
 void amdgpu_fbdev_set_suspend(struct amdgpu_device *adev, int state);
 int amdgpu_fbdev_total_size(struct amdgpu_device *adev);
 bool amdgpu_fbdev_robj_is_fb(struct amdgpu_device *adev, struct amdgpu_bo *robj);
+void amdgpu_fbdev_restore_mode(struct amdgpu_device *adev);
 
 void amdgpu_fb_output_poll_changed(struct amdgpu_device *adev);
 
index 08b09d55b96fedbe77bfa7a9925e61f8bd3028a5..1a7708f365f37923e747dda4b37e5bd3f0ceb203 100644 (file)
@@ -215,6 +215,7 @@ int amdgpu_bo_create_restricted(struct amdgpu_device *adev,
                                bool kernel, u32 domain, u64 flags,
                                struct sg_table *sg,
                                struct ttm_placement *placement,
+                               struct reservation_object *resv,
                                struct amdgpu_bo **bo_ptr)
 {
        struct amdgpu_bo *bo;
@@ -261,7 +262,7 @@ int amdgpu_bo_create_restricted(struct amdgpu_device *adev,
        /* Kernel allocation are uninterruptible */
        r = ttm_bo_init(&adev->mman.bdev, &bo->tbo, size, type,
                        &bo->placement, page_align, !kernel, NULL,
-                       acc_size, sg, NULL, &amdgpu_ttm_bo_destroy);
+                       acc_size, sg, resv, &amdgpu_ttm_bo_destroy);
        if (unlikely(r != 0)) {
                return r;
        }
@@ -275,7 +276,9 @@ int amdgpu_bo_create_restricted(struct amdgpu_device *adev,
 int amdgpu_bo_create(struct amdgpu_device *adev,
                     unsigned long size, int byte_align,
                     bool kernel, u32 domain, u64 flags,
-                    struct sg_table *sg, struct amdgpu_bo **bo_ptr)
+                    struct sg_table *sg,
+                    struct reservation_object *resv,
+                    struct amdgpu_bo **bo_ptr)
 {
        struct ttm_placement placement = {0};
        struct ttm_place placements[AMDGPU_GEM_DOMAIN_MAX + 1];
@@ -286,11 +289,9 @@ int amdgpu_bo_create(struct amdgpu_device *adev,
        amdgpu_ttm_placement_init(adev, &placement,
                                  placements, domain, flags);
 
-       return amdgpu_bo_create_restricted(adev, size, byte_align,
-                                          kernel, domain, flags,
-                                          sg,
-                                          &placement,
-                                          bo_ptr);
+       return amdgpu_bo_create_restricted(adev, size, byte_align, kernel,
+                                          domain, flags, sg, &placement,
+                                          resv, bo_ptr);
 }
 
 int amdgpu_bo_kmap(struct amdgpu_bo *bo, void **ptr)
@@ -535,12 +536,10 @@ int amdgpu_bo_set_metadata (struct amdgpu_bo *bo, void *metadata,
        if (metadata == NULL)
                return -EINVAL;
 
-       buffer = kzalloc(metadata_size, GFP_KERNEL);
+       buffer = kmemdup(metadata, metadata_size, GFP_KERNEL);
        if (buffer == NULL)
                return -ENOMEM;
 
-       memcpy(buffer, metadata, metadata_size);
-
        kfree(bo->metadata);
        bo->metadata_flags = flags;
        bo->metadata = buffer;
index 6ea18dcec561624bf534dda206719691e7a4f04d..3c2ff4567798e1675adfb7a4563e4bd8931f0565 100644 (file)
@@ -129,12 +129,14 @@ int amdgpu_bo_create(struct amdgpu_device *adev,
                            unsigned long size, int byte_align,
                            bool kernel, u32 domain, u64 flags,
                            struct sg_table *sg,
+                           struct reservation_object *resv,
                            struct amdgpu_bo **bo_ptr);
 int amdgpu_bo_create_restricted(struct amdgpu_device *adev,
                                unsigned long size, int byte_align,
                                bool kernel, u32 domain, u64 flags,
                                struct sg_table *sg,
                                struct ttm_placement *placement,
+                               struct reservation_object *resv,
                                struct amdgpu_bo **bo_ptr);
 int amdgpu_bo_kmap(struct amdgpu_bo *bo, void **ptr);
 void amdgpu_bo_kunmap(struct amdgpu_bo *bo);
index efed11509f4a2326cb5c22b68d20cac77c499705..22a8c7d3a3ab03e9dc3fb294c1f0eb818a6a4880 100644 (file)
@@ -294,10 +294,14 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
        struct amdgpu_device *adev = dev_get_drvdata(dev);
        umode_t effective_mode = attr->mode;
 
-       /* Skip limit attributes if DPM is not enabled */
+       /* Skip attributes if DPM is not enabled */
        if (!adev->pm.dpm_enabled &&
            (attr == &sensor_dev_attr_temp1_crit.dev_attr.attr ||
-            attr == &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr))
+            attr == &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr ||
+            attr == &sensor_dev_attr_pwm1.dev_attr.attr ||
+            attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr ||
+            attr == &sensor_dev_attr_pwm1_max.dev_attr.attr ||
+            attr == &sensor_dev_attr_pwm1_min.dev_attr.attr))
                return 0;
 
        /* Skip fan attributes if fan is not present */
@@ -691,6 +695,9 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
 {
        int ret;
 
+       if (adev->pm.sysfs_initialized)
+               return 0;
+
        if (adev->pm.funcs->get_temperature == NULL)
                return 0;
        adev->pm.int_hwmon_dev = hwmon_device_register_with_groups(adev->dev,
@@ -719,6 +726,8 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
                return ret;
        }
 
+       adev->pm.sysfs_initialized = true;
+
        return 0;
 }
 
index d9652fe32d6aee3b52e3920b57648d4e59f37020..59f735a933a939480e4e000190fe5fc042b1b395 100644 (file)
@@ -61,12 +61,15 @@ struct drm_gem_object *amdgpu_gem_prime_import_sg_table(struct drm_device *dev,
                                                        struct dma_buf_attachment *attach,
                                                        struct sg_table *sg)
 {
+       struct reservation_object *resv = attach->dmabuf->resv;
        struct amdgpu_device *adev = dev->dev_private;
        struct amdgpu_bo *bo;
        int ret;
 
+       ww_mutex_lock(&resv->lock, NULL);
        ret = amdgpu_bo_create(adev, attach->dmabuf->size, PAGE_SIZE, false,
-                              AMDGPU_GEM_DOMAIN_GTT, 0, sg, &bo);
+                              AMDGPU_GEM_DOMAIN_GTT, 0, sg, resv, &bo);
+       ww_mutex_unlock(&resv->lock);
        if (ret)
                return ERR_PTR(ret);
 
index 9bec91484c24ee18001a9c32864f486c51eaaf02..30dce235ddeb4e4f3660338bf5a14d6afa3864c5 100644 (file)
@@ -357,11 +357,11 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
                ring->adev = adev;
                ring->idx = adev->num_rings++;
                adev->rings[ring->idx] = ring;
-               amdgpu_fence_driver_init_ring(ring);
+               r = amdgpu_fence_driver_init_ring(ring);
+               if (r)
+                       return r;
        }
 
-       init_waitqueue_head(&ring->fence_drv.fence_queue);
-
        r = amdgpu_wb_get(adev, &ring->rptr_offs);
        if (r) {
                dev_err(adev->dev, "(%d) ring rptr_offs wb alloc failed\n", r);
@@ -407,7 +407,7 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
        if (ring->ring_obj == NULL) {
                r = amdgpu_bo_create(adev, ring->ring_size, PAGE_SIZE, true,
                                     AMDGPU_GEM_DOMAIN_GTT, 0,
-                                    NULL, &ring->ring_obj);
+                                    NULL, NULL, &ring->ring_obj);
                if (r) {
                        dev_err(adev->dev, "(%d) ring create failed\n", r);
                        return r;
index 74dad270362caea3a0d96c4d05b9dec7eef6e6ae..e90712443fe92ac87bd808ffe65957f8320abb72 100644 (file)
@@ -64,8 +64,8 @@ int amdgpu_sa_bo_manager_init(struct amdgpu_device *adev,
                INIT_LIST_HEAD(&sa_manager->flist[i]);
        }
 
-       r = amdgpu_bo_create(adev, size, align, true,
-                            domain, 0, NULL, &sa_manager->bo);
+       r = amdgpu_bo_create(adev, size, align, true, domain,
+                            0, NULL, NULL, &sa_manager->bo);
        if (r) {
                dev_err(adev->dev, "(%d) failed to allocate bo for manager\n", r);
                return r;
@@ -145,8 +145,13 @@ static uint32_t amdgpu_sa_get_ring_from_fence(struct fence *f)
        struct amd_sched_fence *s_fence;
 
        s_fence = to_amd_sched_fence(f);
-       if (s_fence)
-               return s_fence->scheduler->ring_id;
+       if (s_fence) {
+               struct amdgpu_ring *ring;
+
+               ring = container_of(s_fence->sched, struct amdgpu_ring, sched);
+               return ring->idx;
+       }
+
        a_fence = to_amdgpu_fence(f);
        if (a_fence)
                return a_fence->ring->idx;
@@ -412,6 +417,26 @@ void amdgpu_sa_bo_free(struct amdgpu_device *adev, struct amdgpu_sa_bo **sa_bo,
 }
 
 #if defined(CONFIG_DEBUG_FS)
+
+static void amdgpu_sa_bo_dump_fence(struct fence *fence, struct seq_file *m)
+{
+       struct amdgpu_fence *a_fence = to_amdgpu_fence(fence);
+       struct amd_sched_fence *s_fence = to_amd_sched_fence(fence);
+
+       if (a_fence)
+               seq_printf(m, " protected by 0x%016llx on ring %d",
+                          a_fence->seq, a_fence->ring->idx);
+
+       if (s_fence) {
+               struct amdgpu_ring *ring;
+
+
+               ring = container_of(s_fence->sched, struct amdgpu_ring, sched);
+               seq_printf(m, " protected by 0x%016x on ring %d",
+                          s_fence->base.seqno, ring->idx);
+       }
+}
+
 void amdgpu_sa_bo_dump_debug_info(struct amdgpu_sa_manager *sa_manager,
                                  struct seq_file *m)
 {
@@ -428,18 +453,8 @@ void amdgpu_sa_bo_dump_debug_info(struct amdgpu_sa_manager *sa_manager,
                }
                seq_printf(m, "[0x%010llx 0x%010llx] size %8lld",
                           soffset, eoffset, eoffset - soffset);
-               if (i->fence) {
-                       struct amdgpu_fence *a_fence = to_amdgpu_fence(i->fence);
-                       struct amd_sched_fence *s_fence = to_amd_sched_fence(i->fence);
-                       if (a_fence)
-                               seq_printf(m, " protected by 0x%016llx on ring %d",
-                                          a_fence->seq, a_fence->ring->idx);
-                       if (s_fence)
-                               seq_printf(m, " protected by 0x%016x on ring %d",
-                                          s_fence->base.seqno,
-                                          s_fence->scheduler->ring_id);
-
-               }
+               if (i->fence)
+                       amdgpu_sa_bo_dump_fence(i->fence, m);
                seq_printf(m, "\n");
        }
        spin_unlock(&sa_manager->wq.lock);
index de98fbd2971eded37ecb896921255d38787ce7b5..2e946b2cad8878405ec6a03f6512233dbbf93348 100644 (file)
 #include <drm/drmP.h>
 #include "amdgpu.h"
 
-static struct fence *amdgpu_sched_dependency(struct amd_sched_job *job)
+static struct fence *amdgpu_sched_dependency(struct amd_sched_job *sched_job)
 {
-       struct amdgpu_job *sched_job = (struct amdgpu_job *)job;
-       return amdgpu_sync_get_fence(&sched_job->ibs->sync);
+       struct amdgpu_job *job = to_amdgpu_job(sched_job);
+       return amdgpu_sync_get_fence(&job->ibs->sync);
 }
 
-static struct fence *amdgpu_sched_run_job(struct amd_sched_job *job)
+static struct fence *amdgpu_sched_run_job(struct amd_sched_job *sched_job)
 {
-       struct amdgpu_job *sched_job;
-       struct amdgpu_fence *fence;
+       struct amdgpu_fence *fence = NULL;
+       struct amdgpu_job *job;
        int r;
 
-       if (!job) {
+       if (!sched_job) {
                DRM_ERROR("job is null\n");
                return NULL;
        }
-       sched_job = (struct amdgpu_job *)job;
-       mutex_lock(&sched_job->job_lock);
-       r = amdgpu_ib_schedule(sched_job->adev,
-                              sched_job->num_ibs,
-                              sched_job->ibs,
-                              sched_job->base.owner);
-       if (r)
+       job = to_amdgpu_job(sched_job);
+       mutex_lock(&job->job_lock);
+       r = amdgpu_ib_schedule(job->adev,
+                              job->num_ibs,
+                              job->ibs,
+                              job->base.owner);
+       if (r) {
+               DRM_ERROR("Error scheduling IBs (%d)\n", r);
                goto err;
-       fence = amdgpu_fence_ref(sched_job->ibs[sched_job->num_ibs - 1].fence);
-
-       if (sched_job->free_job)
-               sched_job->free_job(sched_job);
+       }
 
-       mutex_unlock(&sched_job->job_lock);
-       return &fence->base;
+       fence = amdgpu_fence_ref(job->ibs[job->num_ibs - 1].fence);
 
 err:
-       DRM_ERROR("Run job error\n");
-       mutex_unlock(&sched_job->job_lock);
-       job->sched->ops->process_job(job);
-       return NULL;
-}
+       if (job->free_job)
+               job->free_job(job);
 
-static void amdgpu_sched_process_job(struct amd_sched_job *job)
-{
-       struct amdgpu_job *sched_job;
-
-       if (!job) {
-               DRM_ERROR("job is null\n");
-               return;
-       }
-       sched_job = (struct amdgpu_job *)job;
-       /* after processing job, free memory */
-       fence_put(&sched_job->base.s_fence->base);
-       kfree(sched_job);
+       mutex_unlock(&job->job_lock);
+       fence_put(&job->base.s_fence->base);
+       kfree(job);
+       return fence ? &fence->base : NULL;
 }
 
 struct amd_sched_backend_ops amdgpu_sched_ops = {
        .dependency = amdgpu_sched_dependency,
        .run_job = amdgpu_sched_run_job,
-       .process_job = amdgpu_sched_process_job
 };
 
 int amdgpu_sched_ib_submit_kernel_helper(struct amdgpu_device *adev,
@@ -100,7 +85,7 @@ int amdgpu_sched_ib_submit_kernel_helper(struct amdgpu_device *adev,
                        kzalloc(sizeof(struct amdgpu_job), GFP_KERNEL);
                if (!job)
                        return -ENOMEM;
-               job->base.sched = ring->scheduler;
+               job->base.sched = &ring->sched;
                job->base.s_entity = &adev->kernel_ctx.rings[ring->idx].entity;
                job->adev = adev;
                job->ibs = ibs;
@@ -109,7 +94,7 @@ int amdgpu_sched_ib_submit_kernel_helper(struct amdgpu_device *adev,
                mutex_init(&job->job_lock);
                job->free_job = free_job;
                mutex_lock(&job->job_lock);
-               r = amd_sched_entity_push_job((struct amd_sched_job *)job);
+               r = amd_sched_entity_push_job(&job->base);
                if (r) {
                        mutex_unlock(&job->job_lock);
                        kfree(job);
index 068aeaff7183b8227f0a27873af71213ac968e30..4921de15b45158fe89af11d540eebcf998e2983c 100644 (file)
@@ -65,8 +65,14 @@ static bool amdgpu_sync_same_dev(struct amdgpu_device *adev, struct fence *f)
 
        if (a_fence)
                return a_fence->ring->adev == adev;
-       if (s_fence)
-               return (struct amdgpu_device *)s_fence->scheduler->priv == adev;
+
+       if (s_fence) {
+               struct amdgpu_ring *ring;
+
+               ring = container_of(s_fence->sched, struct amdgpu_ring, sched);
+               return ring->adev == adev;
+       }
+
        return false;
 }
 
@@ -251,6 +257,20 @@ int amdgpu_sync_wait(struct amdgpu_sync *sync)
                fence_put(e->fence);
                kfree(e);
        }
+
+       if (amdgpu_enable_semaphores)
+               return 0;
+
+       for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
+               struct amdgpu_fence *fence = sync->sync_to[i];
+               if (!fence)
+                       continue;
+
+               r = fence_wait(&fence->base, false);
+               if (r)
+                       return r;
+       }
+
        return 0;
 }
 
@@ -285,7 +305,8 @@ int amdgpu_sync_rings(struct amdgpu_sync *sync,
                        return -EINVAL;
                }
 
-               if (amdgpu_enable_scheduler || (count >= AMDGPU_NUM_SYNCS)) {
+               if (amdgpu_enable_scheduler || !amdgpu_enable_semaphores ||
+                   (count >= AMDGPU_NUM_SYNCS)) {
                        /* not enough room, wait manually */
                        r = fence_wait(&fence->base, false);
                        if (r)
index f80b1a43be8a549aaec7febbcf5df8f2ec3de702..4865615e9c0669d0c2699c7ffd0ae8d11f69b527 100644 (file)
@@ -59,8 +59,9 @@ static void amdgpu_do_test_moves(struct amdgpu_device *adev)
                goto out_cleanup;
        }
 
-       r = amdgpu_bo_create(adev, size, PAGE_SIZE, true, AMDGPU_GEM_DOMAIN_VRAM, 0,
-                            NULL, &vram_obj);
+       r = amdgpu_bo_create(adev, size, PAGE_SIZE, true,
+                            AMDGPU_GEM_DOMAIN_VRAM, 0,
+                            NULL, NULL, &vram_obj);
        if (r) {
                DRM_ERROR("Failed to create VRAM object\n");
                goto out_cleanup;
@@ -80,7 +81,8 @@ static void amdgpu_do_test_moves(struct amdgpu_device *adev)
                struct fence *fence = NULL;
 
                r = amdgpu_bo_create(adev, size, PAGE_SIZE, true,
-                                    AMDGPU_GEM_DOMAIN_GTT, 0, NULL, gtt_obj + i);
+                                    AMDGPU_GEM_DOMAIN_GTT, 0, NULL,
+                                    NULL, gtt_obj + i);
                if (r) {
                        DRM_ERROR("Failed to create GTT object %d\n", i);
                        goto out_lclean;
index b5abd5cde413ffaa42934aa0bf4a731ec8bb8fe2..364cbe97533298d45e9087d322c35f7c3923b52a 100644 (file)
@@ -861,7 +861,7 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
        r = amdgpu_bo_create(adev, 256 * 1024, PAGE_SIZE, true,
                             AMDGPU_GEM_DOMAIN_VRAM,
                             AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
-                            NULL, &adev->stollen_vga_memory);
+                            NULL, NULL, &adev->stollen_vga_memory);
        if (r) {
                return r;
        }
index 482e66797ae6eeae7581492e637b115aa26c3624..5cc95f1a7dab955ea39f93f0dbb1110129c582d0 100644 (file)
@@ -247,7 +247,7 @@ int amdgpu_ucode_init_bo(struct amdgpu_device *adev)
        const struct common_firmware_header *header = NULL;
 
        err = amdgpu_bo_create(adev, adev->firmware.fw_size, PAGE_SIZE, true,
-                       AMDGPU_GEM_DOMAIN_GTT, 0, NULL, bo);
+                       AMDGPU_GEM_DOMAIN_GTT, 0, NULL, NULL, bo);
        if (err) {
                dev_err(adev->dev, "(%d) Firmware buffer allocate failed\n", err);
                err = -ENOMEM;
index 2cf6c6b06e3b157b756fc978126361257becbacc..d0312364d950bec9968c220f876fd0f24b1ebe16 100644 (file)
@@ -156,7 +156,7 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev)
        r = amdgpu_bo_create(adev, bo_size, PAGE_SIZE, true,
                             AMDGPU_GEM_DOMAIN_VRAM,
                             AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
-                            NULL, &adev->uvd.vcpu_bo);
+                            NULL, NULL, &adev->uvd.vcpu_bo);
        if (r) {
                dev_err(adev->dev, "(%d) failed to allocate UVD bo\n", r);
                return r;
@@ -543,46 +543,60 @@ static int amdgpu_uvd_cs_msg(struct amdgpu_uvd_cs_ctx *ctx,
                return -EINVAL;
        }
 
-       if (msg_type == 1) {
+       switch (msg_type) {
+       case 0:
+               /* it's a create msg, calc image size (width * height) */
+               amdgpu_bo_kunmap(bo);
+
+               /* try to alloc a new handle */
+               for (i = 0; i < AMDGPU_MAX_UVD_HANDLES; ++i) {
+                       if (atomic_read(&adev->uvd.handles[i]) == handle) {
+                               DRM_ERROR("Handle 0x%x already in use!\n", handle);
+                               return -EINVAL;
+                       }
+
+                       if (!atomic_cmpxchg(&adev->uvd.handles[i], 0, handle)) {
+                               adev->uvd.filp[i] = ctx->parser->filp;
+                               return 0;
+                       }
+               }
+
+               DRM_ERROR("No more free UVD handles!\n");
+               return -EINVAL;
+
+       case 1:
                /* it's a decode msg, calc buffer sizes */
                r = amdgpu_uvd_cs_msg_decode(msg, ctx->buf_sizes);
                amdgpu_bo_kunmap(bo);
                if (r)
                        return r;
 
-       } else if (msg_type == 2) {
+               /* validate the handle */
+               for (i = 0; i < AMDGPU_MAX_UVD_HANDLES; ++i) {
+                       if (atomic_read(&adev->uvd.handles[i]) == handle) {
+                               if (adev->uvd.filp[i] != ctx->parser->filp) {
+                                       DRM_ERROR("UVD handle collision detected!\n");
+                                       return -EINVAL;
+                               }
+                               return 0;
+                       }
+               }
+
+               DRM_ERROR("Invalid UVD handle 0x%x!\n", handle);
+               return -ENOENT;
+
+       case 2:
                /* it's a destroy msg, free the handle */
                for (i = 0; i < AMDGPU_MAX_UVD_HANDLES; ++i)
                        atomic_cmpxchg(&adev->uvd.handles[i], handle, 0);
                amdgpu_bo_kunmap(bo);
                return 0;
-       } else {
-               /* it's a create msg */
-               amdgpu_bo_kunmap(bo);
-
-               if (msg_type != 0) {
-                       DRM_ERROR("Illegal UVD message type (%d)!\n", msg_type);
-                       return -EINVAL;
-               }
-
-               /* it's a create msg, no special handling needed */
-       }
-
-       /* create or decode, validate the handle */
-       for (i = 0; i < AMDGPU_MAX_UVD_HANDLES; ++i) {
-               if (atomic_read(&adev->uvd.handles[i]) == handle)
-                       return 0;
-       }
 
-       /* handle not found try to alloc a new one */
-       for (i = 0; i < AMDGPU_MAX_UVD_HANDLES; ++i) {
-               if (!atomic_cmpxchg(&adev->uvd.handles[i], 0, handle)) {
-                       adev->uvd.filp[i] = ctx->parser->filp;
-                       return 0;
-               }
+       default:
+               DRM_ERROR("Illegal UVD message type (%d)!\n", msg_type);
+               return -EINVAL;
        }
-
-       DRM_ERROR("No more free UVD handles!\n");
+       BUG();
        return -EINVAL;
 }
 
@@ -805,10 +819,10 @@ int amdgpu_uvd_ring_parse_cs(struct amdgpu_cs_parser *parser, uint32_t ib_idx)
 }
 
 static int amdgpu_uvd_free_job(
-       struct amdgpu_job *sched_job)
+       struct amdgpu_job *job)
 {
-       amdgpu_ib_free(sched_job->adev, sched_job->ibs);
-       kfree(sched_job->ibs);
+       amdgpu_ib_free(job->adev, job->ibs);
+       kfree(job->ibs);
        return 0;
 }
 
@@ -905,7 +919,7 @@ int amdgpu_uvd_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
        r = amdgpu_bo_create(adev, 1024, PAGE_SIZE, true,
                             AMDGPU_GEM_DOMAIN_VRAM,
                             AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
-                            NULL, &bo);
+                            NULL, NULL, &bo);
        if (r)
                return r;
 
@@ -954,7 +968,7 @@ int amdgpu_uvd_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
        r = amdgpu_bo_create(adev, 1024, PAGE_SIZE, true,
                             AMDGPU_GEM_DOMAIN_VRAM,
                             AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
-                            NULL, &bo);
+                            NULL, NULL, &bo);
        if (r)
                return r;
 
index 3cab96c42aa8843487190248b98d999fb6b3598c..74f2038ac74783a3be14be55a7b0de7e768d61c7 100644 (file)
@@ -143,7 +143,7 @@ int amdgpu_vce_sw_init(struct amdgpu_device *adev, unsigned long size)
        r = amdgpu_bo_create(adev, size, PAGE_SIZE, true,
                             AMDGPU_GEM_DOMAIN_VRAM,
                             AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
-                            NULL, &adev->vce.vcpu_bo);
+                            NULL, NULL, &adev->vce.vcpu_bo);
        if (r) {
                dev_err(adev->dev, "(%d) failed to allocate VCE bo\n", r);
                return r;
@@ -342,10 +342,10 @@ void amdgpu_vce_free_handles(struct amdgpu_device *adev, struct drm_file *filp)
 }
 
 static int amdgpu_vce_free_job(
-       struct amdgpu_job *sched_job)
+       struct amdgpu_job *job)
 {
-       amdgpu_ib_free(sched_job->adev, sched_job->ibs);
-       kfree(sched_job->ibs);
+       amdgpu_ib_free(job->adev, job->ibs);
+       kfree(job->ibs);
        return 0;
 }
 
index f68b7cdc370a8694bb489e97c82d27e490e3c3b0..53d551f2d8395ccc24dc799887160e0977419ef2 100644 (file)
@@ -316,12 +316,12 @@ static void amdgpu_vm_update_pages(struct amdgpu_device *adev,
        }
 }
 
-int amdgpu_vm_free_job(struct amdgpu_job *sched_job)
+int amdgpu_vm_free_job(struct amdgpu_job *job)
 {
        int i;
-       for (i = 0; i < sched_job->num_ibs; i++)
-               amdgpu_ib_free(sched_job->adev, &sched_job->ibs[i]);
-       kfree(sched_job->ibs);
+       for (i = 0; i < job->num_ibs; i++)
+               amdgpu_ib_free(job->adev, &job->ibs[i]);
+       kfree(job->ibs);
        return 0;
 }
 
@@ -455,8 +455,10 @@ int amdgpu_vm_update_page_directory(struct amdgpu_device *adev,
                return -ENOMEM;
 
        r = amdgpu_ib_get(ring, NULL, ndw * 4, ib);
-       if (r)
+       if (r) {
+               kfree(ib);
                return r;
+       }
        ib->length_dw = 0;
 
        /* walk over the address space and update the page directory */
@@ -685,31 +687,6 @@ static int amdgpu_vm_update_ptes(struct amdgpu_device *adev,
        return 0;
 }
 
-/**
- * amdgpu_vm_fence_pts - fence page tables after an update
- *
- * @vm: requested vm
- * @start: start of GPU address range
- * @end: end of GPU address range
- * @fence: fence to use
- *
- * Fence the page tables in the range @start - @end (cayman+).
- *
- * Global and local mutex must be locked!
- */
-static void amdgpu_vm_fence_pts(struct amdgpu_vm *vm,
-                               uint64_t start, uint64_t end,
-                               struct fence *fence)
-{
-       unsigned i;
-
-       start >>= amdgpu_vm_block_size;
-       end >>= amdgpu_vm_block_size;
-
-       for (i = start; i <= end; ++i)
-               amdgpu_bo_fence(vm->page_tables[i].bo, fence, true);
-}
-
 /**
  * amdgpu_vm_bo_update_mapping - update a mapping in the vm page table
  *
@@ -813,8 +790,7 @@ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev,
        if (r)
                goto error_free;
 
-       amdgpu_vm_fence_pts(vm, mapping->it.start,
-                           mapping->it.last + 1, f);
+       amdgpu_bo_fence(vm->page_directory, f, true);
        if (fence) {
                fence_put(*fence);
                *fence = fence_get(f);
@@ -855,7 +831,7 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev,
        int r;
 
        if (mem) {
-               addr = mem->start << PAGE_SHIFT;
+               addr = (u64)mem->start << PAGE_SHIFT;
                if (mem->mem_type != TTM_PL_TT)
                        addr += adev->vm_manager.vram_base_offset;
        } else {
@@ -1089,6 +1065,7 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
 
        /* walk over the address space and allocate the page tables */
        for (pt_idx = saddr; pt_idx <= eaddr; ++pt_idx) {
+               struct reservation_object *resv = vm->page_directory->tbo.resv;
                struct amdgpu_bo *pt;
 
                if (vm->page_tables[pt_idx].bo)
@@ -1097,11 +1074,13 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
                /* drop mutex to allocate and clear page table */
                mutex_unlock(&vm->mutex);
 
+               ww_mutex_lock(&resv->lock, NULL);
                r = amdgpu_bo_create(adev, AMDGPU_VM_PTE_COUNT * 8,
                                     AMDGPU_GPU_PAGE_SIZE, true,
                                     AMDGPU_GEM_DOMAIN_VRAM,
                                     AMDGPU_GEM_CREATE_NO_CPU_ACCESS,
-                                    NULL, &pt);
+                                    NULL, resv, &pt);
+               ww_mutex_unlock(&resv->lock);
                if (r)
                        goto error_free;
 
@@ -1303,7 +1282,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm)
        r = amdgpu_bo_create(adev, pd_size, align, true,
                             AMDGPU_GEM_DOMAIN_VRAM,
                             AMDGPU_GEM_CREATE_NO_CPU_ACCESS,
-                            NULL, &vm->page_directory);
+                            NULL, NULL, &vm->page_directory);
        if (r)
                return r;
 
index cd6edc40c9cd0c3dc2f09e96a2207f35e8b53d28..1e0bba29e16796f97c8eee38fc9d3100c405f6bc 100644 (file)
@@ -1279,8 +1279,7 @@ amdgpu_atombios_encoder_setup_dig(struct drm_encoder *encoder, int action)
                        amdgpu_atombios_encoder_setup_dig_encoder(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0);
                }
                if (amdgpu_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
-                       amdgpu_atombios_encoder_setup_dig_transmitter(encoder,
-                                                              ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
+                       amdgpu_atombios_encoder_set_backlight_level(amdgpu_encoder, dig->backlight_level);
                if (ext_encoder)
                        amdgpu_atombios_encoder_setup_external_encoder(encoder, ext_encoder, ATOM_ENABLE);
        } else {
index 82e8d073051759f7b0307b7675282a8dfea280e8..a1a35a5df8e71357eea132019d3500a35a89fce4 100644 (file)
@@ -6185,6 +6185,11 @@ static int ci_dpm_late_init(void *handle)
        if (!amdgpu_dpm)
                return 0;
 
+       /* init the sysfs and debugfs files late */
+       ret = amdgpu_pm_sysfs_init(adev);
+       if (ret)
+               return ret;
+
        ret = ci_set_temperature_range(adev);
        if (ret)
                return ret;
@@ -6232,9 +6237,6 @@ static int ci_dpm_sw_init(void *handle)
        adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps;
        if (amdgpu_dpm == 1)
                amdgpu_pm_print_power_states(adev);
-       ret = amdgpu_pm_sysfs_init(adev);
-       if (ret)
-               goto dpm_failed;
        mutex_unlock(&adev->pm.mutex);
        DRM_INFO("amdgpu: dpm initialized\n");
 
index 4b6ce74753cded5179b17eaf698ddd16766760b1..484710cfdf8243d563afe908c2b9c9884879f971 100644 (file)
@@ -1567,6 +1567,9 @@ static void cik_pcie_gen3_enable(struct amdgpu_device *adev)
        int ret, i;
        u16 tmp16;
 
+       if (pci_is_root_bus(adev->pdev->bus))
+               return;
+
        if (amdgpu_pcie_gen2 == 0)
                return;
 
index 44fa96ad47099b765ac81e5c439766a8f9849392..2e3373ed4c942d9fc753851d50adb9a3034ebff8 100644 (file)
@@ -596,6 +596,12 @@ static int cz_dpm_late_init(void *handle)
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
        if (amdgpu_dpm) {
+               int ret;
+               /* init the sysfs and debugfs files late */
+               ret = amdgpu_pm_sysfs_init(adev);
+               if (ret)
+                       return ret;
+
                /* powerdown unused blocks for now */
                cz_dpm_powergate_uvd(adev, true);
                cz_dpm_powergate_vce(adev, true);
@@ -632,10 +638,6 @@ static int cz_dpm_sw_init(void *handle)
        if (amdgpu_dpm == 1)
                amdgpu_pm_print_power_states(adev);
 
-       ret = amdgpu_pm_sysfs_init(adev);
-       if (ret)
-               goto dpm_init_failed;
-
        mutex_unlock(&adev->pm.mutex);
        DRM_INFO("amdgpu: dpm initialized\n");
 
index a72ffc7d6c26dde601bb5c28590d79a9d9827208..e33180d3314a306269004fc8612608ff153039d3 100644 (file)
@@ -814,7 +814,8 @@ int cz_smu_init(struct amdgpu_device *adev)
        * 3. map kernel virtual address
        */
        ret = amdgpu_bo_create(adev, priv->toc_buffer.data_size, PAGE_SIZE,
-                               true, AMDGPU_GEM_DOMAIN_GTT, 0, NULL, toc_buf);
+                              true, AMDGPU_GEM_DOMAIN_GTT, 0, NULL, NULL,
+                              toc_buf);
 
        if (ret) {
                dev_err(adev->dev, "(%d) SMC TOC buffer allocation failed\n", ret);
@@ -822,7 +823,8 @@ int cz_smu_init(struct amdgpu_device *adev)
        }
 
        ret = amdgpu_bo_create(adev, priv->smu_buffer.data_size, PAGE_SIZE,
-                               true, AMDGPU_GEM_DOMAIN_GTT, 0, NULL, smu_buf);
+                              true, AMDGPU_GEM_DOMAIN_GTT, 0, NULL, NULL,
+                              smu_buf);
 
        if (ret) {
                dev_err(adev->dev, "(%d) SMC Internal buffer allocation failed\n", ret);
index e4d101b1252a47eaf7a2c7e35c2d8d83f737d762..d4c82b6257273475d15c3274cda7a30404fca231 100644 (file)
@@ -255,6 +255,24 @@ static u32 dce_v10_0_vblank_get_counter(struct amdgpu_device *adev, int crtc)
                return RREG32(mmCRTC_STATUS_FRAME_COUNT + crtc_offsets[crtc]);
 }
 
+static void dce_v10_0_pageflip_interrupt_init(struct amdgpu_device *adev)
+{
+       unsigned i;
+
+       /* Enable pflip interrupts */
+       for (i = 0; i < adev->mode_info.num_crtc; i++)
+               amdgpu_irq_get(adev, &adev->pageflip_irq, i);
+}
+
+static void dce_v10_0_pageflip_interrupt_fini(struct amdgpu_device *adev)
+{
+       unsigned i;
+
+       /* Disable pflip interrupts */
+       for (i = 0; i < adev->mode_info.num_crtc; i++)
+               amdgpu_irq_put(adev, &adev->pageflip_irq, i);
+}
+
 /**
  * dce_v10_0_page_flip - pageflip callback.
  *
@@ -2663,9 +2681,10 @@ static void dce_v10_0_crtc_dpms(struct drm_crtc *crtc, int mode)
                dce_v10_0_vga_enable(crtc, true);
                amdgpu_atombios_crtc_blank(crtc, ATOM_DISABLE);
                dce_v10_0_vga_enable(crtc, false);
-               /* Make sure VBLANK interrupt is still enabled */
+               /* Make sure VBLANK and PFLIP interrupts are still enabled */
                type = amdgpu_crtc_idx_to_irq_type(adev, amdgpu_crtc->crtc_id);
                amdgpu_irq_update(adev, &adev->crtc_irq, type);
+               amdgpu_irq_update(adev, &adev->pageflip_irq, type);
                drm_vblank_post_modeset(dev, amdgpu_crtc->crtc_id);
                dce_v10_0_crtc_load_lut(crtc);
                break;
@@ -3025,6 +3044,8 @@ static int dce_v10_0_hw_init(void *handle)
                dce_v10_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false);
        }
 
+       dce_v10_0_pageflip_interrupt_init(adev);
+
        return 0;
 }
 
@@ -3039,6 +3060,8 @@ static int dce_v10_0_hw_fini(void *handle)
                dce_v10_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false);
        }
 
+       dce_v10_0_pageflip_interrupt_fini(adev);
+
        return 0;
 }
 
@@ -3050,6 +3073,8 @@ static int dce_v10_0_suspend(void *handle)
 
        dce_v10_0_hpd_fini(adev);
 
+       dce_v10_0_pageflip_interrupt_fini(adev);
+
        return 0;
 }
 
@@ -3075,6 +3100,8 @@ static int dce_v10_0_resume(void *handle)
        /* initialize hpd */
        dce_v10_0_hpd_init(adev);
 
+       dce_v10_0_pageflip_interrupt_init(adev);
+
        return 0;
 }
 
@@ -3369,7 +3396,6 @@ static int dce_v10_0_pageflip_irq(struct amdgpu_device *adev,
        spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
 
        drm_vblank_put(adev->ddev, amdgpu_crtc->crtc_id);
-       amdgpu_irq_put(adev, &adev->pageflip_irq, crtc_id);
        queue_work(amdgpu_crtc->pflip_queue, &works->unpin_work);
 
        return 0;
index 6411e824467164831eef8af634051f95b8faba69..7e1cf5e4eebf468dfd7c6fc0d97aeccb805e0fbe 100644 (file)
@@ -233,6 +233,24 @@ static u32 dce_v11_0_vblank_get_counter(struct amdgpu_device *adev, int crtc)
                return RREG32(mmCRTC_STATUS_FRAME_COUNT + crtc_offsets[crtc]);
 }
 
+static void dce_v11_0_pageflip_interrupt_init(struct amdgpu_device *adev)
+{
+       unsigned i;
+
+       /* Enable pflip interrupts */
+       for (i = 0; i < adev->mode_info.num_crtc; i++)
+               amdgpu_irq_get(adev, &adev->pageflip_irq, i);
+}
+
+static void dce_v11_0_pageflip_interrupt_fini(struct amdgpu_device *adev)
+{
+       unsigned i;
+
+       /* Disable pflip interrupts */
+       for (i = 0; i < adev->mode_info.num_crtc; i++)
+               amdgpu_irq_put(adev, &adev->pageflip_irq, i);
+}
+
 /**
  * dce_v11_0_page_flip - pageflip callback.
  *
@@ -2640,9 +2658,10 @@ static void dce_v11_0_crtc_dpms(struct drm_crtc *crtc, int mode)
                dce_v11_0_vga_enable(crtc, true);
                amdgpu_atombios_crtc_blank(crtc, ATOM_DISABLE);
                dce_v11_0_vga_enable(crtc, false);
-               /* Make sure VBLANK interrupt is still enabled */
+               /* Make sure VBLANK and PFLIP interrupts are still enabled */
                type = amdgpu_crtc_idx_to_irq_type(adev, amdgpu_crtc->crtc_id);
                amdgpu_irq_update(adev, &adev->crtc_irq, type);
+               amdgpu_irq_update(adev, &adev->pageflip_irq, type);
                drm_vblank_post_modeset(dev, amdgpu_crtc->crtc_id);
                dce_v11_0_crtc_load_lut(crtc);
                break;
@@ -2888,7 +2907,7 @@ static int dce_v11_0_early_init(void *handle)
 
        switch (adev->asic_type) {
        case CHIP_CARRIZO:
-               adev->mode_info.num_crtc = 4;
+               adev->mode_info.num_crtc = 3;
                adev->mode_info.num_hpd = 6;
                adev->mode_info.num_dig = 9;
                break;
@@ -3000,6 +3019,8 @@ static int dce_v11_0_hw_init(void *handle)
                dce_v11_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false);
        }
 
+       dce_v11_0_pageflip_interrupt_init(adev);
+
        return 0;
 }
 
@@ -3014,6 +3035,8 @@ static int dce_v11_0_hw_fini(void *handle)
                dce_v11_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false);
        }
 
+       dce_v11_0_pageflip_interrupt_fini(adev);
+
        return 0;
 }
 
@@ -3025,6 +3048,8 @@ static int dce_v11_0_suspend(void *handle)
 
        dce_v11_0_hpd_fini(adev);
 
+       dce_v11_0_pageflip_interrupt_fini(adev);
+
        return 0;
 }
 
@@ -3051,6 +3076,8 @@ static int dce_v11_0_resume(void *handle)
        /* initialize hpd */
        dce_v11_0_hpd_init(adev);
 
+       dce_v11_0_pageflip_interrupt_init(adev);
+
        return 0;
 }
 
@@ -3345,7 +3372,6 @@ static int dce_v11_0_pageflip_irq(struct amdgpu_device *adev,
        spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
 
        drm_vblank_put(adev->ddev, amdgpu_crtc->crtc_id);
-       amdgpu_irq_put(adev, &adev->pageflip_irq, crtc_id);
        queue_work(amdgpu_crtc->pflip_queue, &works->unpin_work);
 
        return 0;
index c86911c2ea2a896f414473f798d782e9c08518cf..34b9c2a9d8d489c7958af39e0fdbd4e484a572c6 100644 (file)
@@ -204,6 +204,24 @@ static u32 dce_v8_0_vblank_get_counter(struct amdgpu_device *adev, int crtc)
                return RREG32(mmCRTC_STATUS_FRAME_COUNT + crtc_offsets[crtc]);
 }
 
+static void dce_v8_0_pageflip_interrupt_init(struct amdgpu_device *adev)
+{
+       unsigned i;
+
+       /* Enable pflip interrupts */
+       for (i = 0; i < adev->mode_info.num_crtc; i++)
+               amdgpu_irq_get(adev, &adev->pageflip_irq, i);
+}
+
+static void dce_v8_0_pageflip_interrupt_fini(struct amdgpu_device *adev)
+{
+       unsigned i;
+
+       /* Disable pflip interrupts */
+       for (i = 0; i < adev->mode_info.num_crtc; i++)
+               amdgpu_irq_put(adev, &adev->pageflip_irq, i);
+}
+
 /**
  * dce_v8_0_page_flip - pageflip callback.
  *
@@ -2575,9 +2593,10 @@ static void dce_v8_0_crtc_dpms(struct drm_crtc *crtc, int mode)
                dce_v8_0_vga_enable(crtc, true);
                amdgpu_atombios_crtc_blank(crtc, ATOM_DISABLE);
                dce_v8_0_vga_enable(crtc, false);
-               /* Make sure VBLANK interrupt is still enabled */
+               /* Make sure VBLANK and PFLIP interrupts are still enabled */
                type = amdgpu_crtc_idx_to_irq_type(adev, amdgpu_crtc->crtc_id);
                amdgpu_irq_update(adev, &adev->crtc_irq, type);
+               amdgpu_irq_update(adev, &adev->pageflip_irq, type);
                drm_vblank_post_modeset(dev, amdgpu_crtc->crtc_id);
                dce_v8_0_crtc_load_lut(crtc);
                break;
@@ -2933,6 +2952,8 @@ static int dce_v8_0_hw_init(void *handle)
                dce_v8_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false);
        }
 
+       dce_v8_0_pageflip_interrupt_init(adev);
+
        return 0;
 }
 
@@ -2947,6 +2968,8 @@ static int dce_v8_0_hw_fini(void *handle)
                dce_v8_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false);
        }
 
+       dce_v8_0_pageflip_interrupt_fini(adev);
+
        return 0;
 }
 
@@ -2958,6 +2981,8 @@ static int dce_v8_0_suspend(void *handle)
 
        dce_v8_0_hpd_fini(adev);
 
+       dce_v8_0_pageflip_interrupt_fini(adev);
+
        return 0;
 }
 
@@ -2981,6 +3006,8 @@ static int dce_v8_0_resume(void *handle)
        /* initialize hpd */
        dce_v8_0_hpd_init(adev);
 
+       dce_v8_0_pageflip_interrupt_init(adev);
+
        return 0;
 }
 
@@ -3376,7 +3403,6 @@ static int dce_v8_0_pageflip_irq(struct amdgpu_device *adev,
        spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
 
        drm_vblank_put(adev->ddev, amdgpu_crtc->crtc_id);
-       amdgpu_irq_put(adev, &adev->pageflip_irq, crtc_id);
        queue_work(amdgpu_crtc->pflip_queue, &works->unpin_work);
 
        return 0;
index 322edea65857872ebd084ff322ee6fff6bf31e13..bda1249eb871e1c2c59f626aeb39914eb875abcd 100644 (file)
@@ -764,7 +764,7 @@ int fiji_smu_init(struct amdgpu_device *adev)
        ret = amdgpu_bo_create(adev, image_size, PAGE_SIZE,
                               true, AMDGPU_GEM_DOMAIN_VRAM,
                               AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
-                              NULL, toc_buf);
+                              NULL, NULL, toc_buf);
        if (ret) {
                DRM_ERROR("Failed to allocate memory for TOC buffer\n");
                return -ENOMEM;
@@ -774,7 +774,7 @@ int fiji_smu_init(struct amdgpu_device *adev)
        ret = amdgpu_bo_create(adev, smu_internal_buffer_size, PAGE_SIZE,
                               true, AMDGPU_GEM_DOMAIN_VRAM,
                               AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
-                              NULL, smu_buf);
+                              NULL, NULL, smu_buf);
        if (ret) {
                DRM_ERROR("Failed to allocate memory for SMU internal buffer\n");
                return -ENOMEM;
index 4bd1e5cf65ca81a04de64ec775164c5e5c410947..e992bf2ff66ce23e8c1d5f81b6b093713c1fac90 100644 (file)
@@ -3206,7 +3206,7 @@ static int gfx_v7_0_mec_init(struct amdgpu_device *adev)
                r = amdgpu_bo_create(adev,
                                     adev->gfx.mec.num_mec *adev->gfx.mec.num_pipe * MEC_HPD_SIZE * 2,
                                     PAGE_SIZE, true,
-                                    AMDGPU_GEM_DOMAIN_GTT, 0, NULL,
+                                    AMDGPU_GEM_DOMAIN_GTT, 0, NULL, NULL,
                                     &adev->gfx.mec.hpd_eop_obj);
                if (r) {
                        dev_warn(adev->dev, "(%d) create HDP EOP bo failed\n", r);
@@ -3373,7 +3373,7 @@ static int gfx_v7_0_cp_compute_resume(struct amdgpu_device *adev)
                        r = amdgpu_bo_create(adev,
                                             sizeof(struct bonaire_mqd),
                                             PAGE_SIZE, true,
-                                            AMDGPU_GEM_DOMAIN_GTT, 0, NULL,
+                                            AMDGPU_GEM_DOMAIN_GTT, 0, NULL, NULL,
                                             &ring->mqd_obj);
                        if (r) {
                                dev_warn(adev->dev, "(%d) create MQD bo failed\n", r);
@@ -3610,41 +3610,6 @@ static int gfx_v7_0_cp_resume(struct amdgpu_device *adev)
        return 0;
 }
 
-static void gfx_v7_0_ce_sync_me(struct amdgpu_ring *ring)
-{
-       struct amdgpu_device *adev = ring->adev;
-       u64 gpu_addr = adev->wb.gpu_addr + adev->gfx.ce_sync_offs * 4;
-
-       /* instruct DE to set a magic number */
-       amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
-       amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
-                                                        WRITE_DATA_DST_SEL(5)));
-       amdgpu_ring_write(ring, gpu_addr & 0xfffffffc);
-       amdgpu_ring_write(ring, upper_32_bits(gpu_addr) & 0xffffffff);
-       amdgpu_ring_write(ring, 1);
-
-       /* let CE wait till condition satisfied */
-       amdgpu_ring_write(ring, PACKET3(PACKET3_WAIT_REG_MEM, 5));
-       amdgpu_ring_write(ring, (WAIT_REG_MEM_OPERATION(0) | /* wait */
-                                                        WAIT_REG_MEM_MEM_SPACE(1) | /* memory */
-                                                        WAIT_REG_MEM_FUNCTION(3) |  /* == */
-                                                        WAIT_REG_MEM_ENGINE(2)));   /* ce */
-       amdgpu_ring_write(ring, gpu_addr & 0xfffffffc);
-       amdgpu_ring_write(ring, upper_32_bits(gpu_addr) & 0xffffffff);
-       amdgpu_ring_write(ring, 1);
-       amdgpu_ring_write(ring, 0xffffffff);
-       amdgpu_ring_write(ring, 4); /* poll interval */
-
-       /* instruct CE to reset wb of ce_sync to zero */
-       amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
-       amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(2) |
-                                                        WRITE_DATA_DST_SEL(5) |
-                                                        WR_CONFIRM));
-       amdgpu_ring_write(ring, gpu_addr & 0xfffffffc);
-       amdgpu_ring_write(ring, upper_32_bits(gpu_addr) & 0xffffffff);
-       amdgpu_ring_write(ring, 0);
-}
-
 /*
  * vm
  * VMID 0 is the physical GPU addresses as used by the kernel.
@@ -3663,6 +3628,13 @@ static void gfx_v7_0_ring_emit_vm_flush(struct amdgpu_ring *ring,
                                        unsigned vm_id, uint64_t pd_addr)
 {
        int usepfp = (ring->type == AMDGPU_RING_TYPE_GFX);
+       if (usepfp) {
+               /* synce CE with ME to prevent CE fetch CEIB before context switch done */
+               amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
+               amdgpu_ring_write(ring, 0);
+               amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
+               amdgpu_ring_write(ring, 0);
+       }
 
        amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
        amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(usepfp) |
@@ -3703,7 +3675,10 @@ static void gfx_v7_0_ring_emit_vm_flush(struct amdgpu_ring *ring,
                amdgpu_ring_write(ring, 0x0);
 
                /* synce CE with ME to prevent CE fetch CEIB before context switch done */
-               gfx_v7_0_ce_sync_me(ring);
+               amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
+               amdgpu_ring_write(ring, 0);
+               amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
+               amdgpu_ring_write(ring, 0);
        }
 }
 
@@ -3788,7 +3763,8 @@ static int gfx_v7_0_rlc_init(struct amdgpu_device *adev)
                        r = amdgpu_bo_create(adev, dws * 4, PAGE_SIZE, true,
                                             AMDGPU_GEM_DOMAIN_VRAM,
                                             AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
-                                            NULL, &adev->gfx.rlc.save_restore_obj);
+                                            NULL, NULL,
+                                            &adev->gfx.rlc.save_restore_obj);
                        if (r) {
                                dev_warn(adev->dev, "(%d) create RLC sr bo failed\n", r);
                                return r;
@@ -3831,7 +3807,8 @@ static int gfx_v7_0_rlc_init(struct amdgpu_device *adev)
                        r = amdgpu_bo_create(adev, dws * 4, PAGE_SIZE, true,
                                             AMDGPU_GEM_DOMAIN_VRAM,
                                             AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
-                                            NULL, &adev->gfx.rlc.clear_state_obj);
+                                            NULL, NULL,
+                                            &adev->gfx.rlc.clear_state_obj);
                        if (r) {
                                dev_warn(adev->dev, "(%d) create RLC c bo failed\n", r);
                                gfx_v7_0_rlc_fini(adev);
@@ -3870,7 +3847,8 @@ static int gfx_v7_0_rlc_init(struct amdgpu_device *adev)
                        r = amdgpu_bo_create(adev, adev->gfx.rlc.cp_table_size, PAGE_SIZE, true,
                                             AMDGPU_GEM_DOMAIN_VRAM,
                                             AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
-                                            NULL, &adev->gfx.rlc.cp_table_obj);
+                                            NULL, NULL,
+                                            &adev->gfx.rlc.cp_table_obj);
                        if (r) {
                                dev_warn(adev->dev, "(%d) create RLC cp table bo failed\n", r);
                                gfx_v7_0_rlc_fini(adev);
@@ -4802,12 +4780,6 @@ static int gfx_v7_0_sw_init(void *handle)
                return r;
        }
 
-       r = amdgpu_wb_get(adev, &adev->gfx.ce_sync_offs);
-       if (r) {
-               DRM_ERROR("(%d) gfx.ce_sync_offs wb alloc failed\n", r);
-               return r;
-       }
-
        for (i = 0; i < adev->gfx.num_gfx_rings; i++) {
                ring = &adev->gfx.gfx_ring[i];
                ring->ring_obj = NULL;
@@ -4851,21 +4823,21 @@ static int gfx_v7_0_sw_init(void *handle)
        r = amdgpu_bo_create(adev, adev->gds.mem.gfx_partition_size,
                        PAGE_SIZE, true,
                        AMDGPU_GEM_DOMAIN_GDS, 0,
-                       NULL, &adev->gds.gds_gfx_bo);
+                       NULL, NULL, &adev->gds.gds_gfx_bo);
        if (r)
                return r;
 
        r = amdgpu_bo_create(adev, adev->gds.gws.gfx_partition_size,
                PAGE_SIZE, true,
                AMDGPU_GEM_DOMAIN_GWS, 0,
-               NULL, &adev->gds.gws_gfx_bo);
+               NULL, NULL, &adev->gds.gws_gfx_bo);
        if (r)
                return r;
 
        r = amdgpu_bo_create(adev, adev->gds.oa.gfx_partition_size,
                        PAGE_SIZE, true,
                        AMDGPU_GEM_DOMAIN_OA, 0,
-                       NULL, &adev->gds.oa_gfx_bo);
+                       NULL, NULL, &adev->gds.oa_gfx_bo);
        if (r)
                return r;
 
@@ -4886,8 +4858,6 @@ static int gfx_v7_0_sw_fini(void *handle)
        for (i = 0; i < adev->gfx.num_compute_rings; i++)
                amdgpu_ring_fini(&adev->gfx.compute_ring[i]);
 
-       amdgpu_wb_free(adev, adev->gfx.ce_sync_offs);
-
        gfx_v7_0_cp_compute_fini(adev);
        gfx_v7_0_rlc_fini(adev);
        gfx_v7_0_mec_fini(adev);
index 53f07439a51285dd29a729724d2a0bc8583c9c88..cb4f68f53f248ab58cdb00100dc0da5d6f81da9d 100644 (file)
@@ -868,7 +868,7 @@ static int gfx_v8_0_mec_init(struct amdgpu_device *adev)
                r = amdgpu_bo_create(adev,
                                     adev->gfx.mec.num_mec *adev->gfx.mec.num_pipe * MEC_HPD_SIZE * 2,
                                     PAGE_SIZE, true,
-                                    AMDGPU_GEM_DOMAIN_GTT, 0, NULL,
+                                    AMDGPU_GEM_DOMAIN_GTT, 0, NULL, NULL,
                                     &adev->gfx.mec.hpd_eop_obj);
                if (r) {
                        dev_warn(adev->dev, "(%d) create HDP EOP bo failed\n", r);
@@ -940,12 +940,6 @@ static int gfx_v8_0_sw_init(void *handle)
                return r;
        }
 
-       r = amdgpu_wb_get(adev, &adev->gfx.ce_sync_offs);
-       if (r) {
-               DRM_ERROR("(%d) gfx.ce_sync_offs wb alloc failed\n", r);
-               return r;
-       }
-
        /* set up the gfx ring */
        for (i = 0; i < adev->gfx.num_gfx_rings; i++) {
                ring = &adev->gfx.gfx_ring[i];
@@ -995,21 +989,21 @@ static int gfx_v8_0_sw_init(void *handle)
        /* reserve GDS, GWS and OA resource for gfx */
        r = amdgpu_bo_create(adev, adev->gds.mem.gfx_partition_size,
                        PAGE_SIZE, true,
-                       AMDGPU_GEM_DOMAIN_GDS, 0,
+                       AMDGPU_GEM_DOMAIN_GDS, 0, NULL,
                        NULL, &adev->gds.gds_gfx_bo);
        if (r)
                return r;
 
        r = amdgpu_bo_create(adev, adev->gds.gws.gfx_partition_size,
                PAGE_SIZE, true,
-               AMDGPU_GEM_DOMAIN_GWS, 0,
+               AMDGPU_GEM_DOMAIN_GWS, 0, NULL,
                NULL, &adev->gds.gws_gfx_bo);
        if (r)
                return r;
 
        r = amdgpu_bo_create(adev, adev->gds.oa.gfx_partition_size,
                        PAGE_SIZE, true,
-                       AMDGPU_GEM_DOMAIN_OA, 0,
+                       AMDGPU_GEM_DOMAIN_OA, 0, NULL,
                        NULL, &adev->gds.oa_gfx_bo);
        if (r)
                return r;
@@ -1033,8 +1027,6 @@ static int gfx_v8_0_sw_fini(void *handle)
        for (i = 0; i < adev->gfx.num_compute_rings; i++)
                amdgpu_ring_fini(&adev->gfx.compute_ring[i]);
 
-       amdgpu_wb_free(adev, adev->gfx.ce_sync_offs);
-
        gfx_v8_0_mec_fini(adev);
 
        return 0;
@@ -3106,7 +3098,7 @@ static int gfx_v8_0_cp_compute_resume(struct amdgpu_device *adev)
                                             sizeof(struct vi_mqd),
                                             PAGE_SIZE, true,
                                             AMDGPU_GEM_DOMAIN_GTT, 0, NULL,
-                                            &ring->mqd_obj);
+                                            NULL, &ring->mqd_obj);
                        if (r) {
                                dev_warn(adev->dev, "(%d) create MQD bo failed\n", r);
                                return r;
@@ -3965,6 +3957,7 @@ static void gfx_v8_0_ring_emit_fence_gfx(struct amdgpu_ring *ring, u64 addr,
                          DATA_SEL(write64bit ? 2 : 1) | INT_SEL(int_sel ? 2 : 0));
        amdgpu_ring_write(ring, lower_32_bits(seq));
        amdgpu_ring_write(ring, upper_32_bits(seq));
+
 }
 
 /**
@@ -4005,49 +3998,34 @@ static bool gfx_v8_0_ring_emit_semaphore(struct amdgpu_ring *ring,
        return true;
 }
 
-static void gfx_v8_0_ce_sync_me(struct amdgpu_ring *ring)
+static void gfx_v8_0_ring_emit_vm_flush(struct amdgpu_ring *ring,
+                                       unsigned vm_id, uint64_t pd_addr)
 {
-       struct amdgpu_device *adev = ring->adev;
-       u64 gpu_addr = adev->wb.gpu_addr + adev->gfx.ce_sync_offs * 4;
-
-       /* instruct DE to set a magic number */
-       amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
-       amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
-                                                        WRITE_DATA_DST_SEL(5)));
-       amdgpu_ring_write(ring, gpu_addr & 0xfffffffc);
-       amdgpu_ring_write(ring, upper_32_bits(gpu_addr) & 0xffffffff);
-       amdgpu_ring_write(ring, 1);
+       int usepfp = (ring->type == AMDGPU_RING_TYPE_GFX);
+       uint32_t seq = ring->fence_drv.sync_seq[ring->idx];
+       uint64_t addr = ring->fence_drv.gpu_addr;
 
-       /* let CE wait till condition satisfied */
        amdgpu_ring_write(ring, PACKET3(PACKET3_WAIT_REG_MEM, 5));
-       amdgpu_ring_write(ring, (WAIT_REG_MEM_OPERATION(0) | /* wait */
-                                                        WAIT_REG_MEM_MEM_SPACE(1) | /* memory */
-                                                        WAIT_REG_MEM_FUNCTION(3) |  /* == */
-                                                        WAIT_REG_MEM_ENGINE(2)));   /* ce */
-       amdgpu_ring_write(ring, gpu_addr & 0xfffffffc);
-       amdgpu_ring_write(ring, upper_32_bits(gpu_addr) & 0xffffffff);
-       amdgpu_ring_write(ring, 1);
+       amdgpu_ring_write(ring, (WAIT_REG_MEM_MEM_SPACE(1) | /* memory */
+                WAIT_REG_MEM_FUNCTION(3))); /* equal */
+       amdgpu_ring_write(ring, addr & 0xfffffffc);
+       amdgpu_ring_write(ring, upper_32_bits(addr) & 0xffffffff);
+       amdgpu_ring_write(ring, seq);
        amdgpu_ring_write(ring, 0xffffffff);
        amdgpu_ring_write(ring, 4); /* poll interval */
 
-       /* instruct CE to reset wb of ce_sync to zero */
-       amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
-       amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(2) |
-                                                        WRITE_DATA_DST_SEL(5) |
-                                                        WR_CONFIRM));
-       amdgpu_ring_write(ring, gpu_addr & 0xfffffffc);
-       amdgpu_ring_write(ring, upper_32_bits(gpu_addr) & 0xffffffff);
-       amdgpu_ring_write(ring, 0);
-}
-
-static void gfx_v8_0_ring_emit_vm_flush(struct amdgpu_ring *ring,
-                                       unsigned vm_id, uint64_t pd_addr)
-{
-       int usepfp = (ring->type == AMDGPU_RING_TYPE_GFX);
+       if (usepfp) {
+               /* synce CE with ME to prevent CE fetch CEIB before context switch done */
+               amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
+               amdgpu_ring_write(ring, 0);
+               amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
+               amdgpu_ring_write(ring, 0);
+       }
 
        amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
        amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(usepfp) |
-                                WRITE_DATA_DST_SEL(0)));
+                                WRITE_DATA_DST_SEL(0)) |
+                                WR_CONFIRM);
        if (vm_id < 8) {
                amdgpu_ring_write(ring,
                                  (mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR + vm_id));
@@ -4083,9 +4061,10 @@ static void gfx_v8_0_ring_emit_vm_flush(struct amdgpu_ring *ring,
                /* sync PFP to ME, otherwise we might get invalid PFP reads */
                amdgpu_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0));
                amdgpu_ring_write(ring, 0x0);
-
-               /* synce CE with ME to prevent CE fetch CEIB before context switch done */
-               gfx_v8_0_ce_sync_me(ring);
+               amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
+               amdgpu_ring_write(ring, 0);
+               amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
+               amdgpu_ring_write(ring, 0);
        }
 }
 
index 774528ab8704387f00525618b1c48578387b70df..fab5471d25d7e3dc3a3605d22c52fd669e919f7b 100644 (file)
@@ -1262,6 +1262,12 @@ static int gmc_v7_0_process_interrupt(struct amdgpu_device *adev,
        addr = RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_ADDR);
        status = RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_STATUS);
        mc_client = RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_MCCLIENT);
+       /* reset addr and status */
+       WREG32_P(mmVM_CONTEXT1_CNTL2, 1, ~1);
+
+       if (!addr && !status)
+               return 0;
+
        dev_err(adev->dev, "GPU fault detected: %d 0x%08x\n",
                entry->src_id, entry->src_data);
        dev_err(adev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_ADDR   0x%08X\n",
@@ -1269,8 +1275,6 @@ static int gmc_v7_0_process_interrupt(struct amdgpu_device *adev,
        dev_err(adev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n",
                status);
        gmc_v7_0_vm_decode_fault(adev, status, addr, mc_client);
-       /* reset addr and status */
-       WREG32_P(mmVM_CONTEXT1_CNTL2, 1, ~1);
 
        return 0;
 }
index 9a07742620d0361ad054930ff3b07c75c9bbcf2c..7bc9e9fcf3d26cbbaa6d7aa76fbef0349964ec6f 100644 (file)
@@ -1262,6 +1262,12 @@ static int gmc_v8_0_process_interrupt(struct amdgpu_device *adev,
        addr = RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_ADDR);
        status = RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_STATUS);
        mc_client = RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_MCCLIENT);
+       /* reset addr and status */
+       WREG32_P(mmVM_CONTEXT1_CNTL2, 1, ~1);
+
+       if (!addr && !status)
+               return 0;
+
        dev_err(adev->dev, "GPU fault detected: %d 0x%08x\n",
                entry->src_id, entry->src_data);
        dev_err(adev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_ADDR   0x%08X\n",
@@ -1269,8 +1275,6 @@ static int gmc_v8_0_process_interrupt(struct amdgpu_device *adev,
        dev_err(adev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n",
                status);
        gmc_v8_0_vm_decode_fault(adev, status, addr, mc_client);
-       /* reset addr and status */
-       WREG32_P(mmVM_CONTEXT1_CNTL2, 1, ~1);
 
        return 0;
 }
index c900aa942adef4f31674ddb98070c7702c6600b3..966d4b2ed9dad0527a2d0246b23731f1d802d9e2 100644 (file)
@@ -625,7 +625,7 @@ int iceland_smu_init(struct amdgpu_device *adev)
        ret = amdgpu_bo_create(adev, image_size, PAGE_SIZE,
                               true, AMDGPU_GEM_DOMAIN_VRAM,
                               AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
-                              NULL, toc_buf);
+                              NULL, NULL, toc_buf);
        if (ret) {
                DRM_ERROR("Failed to allocate memory for TOC buffer\n");
                return -ENOMEM;
index 94ec04a9c4d5c975eeb329dc770d3dd055b74ae5..7e9154c7f1dbbb7f9d3eee6791c0e4fcc835ea8d 100644 (file)
@@ -2995,6 +2995,15 @@ static int kv_dpm_late_init(void *handle)
 {
        /* powerdown unused blocks for now */
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+       int ret;
+
+       if (!amdgpu_dpm)
+               return 0;
+
+       /* init the sysfs and debugfs files late */
+       ret = amdgpu_pm_sysfs_init(adev);
+       if (ret)
+               return ret;
 
        kv_dpm_powergate_acp(adev, true);
        kv_dpm_powergate_samu(adev, true);
@@ -3038,9 +3047,6 @@ static int kv_dpm_sw_init(void *handle)
        adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps;
        if (amdgpu_dpm == 1)
                amdgpu_pm_print_power_states(adev);
-       ret = amdgpu_pm_sysfs_init(adev);
-       if (ret)
-               goto dpm_failed;
        mutex_unlock(&adev->pm.mutex);
        DRM_INFO("amdgpu: dpm initialized\n");
 
index 1f5ac941a610819f434958cb04b8bb5bb6946439..5421309c18623b389c6c469d3c12de431effe142 100644 (file)
@@ -763,7 +763,7 @@ int tonga_smu_init(struct amdgpu_device *adev)
        ret = amdgpu_bo_create(adev, image_size, PAGE_SIZE,
                               true, AMDGPU_GEM_DOMAIN_VRAM,
                               AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
-                              NULL, toc_buf);
+                              NULL, NULL, toc_buf);
        if (ret) {
                DRM_ERROR("Failed to allocate memory for TOC buffer\n");
                return -ENOMEM;
@@ -773,7 +773,7 @@ int tonga_smu_init(struct amdgpu_device *adev)
        ret = amdgpu_bo_create(adev, smu_internal_buffer_size, PAGE_SIZE,
                               true, AMDGPU_GEM_DOMAIN_VRAM,
                               AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
-                              NULL, smu_buf);
+                              NULL, NULL, smu_buf);
        if (ret) {
                DRM_ERROR("Failed to allocate memory for SMU internal buffer\n");
                return -ENOMEM;
index 5fac5da694f0d12a1bb415d2a5f557cb25461c43..ed50dd725788df2e766650868f1782b49dec2cdd 100644 (file)
@@ -224,11 +224,11 @@ static int uvd_v4_2_suspend(void *handle)
        int r;
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       r = uvd_v4_2_hw_fini(adev);
+       r = amdgpu_uvd_suspend(adev);
        if (r)
                return r;
 
-       r = amdgpu_uvd_suspend(adev);
+       r = uvd_v4_2_hw_fini(adev);
        if (r)
                return r;
 
index 2d5c59c318afb5b0265ccf98461208de81d983b7..9ad8b9906c0bec4af7448884bf5b24149a490ad9 100644 (file)
@@ -220,11 +220,11 @@ static int uvd_v5_0_suspend(void *handle)
        int r;
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       r = uvd_v5_0_hw_fini(adev);
+       r = amdgpu_uvd_suspend(adev);
        if (r)
                return r;
 
-       r = amdgpu_uvd_suspend(adev);
+       r = uvd_v5_0_hw_fini(adev);
        if (r)
                return r;
 
index d9f553fce5310936c560647db64accda8bc9184e..7e9934fa41939f55255aa77ee6c828b888fc4f3f 100644 (file)
@@ -214,14 +214,16 @@ static int uvd_v6_0_suspend(void *handle)
        int r;
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
+       /* Skip this for APU for now */
+       if (!(adev->flags & AMD_IS_APU)) {
+               r = amdgpu_uvd_suspend(adev);
+               if (r)
+                       return r;
+       }
        r = uvd_v6_0_hw_fini(adev);
        if (r)
                return r;
 
-       r = amdgpu_uvd_suspend(adev);
-       if (r)
-               return r;
-
        return r;
 }
 
@@ -230,10 +232,12 @@ static int uvd_v6_0_resume(void *handle)
        int r;
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       r = amdgpu_uvd_resume(adev);
-       if (r)
-               return r;
-
+       /* Skip this for APU for now */
+       if (!(adev->flags & AMD_IS_APU)) {
+               r = amdgpu_uvd_resume(adev);
+               if (r)
+                       return r;
+       }
        r = uvd_v6_0_hw_init(adev);
        if (r)
                return r;
index 552d9e75ad1bac1ef74ddf071fcd8aed9e40b31a..0bac8702e9348c2ee9c86ed52d6aaf490ef5032f 100644 (file)
@@ -1005,6 +1005,9 @@ static void vi_pcie_gen3_enable(struct amdgpu_device *adev)
        u32 mask;
        int ret;
 
+       if (pci_is_root_bus(adev->pdev->bus))
+               return;
+
        if (amdgpu_pcie_gen2 == 0)
                return;
 
@@ -1400,7 +1403,8 @@ static int vi_common_early_init(void *handle)
        case CHIP_CARRIZO:
                adev->has_uvd = true;
                adev->cg_flags = 0;
-               adev->pg_flags = AMDGPU_PG_SUPPORT_UVD | AMDGPU_PG_SUPPORT_VCE;
+               /* Disable UVD pg */
+               adev->pg_flags = /* AMDGPU_PG_SUPPORT_UVD | */AMDGPU_PG_SUPPORT_VCE;
                adev->external_rev_id = adev->rev_id + 0x1;
                if (amdgpu_smc_load_fw && smc_enabled)
                        adev->firmware.smu_load = true;
index 488642f08267902c628c9db541030c6a27cb2def..3b47ae313e36bc7a0385365c082a519207fd7470 100644 (file)
 
 #include "cgs_common.h"
 
-/**
- * cgs_import_gpu_mem() - Import dmabuf handle
- * @cgs_device:  opaque device handle
- * @dmabuf_fd:   DMABuf file descriptor
- * @handle:      memory handle (output)
- *
- * Must be called in the process context that dmabuf_fd belongs to.
- *
- * Return:  0 on success, -errno otherwise
- */
-typedef int (*cgs_import_gpu_mem_t)(void *cgs_device, int dmabuf_fd,
-                                   cgs_handle_t *handle);
-
 /**
  * cgs_irq_source_set_func() - Callback for enabling/disabling interrupt sources
  * @private_data:  private data provided to cgs_add_irq_source
@@ -114,16 +101,12 @@ typedef int (*cgs_irq_get_t)(void *cgs_device, unsigned src_id, unsigned type);
 typedef int (*cgs_irq_put_t)(void *cgs_device, unsigned src_id, unsigned type);
 
 struct cgs_os_ops {
-       cgs_import_gpu_mem_t import_gpu_mem;
-
        /* IRQ handling */
        cgs_add_irq_source_t add_irq_source;
        cgs_irq_get_t irq_get;
        cgs_irq_put_t irq_put;
 };
 
-#define cgs_import_gpu_mem(dev,dmabuf_fd,handle)               \
-       CGS_OS_CALL(import_gpu_mem,dev,dmabuf_fd,handle)
 #define cgs_add_irq_source(dev,src_id,num_types,set,handler,private_data) \
        CGS_OS_CALL(add_irq_source,dev,src_id,num_types,set,handler,    \
                    private_data)
diff --git a/drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h b/drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h
new file mode 100644 (file)
index 0000000..144f50a
--- /dev/null
@@ -0,0 +1,41 @@
+#if !defined(_GPU_SCHED_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _GPU_SCHED_TRACE_H_
+
+#include <linux/stringify.h>
+#include <linux/types.h>
+#include <linux/tracepoint.h>
+
+#include <drm/drmP.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM gpu_sched
+#define TRACE_INCLUDE_FILE gpu_sched_trace
+
+TRACE_EVENT(amd_sched_job,
+           TP_PROTO(struct amd_sched_job *sched_job),
+           TP_ARGS(sched_job),
+           TP_STRUCT__entry(
+                            __field(struct amd_sched_entity *, entity)
+                            __field(const char *, name)
+                            __field(u32, job_count)
+                            __field(int, hw_job_count)
+                            ),
+
+           TP_fast_assign(
+                          __entry->entity = sched_job->s_entity;
+                          __entry->name = sched_job->sched->name;
+                          __entry->job_count = kfifo_len(
+                                  &sched_job->s_entity->job_queue) / sizeof(sched_job);
+                          __entry->hw_job_count = atomic_read(
+                                  &sched_job->sched->hw_rq_count);
+                          ),
+           TP_printk("entity=%p, ring=%s, job count:%u, hw job count:%d",
+                     __entry->entity, __entry->name, __entry->job_count,
+                     __entry->hw_job_count)
+);
+#endif
+
+/* This part must be outside protection */
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#include <trace/define_trace.h>
index 9259f1b6664c60cb94894d8b0c309ca8e9e8b26e..3697eeeecf82a75ef1a5b0ee44e6b4d572841053 100644 (file)
@@ -27,6 +27,9 @@
 #include <drm/drmP.h>
 #include "gpu_scheduler.h"
 
+#define CREATE_TRACE_POINTS
+#include "gpu_sched_trace.h"
+
 static struct amd_sched_job *
 amd_sched_entity_pop_job(struct amd_sched_entity *entity);
 static void amd_sched_wakeup(struct amd_gpu_scheduler *sched);
@@ -65,29 +68,29 @@ static struct amd_sched_job *
 amd_sched_rq_select_job(struct amd_sched_rq *rq)
 {
        struct amd_sched_entity *entity;
-       struct amd_sched_job *job;
+       struct amd_sched_job *sched_job;
 
        spin_lock(&rq->lock);
 
        entity = rq->current_entity;
        if (entity) {
                list_for_each_entry_continue(entity, &rq->entities, list) {
-                       job = amd_sched_entity_pop_job(entity);
-                       if (job) {
+                       sched_job = amd_sched_entity_pop_job(entity);
+                       if (sched_job) {
                                rq->current_entity = entity;
                                spin_unlock(&rq->lock);
-                               return job;
+                               return sched_job;
                        }
                }
        }
 
        list_for_each_entry(entity, &rq->entities, list) {
 
-               job = amd_sched_entity_pop_job(entity);
-               if (job) {
+               sched_job = amd_sched_entity_pop_job(entity);
+               if (sched_job) {
                        rq->current_entity = entity;
                        spin_unlock(&rq->lock);
-                       return job;
+                       return sched_job;
                }
 
                if (entity == rq->current_entity)
@@ -115,23 +118,27 @@ int amd_sched_entity_init(struct amd_gpu_scheduler *sched,
                          struct amd_sched_rq *rq,
                          uint32_t jobs)
 {
+       int r;
+
        if (!(sched && entity && rq))
                return -EINVAL;
 
        memset(entity, 0, sizeof(struct amd_sched_entity));
-       entity->belongto_rq = rq;
-       entity->scheduler = sched;
-       entity->fence_context = fence_context_alloc(1);
-       if(kfifo_alloc(&entity->job_queue,
-                      jobs * sizeof(void *),
-                      GFP_KERNEL))
-               return -EINVAL;
+       INIT_LIST_HEAD(&entity->list);
+       entity->rq = rq;
+       entity->sched = sched;
 
        spin_lock_init(&entity->queue_lock);
+       r = kfifo_alloc(&entity->job_queue, jobs * sizeof(void *), GFP_KERNEL);
+       if (r)
+               return r;
+
        atomic_set(&entity->fence_seq, 0);
+       entity->fence_context = fence_context_alloc(1);
 
        /* Add the entity to the run queue */
        amd_sched_rq_add_entity(rq, entity);
+
        return 0;
 }
 
@@ -146,8 +153,8 @@ int amd_sched_entity_init(struct amd_gpu_scheduler *sched,
 static bool amd_sched_entity_is_initialized(struct amd_gpu_scheduler *sched,
                                            struct amd_sched_entity *entity)
 {
-       return entity->scheduler == sched &&
-               entity->belongto_rq != NULL;
+       return entity->sched == sched &&
+               entity->rq != NULL;
 }
 
 /**
@@ -177,7 +184,7 @@ static bool amd_sched_entity_is_idle(struct amd_sched_entity *entity)
 void amd_sched_entity_fini(struct amd_gpu_scheduler *sched,
                           struct amd_sched_entity *entity)
 {
-       struct amd_sched_rq *rq = entity->belongto_rq;
+       struct amd_sched_rq *rq = entity->rq;
 
        if (!amd_sched_entity_is_initialized(sched, entity))
                return;
@@ -198,22 +205,22 @@ static void amd_sched_entity_wakeup(struct fence *f, struct fence_cb *cb)
                container_of(cb, struct amd_sched_entity, cb);
        entity->dependency = NULL;
        fence_put(f);
-       amd_sched_wakeup(entity->scheduler);
+       amd_sched_wakeup(entity->sched);
 }
 
 static struct amd_sched_job *
 amd_sched_entity_pop_job(struct amd_sched_entity *entity)
 {
-       struct amd_gpu_scheduler *sched = entity->scheduler;
-       struct amd_sched_job *job;
+       struct amd_gpu_scheduler *sched = entity->sched;
+       struct amd_sched_job *sched_job;
 
        if (ACCESS_ONCE(entity->dependency))
                return NULL;
 
-       if (!kfifo_out_peek(&entity->job_queue, &job, sizeof(job)))
+       if (!kfifo_out_peek(&entity->job_queue, &sched_job, sizeof(sched_job)))
                return NULL;
 
-       while ((entity->dependency = sched->ops->dependency(job))) {
+       while ((entity->dependency = sched->ops->dependency(sched_job))) {
 
                if (fence_add_callback(entity->dependency, &entity->cb,
                                       amd_sched_entity_wakeup))
@@ -222,32 +229,33 @@ amd_sched_entity_pop_job(struct amd_sched_entity *entity)
                        return NULL;
        }
 
-       return job;
+       return sched_job;
 }
 
 /**
  * Helper to submit a job to the job queue
  *
- * @job                The pointer to job required to submit
+ * @sched_job          The pointer to job required to submit
  *
  * Returns true if we could submit the job.
  */
-static bool amd_sched_entity_in(struct amd_sched_job *job)
+static bool amd_sched_entity_in(struct amd_sched_job *sched_job)
 {
-       struct amd_sched_entity *entity = job->s_entity;
+       struct amd_sched_entity *entity = sched_job->s_entity;
        bool added, first = false;
 
        spin_lock(&entity->queue_lock);
-       added = kfifo_in(&entity->job_queue, &job, sizeof(job)) == sizeof(job);
+       added = kfifo_in(&entity->job_queue, &sched_job,
+                       sizeof(sched_job)) == sizeof(sched_job);
 
-       if (added && kfifo_len(&entity->job_queue) == sizeof(job))
+       if (added && kfifo_len(&entity->job_queue) == sizeof(sched_job))
                first = true;
 
        spin_unlock(&entity->queue_lock);
 
        /* first job wakes up scheduler */
        if (first)
-               amd_sched_wakeup(job->sched);
+               amd_sched_wakeup(sched_job->sched);
 
        return added;
 }
@@ -255,7 +263,7 @@ static bool amd_sched_entity_in(struct amd_sched_job *job)
 /**
  * Submit a job to the job queue
  *
- * @job                The pointer to job required to submit
+ * @sched_job          The pointer to job required to submit
  *
  * Returns 0 for success, negative error code otherwise.
  */
@@ -271,9 +279,9 @@ int amd_sched_entity_push_job(struct amd_sched_job *sched_job)
        fence_get(&fence->base);
        sched_job->s_fence = fence;
 
-       wait_event(entity->scheduler->job_scheduled,
+       wait_event(entity->sched->job_scheduled,
                   amd_sched_entity_in(sched_job));
-
+       trace_amd_sched_job(sched_job);
        return 0;
 }
 
@@ -301,30 +309,28 @@ static void amd_sched_wakeup(struct amd_gpu_scheduler *sched)
 static struct amd_sched_job *
 amd_sched_select_job(struct amd_gpu_scheduler *sched)
 {
-       struct amd_sched_job *job;
+       struct amd_sched_job *sched_job;
 
        if (!amd_sched_ready(sched))
                return NULL;
 
        /* Kernel run queue has higher priority than normal run queue*/
-       job = amd_sched_rq_select_job(&sched->kernel_rq);
-       if (job == NULL)
-               job = amd_sched_rq_select_job(&sched->sched_rq);
+       sched_job = amd_sched_rq_select_job(&sched->kernel_rq);
+       if (sched_job == NULL)
+               sched_job = amd_sched_rq_select_job(&sched->sched_rq);
 
-       return job;
+       return sched_job;
 }
 
 static void amd_sched_process_job(struct fence *f, struct fence_cb *cb)
 {
-       struct amd_sched_job *sched_job =
-               container_of(cb, struct amd_sched_job, cb);
-       struct amd_gpu_scheduler *sched;
+       struct amd_sched_fence *s_fence =
+               container_of(cb, struct amd_sched_fence, cb);
+       struct amd_gpu_scheduler *sched = s_fence->sched;
 
-       sched = sched_job->sched;
-       amd_sched_fence_signal(sched_job->s_fence);
        atomic_dec(&sched->hw_rq_count);
-       fence_put(&sched_job->s_fence->base);
-       sched->ops->process_job(sched_job);
+       amd_sched_fence_signal(s_fence);
+       fence_put(&s_fence->base);
        wake_up_interruptible(&sched->wake_up_worker);
 }
 
@@ -338,87 +344,82 @@ static int amd_sched_main(void *param)
 
        while (!kthread_should_stop()) {
                struct amd_sched_entity *entity;
-               struct amd_sched_job *job;
+               struct amd_sched_fence *s_fence;
+               struct amd_sched_job *sched_job;
                struct fence *fence;
 
                wait_event_interruptible(sched->wake_up_worker,
                        kthread_should_stop() ||
-                       (job = amd_sched_select_job(sched)));
+                       (sched_job = amd_sched_select_job(sched)));
 
-               if (!job)
+               if (!sched_job)
                        continue;
 
-               entity = job->s_entity;
+               entity = sched_job->s_entity;
+               s_fence = sched_job->s_fence;
                atomic_inc(&sched->hw_rq_count);
-               fence = sched->ops->run_job(job);
+               fence = sched->ops->run_job(sched_job);
                if (fence) {
-                       r = fence_add_callback(fence, &job->cb,
+                       r = fence_add_callback(fence, &s_fence->cb,
                                               amd_sched_process_job);
                        if (r == -ENOENT)
-                               amd_sched_process_job(fence, &job->cb);
+                               amd_sched_process_job(fence, &s_fence->cb);
                        else if (r)
                                DRM_ERROR("fence add callback failed (%d)\n", r);
                        fence_put(fence);
+               } else {
+                       DRM_ERROR("Failed to run job!\n");
+                       amd_sched_process_job(NULL, &s_fence->cb);
                }
 
-               count = kfifo_out(&entity->job_queue, &job, sizeof(job));
-               WARN_ON(count != sizeof(job));
+               count = kfifo_out(&entity->job_queue, &sched_job,
+                               sizeof(sched_job));
+               WARN_ON(count != sizeof(sched_job));
                wake_up(&sched->job_scheduled);
        }
        return 0;
 }
 
 /**
- * Create a gpu scheduler
+ * Init a gpu scheduler instance
  *
+ * @sched              The pointer to the scheduler
  * @ops                        The backend operations for this scheduler.
- * @ring               The the ring id for the scheduler.
  * @hw_submissions     Number of hw submissions to do.
+ * @name               Name used for debugging
  *
- * Return the pointer to scheduler for success, otherwise return NULL
+ * Return 0 on success, otherwise error code.
 */
-struct amd_gpu_scheduler *amd_sched_create(struct amd_sched_backend_ops *ops,
-                                          unsigned ring, unsigned hw_submission,
-                                          void *priv)
+int amd_sched_init(struct amd_gpu_scheduler *sched,
+                  struct amd_sched_backend_ops *ops,
+                  unsigned hw_submission, const char *name)
 {
-       struct amd_gpu_scheduler *sched;
-
-       sched = kzalloc(sizeof(struct amd_gpu_scheduler), GFP_KERNEL);
-       if (!sched)
-               return NULL;
-
        sched->ops = ops;
-       sched->ring_id = ring;
        sched->hw_submission_limit = hw_submission;
-       sched->priv = priv;
-       snprintf(sched->name, sizeof(sched->name), "amdgpu[%d]", ring);
+       sched->name = name;
        amd_sched_rq_init(&sched->sched_rq);
        amd_sched_rq_init(&sched->kernel_rq);
 
        init_waitqueue_head(&sched->wake_up_worker);
        init_waitqueue_head(&sched->job_scheduled);
        atomic_set(&sched->hw_rq_count, 0);
+
        /* Each scheduler will run on a seperate kernel thread */
        sched->thread = kthread_run(amd_sched_main, sched, sched->name);
        if (IS_ERR(sched->thread)) {
-               DRM_ERROR("Failed to create scheduler for id %d.\n", ring);
-               kfree(sched);
-               return NULL;
+               DRM_ERROR("Failed to create scheduler for %s.\n", name);
+               return PTR_ERR(sched->thread);
        }
 
-       return sched;
+       return 0;
 }
 
 /**
  * Destroy a gpu scheduler
  *
  * @sched      The pointer to the scheduler
- *
- * return 0 if succeed. -1 if failed.
  */
-int amd_sched_destroy(struct amd_gpu_scheduler *sched)
+void amd_sched_fini(struct amd_gpu_scheduler *sched)
 {
        kthread_stop(sched->thread);
-       kfree(sched);
-       return  0;
 }
index 2af0e4d4d817a044fa0d1ff881d06ba75adc7032..80b64dc2221417938347e8ac463a6d3d676b9f0d 100644 (file)
@@ -38,13 +38,15 @@ struct amd_sched_rq;
 */
 struct amd_sched_entity {
        struct list_head                list;
-       struct amd_sched_rq             *belongto_rq;
-       atomic_t                        fence_seq;
-       /* the job_queue maintains the jobs submitted by clients */
-       struct kfifo                    job_queue;
+       struct amd_sched_rq             *rq;
+       struct amd_gpu_scheduler        *sched;
+
        spinlock_t                      queue_lock;
-       struct amd_gpu_scheduler        *scheduler;
+       struct kfifo                    job_queue;
+
+       atomic_t                        fence_seq;
        uint64_t                        fence_context;
+
        struct fence                    *dependency;
        struct fence_cb                 cb;
 };
@@ -62,13 +64,13 @@ struct amd_sched_rq {
 
 struct amd_sched_fence {
        struct fence                    base;
-       struct amd_gpu_scheduler        *scheduler;
+       struct fence_cb                 cb;
+       struct amd_gpu_scheduler        *sched;
        spinlock_t                      lock;
        void                            *owner;
 };
 
 struct amd_sched_job {
-       struct fence_cb                 cb;
        struct amd_gpu_scheduler        *sched;
        struct amd_sched_entity         *s_entity;
        struct amd_sched_fence          *s_fence;
@@ -91,32 +93,29 @@ static inline struct amd_sched_fence *to_amd_sched_fence(struct fence *f)
  * these functions should be implemented in driver side
 */
 struct amd_sched_backend_ops {
-       struct fence *(*dependency)(struct amd_sched_job *job);
-       struct fence *(*run_job)(struct amd_sched_job *job);
-       void (*process_job)(struct amd_sched_job *job);
+       struct fence *(*dependency)(struct amd_sched_job *sched_job);
+       struct fence *(*run_job)(struct amd_sched_job *sched_job);
 };
 
 /**
  * One scheduler is implemented for each hardware ring
 */
 struct amd_gpu_scheduler {
-       struct task_struct              *thread;
+       struct amd_sched_backend_ops    *ops;
+       uint32_t                        hw_submission_limit;
+       const char                      *name;
        struct amd_sched_rq             sched_rq;
        struct amd_sched_rq             kernel_rq;
-       atomic_t                        hw_rq_count;
-       struct amd_sched_backend_ops    *ops;
-       uint32_t                        ring_id;
        wait_queue_head_t               wake_up_worker;
        wait_queue_head_t               job_scheduled;
-       uint32_t                        hw_submission_limit;
-       char                            name[20];
-       void                            *priv;
+       atomic_t                        hw_rq_count;
+       struct task_struct              *thread;
 };
 
-struct amd_gpu_scheduler *
-amd_sched_create(struct amd_sched_backend_ops *ops,
-                uint32_t ring, uint32_t hw_submission, void *priv);
-int amd_sched_destroy(struct amd_gpu_scheduler *sched);
+int amd_sched_init(struct amd_gpu_scheduler *sched,
+                  struct amd_sched_backend_ops *ops,
+                  uint32_t hw_submission, const char *name);
+void amd_sched_fini(struct amd_gpu_scheduler *sched);
 
 int amd_sched_entity_init(struct amd_gpu_scheduler *sched,
                          struct amd_sched_entity *entity,
index e62c37920e11ccacea8f59a31d93dceab78676a8..d802638094f4bb3817bb6612f1e37bf2479cf142 100644 (file)
@@ -36,7 +36,7 @@ struct amd_sched_fence *amd_sched_fence_create(struct amd_sched_entity *s_entity
        if (fence == NULL)
                return NULL;
        fence->owner = owner;
-       fence->scheduler = s_entity->scheduler;
+       fence->sched = s_entity->sched;
        spin_lock_init(&fence->lock);
 
        seq = atomic_inc_return(&s_entity->fence_seq);
@@ -63,7 +63,7 @@ static const char *amd_sched_fence_get_driver_name(struct fence *fence)
 static const char *amd_sched_fence_get_timeline_name(struct fence *f)
 {
        struct amd_sched_fence *fence = to_amd_sched_fence(f);
-       return (const char *)fence->scheduler->name;
+       return (const char *)fence->sched->name;
 }
 
 static bool amd_sched_fence_enable_signaling(struct fence *f)
index 33d877c65ced6a3c138af9ab47c824038410be0b..8328e7059205d266a456710613628c64b097f787 100644 (file)
@@ -4105,7 +4105,7 @@ drm_property_create_blob(struct drm_device *dev, size_t length,
        struct drm_property_blob *blob;
        int ret;
 
-       if (!length)
+       if (!length || length > ULONG_MAX - sizeof(struct drm_property_blob))
                return ERR_PTR(-EINVAL);
 
        blob = kzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL);
@@ -4454,7 +4454,7 @@ int drm_mode_createblob_ioctl(struct drm_device *dev,
         * not associated with any file_priv. */
        mutex_lock(&dev->mode_config.blob_lock);
        out_resp->blob_id = blob->base.id;
-       list_add_tail(&file_priv->blobs, &blob->head_file);
+       list_add_tail(&blob->head_file, &file_priv->blobs);
        mutex_unlock(&dev->mode_config.blob_lock);
 
        return 0;
index e23df5fd3836b1b70169a1ee125782c1e754b875..809959d56d7826364b540204a16190aaf270f9c4 100644 (file)
@@ -53,8 +53,8 @@ static int drm_dp_send_dpcd_write(struct drm_dp_mst_topology_mgr *mgr,
                                  struct drm_dp_mst_port *port,
                                  int offset, int size, u8 *bytes);
 
-static int drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
-                                   struct drm_dp_mst_branch *mstb);
+static void drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
+                                    struct drm_dp_mst_branch *mstb);
 static int drm_dp_send_enum_path_resources(struct drm_dp_mst_topology_mgr *mgr,
                                           struct drm_dp_mst_branch *mstb,
                                           struct drm_dp_mst_port *port);
@@ -804,8 +804,6 @@ static void drm_dp_destroy_mst_branch_device(struct kref *kref)
        struct drm_dp_mst_port *port, *tmp;
        bool wake_tx = false;
 
-       cancel_work_sync(&mstb->mgr->work);
-
        /*
         * destroy all ports - don't need lock
         * as there are no more references to the mst branch
@@ -863,29 +861,33 @@ static void drm_dp_destroy_port(struct kref *kref)
 {
        struct drm_dp_mst_port *port = container_of(kref, struct drm_dp_mst_port, kref);
        struct drm_dp_mst_topology_mgr *mgr = port->mgr;
+
        if (!port->input) {
                port->vcpi.num_slots = 0;
 
                kfree(port->cached_edid);
 
-               /* we can't destroy the connector here, as
-                  we might be holding the mode_config.mutex
-                  from an EDID retrieval */
+               /*
+                * The only time we don't have a connector
+                * on an output port is if the connector init
+                * fails.
+                */
                if (port->connector) {
+                       /* we can't destroy the connector here, as
+                        * we might be holding the mode_config.mutex
+                        * from an EDID retrieval */
+
                        mutex_lock(&mgr->destroy_connector_lock);
                        list_add(&port->next, &mgr->destroy_connector_list);
                        mutex_unlock(&mgr->destroy_connector_lock);
                        schedule_work(&mgr->destroy_connector_work);
                        return;
                }
+               /* no need to clean up vcpi
+                * as if we have no connector we never setup a vcpi */
                drm_dp_port_teardown_pdt(port, port->pdt);
-
-               if (!port->input && port->vcpi.vcpi > 0)
-                       drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi);
        }
        kfree(port);
-
-       (*mgr->cbs->hotplug)(mgr);
 }
 
 static void drm_dp_put_port(struct drm_dp_mst_port *port)
@@ -1027,8 +1029,8 @@ static void drm_dp_check_port_guid(struct drm_dp_mst_branch *mstb,
        }
 }
 
-static void build_mst_prop_path(struct drm_dp_mst_port *port,
-                               struct drm_dp_mst_branch *mstb,
+static void build_mst_prop_path(const struct drm_dp_mst_branch *mstb,
+                               int pnum,
                                char *proppath,
                                size_t proppath_size)
 {
@@ -1041,7 +1043,7 @@ static void build_mst_prop_path(struct drm_dp_mst_port *port,
                snprintf(temp, sizeof(temp), "-%d", port_num);
                strlcat(proppath, temp, proppath_size);
        }
-       snprintf(temp, sizeof(temp), "-%d", port->port_num);
+       snprintf(temp, sizeof(temp), "-%d", pnum);
        strlcat(proppath, temp, proppath_size);
 }
 
@@ -1105,22 +1107,32 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
                drm_dp_port_teardown_pdt(port, old_pdt);
 
                ret = drm_dp_port_setup_pdt(port);
-               if (ret == true) {
+               if (ret == true)
                        drm_dp_send_link_address(mstb->mgr, port->mstb);
-                       port->mstb->link_address_sent = true;
-               }
        }
 
        if (created && !port->input) {
                char proppath[255];
-               build_mst_prop_path(port, mstb, proppath, sizeof(proppath));
-               port->connector = (*mstb->mgr->cbs->add_connector)(mstb->mgr, port, proppath);
 
-               if (port->port_num >= 8) {
+               build_mst_prop_path(mstb, port->port_num, proppath, sizeof(proppath));
+               port->connector = (*mstb->mgr->cbs->add_connector)(mstb->mgr, port, proppath);
+               if (!port->connector) {
+                       /* remove it from the port list */
+                       mutex_lock(&mstb->mgr->lock);
+                       list_del(&port->next);
+                       mutex_unlock(&mstb->mgr->lock);
+                       /* drop port list reference */
+                       drm_dp_put_port(port);
+                       goto out;
+               }
+               if (port->port_num >= DP_MST_LOGICAL_PORT_0) {
                        port->cached_edid = drm_get_edid(port->connector, &port->aux.ddc);
+                       drm_mode_connector_set_tile_property(port->connector);
                }
+               (*mstb->mgr->cbs->register_connector)(port->connector);
        }
 
+out:
        /* put reference to this port */
        drm_dp_put_port(port);
 }
@@ -1182,17 +1194,18 @@ static struct drm_dp_mst_branch *drm_dp_get_mst_branch_device(struct drm_dp_mst_
 
                list_for_each_entry(port, &mstb->ports, next) {
                        if (port->port_num == port_num) {
-                               if (!port->mstb) {
+                               mstb = port->mstb;
+                               if (!mstb) {
                                        DRM_ERROR("failed to lookup MSTB with lct %d, rad %02x\n", lct, rad[0]);
-                                       return NULL;
+                                       goto out;
                                }
 
-                               mstb = port->mstb;
                                break;
                        }
                }
        }
        kref_get(&mstb->kref);
+out:
        mutex_unlock(&mgr->lock);
        return mstb;
 }
@@ -1202,10 +1215,9 @@ static void drm_dp_check_and_send_link_address(struct drm_dp_mst_topology_mgr *m
 {
        struct drm_dp_mst_port *port;
        struct drm_dp_mst_branch *mstb_child;
-       if (!mstb->link_address_sent) {
+       if (!mstb->link_address_sent)
                drm_dp_send_link_address(mgr, mstb);
-               mstb->link_address_sent = true;
-       }
+
        list_for_each_entry(port, &mstb->ports, next) {
                if (port->input)
                        continue;
@@ -1458,8 +1470,8 @@ static void drm_dp_queue_down_tx(struct drm_dp_mst_topology_mgr *mgr,
        mutex_unlock(&mgr->qlock);
 }
 
-static int drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
-                                   struct drm_dp_mst_branch *mstb)
+static void drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
+                                    struct drm_dp_mst_branch *mstb)
 {
        int len;
        struct drm_dp_sideband_msg_tx *txmsg;
@@ -1467,11 +1479,12 @@ static int drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
 
        txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
        if (!txmsg)
-               return -ENOMEM;
+               return;
 
        txmsg->dst = mstb;
        len = build_link_address(txmsg);
 
+       mstb->link_address_sent = true;
        drm_dp_queue_down_tx(mgr, txmsg);
 
        ret = drm_dp_mst_wait_tx_reply(mstb, txmsg);
@@ -1499,11 +1512,12 @@ static int drm_dp_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
                        }
                        (*mgr->cbs->hotplug)(mgr);
                }
-       } else
+       } else {
+               mstb->link_address_sent = false;
                DRM_DEBUG_KMS("link address failed %d\n", ret);
+       }
 
        kfree(txmsg);
-       return 0;
 }
 
 static int drm_dp_send_enum_path_resources(struct drm_dp_mst_topology_mgr *mgr,
@@ -1978,6 +1992,8 @@ void drm_dp_mst_topology_mgr_suspend(struct drm_dp_mst_topology_mgr *mgr)
        drm_dp_dpcd_writeb(mgr->aux, DP_MSTM_CTRL,
                           DP_MST_EN | DP_UPSTREAM_IS_SRC);
        mutex_unlock(&mgr->lock);
+       flush_work(&mgr->work);
+       flush_work(&mgr->destroy_connector_work);
 }
 EXPORT_SYMBOL(drm_dp_mst_topology_mgr_suspend);
 
@@ -2263,10 +2279,10 @@ struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_
 
        if (port->cached_edid)
                edid = drm_edid_duplicate(port->cached_edid);
-       else
+       else {
                edid = drm_get_edid(connector, &port->aux.ddc);
-
-       drm_mode_connector_set_tile_property(connector);
+               drm_mode_connector_set_tile_property(connector);
+       }
        drm_dp_put_port(port);
        return edid;
 }
@@ -2671,7 +2687,7 @@ static void drm_dp_destroy_connector_work(struct work_struct *work)
 {
        struct drm_dp_mst_topology_mgr *mgr = container_of(work, struct drm_dp_mst_topology_mgr, destroy_connector_work);
        struct drm_dp_mst_port *port;
-
+       bool send_hotplug = false;
        /*
         * Not a regular list traverse as we have to drop the destroy
         * connector lock before destroying the connector, to avoid AB->BA
@@ -2694,7 +2710,10 @@ static void drm_dp_destroy_connector_work(struct work_struct *work)
                if (!port->input && port->vcpi.vcpi > 0)
                        drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi);
                kfree(port);
+               send_hotplug = true;
        }
+       if (send_hotplug)
+               (*mgr->cbs->hotplug)(mgr);
 }
 
 /**
@@ -2747,6 +2766,7 @@ EXPORT_SYMBOL(drm_dp_mst_topology_mgr_init);
  */
 void drm_dp_mst_topology_mgr_destroy(struct drm_dp_mst_topology_mgr *mgr)
 {
+       flush_work(&mgr->work);
        flush_work(&mgr->destroy_connector_work);
        mutex_lock(&mgr->payload_lock);
        kfree(mgr->payloads);
@@ -2782,12 +2802,13 @@ static int drm_dp_mst_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs
        if (msgs[num - 1].flags & I2C_M_RD)
                reading = true;
 
-       if (!reading) {
+       if (!reading || (num - 1 > DP_REMOTE_I2C_READ_MAX_TRANSACTIONS)) {
                DRM_DEBUG_KMS("Unsupported I2C transaction for MST device\n");
                ret = -EIO;
                goto out;
        }
 
+       memset(&msg, 0, sizeof(msg));
        msg.req_type = DP_REMOTE_I2C_READ;
        msg.u.i2c_read.num_transactions = num - 1;
        msg.u.i2c_read.port_number = port->port_num;
index 418d299f3b129b307f86a970fdf49d3a826af4c8..ca08c472311bd3f6238f7513bc4ac26737228884 100644 (file)
@@ -345,7 +345,11 @@ static bool restore_fbdev_mode(struct drm_fb_helper *fb_helper)
                struct drm_crtc *crtc = mode_set->crtc;
                int ret;
 
-               if (crtc->funcs->cursor_set) {
+               if (crtc->funcs->cursor_set2) {
+                       ret = crtc->funcs->cursor_set2(crtc, NULL, 0, 0, 0, 0, 0);
+                       if (ret)
+                               error = true;
+               } else if (crtc->funcs->cursor_set) {
                        ret = crtc->funcs->cursor_set(crtc, NULL, 0, 0, 0);
                        if (ret)
                                error = true;
index 9a860ca1e9d7e451e571680092c8154b75e1dd14..d93e7378c0779dd54be72447421aa49cc12c3f4f 100644 (file)
@@ -520,7 +520,8 @@ EXPORT_SYMBOL(drm_ioctl_permit);
 
 /** Ioctl table */
 static const struct drm_ioctl_desc drm_ioctls[] = {
-       DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, DRM_UNLOCKED|DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version,
+                     DRM_UNLOCKED|DRM_RENDER_ALLOW|DRM_CONTROL_ALLOW),
        DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0),
        DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0),
        DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY),
index d734780b31c0fdcd67d2d622333b0a78c8098e10..a18164f2f6d28290c09462dd7a755168873a42d3 100644 (file)
@@ -94,7 +94,18 @@ static int drm_helper_probe_add_cmdline_mode(struct drm_connector *connector)
 }
 
 #define DRM_OUTPUT_POLL_PERIOD (10*HZ)
-static void __drm_kms_helper_poll_enable(struct drm_device *dev)
+/**
+ * drm_kms_helper_poll_enable_locked - re-enable output polling.
+ * @dev: drm_device
+ *
+ * This function re-enables the output polling work without
+ * locking the mode_config mutex.
+ *
+ * This is like drm_kms_helper_poll_enable() however it is to be
+ * called from a context where the mode_config mutex is locked
+ * already.
+ */
+void drm_kms_helper_poll_enable_locked(struct drm_device *dev)
 {
        bool poll = false;
        struct drm_connector *connector;
@@ -113,6 +124,8 @@ static void __drm_kms_helper_poll_enable(struct drm_device *dev)
        if (poll)
                schedule_delayed_work(&dev->mode_config.output_poll_work, DRM_OUTPUT_POLL_PERIOD);
 }
+EXPORT_SYMBOL(drm_kms_helper_poll_enable_locked);
+
 
 static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connector *connector,
                                                              uint32_t maxX, uint32_t maxY, bool merge_type_bits)
@@ -174,7 +187,7 @@ static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connect
 
        /* Re-enable polling in case the global poll config changed. */
        if (drm_kms_helper_poll != dev->mode_config.poll_running)
-               __drm_kms_helper_poll_enable(dev);
+               drm_kms_helper_poll_enable_locked(dev);
 
        dev->mode_config.poll_running = drm_kms_helper_poll;
 
@@ -428,7 +441,7 @@ EXPORT_SYMBOL(drm_kms_helper_poll_disable);
 void drm_kms_helper_poll_enable(struct drm_device *dev)
 {
        mutex_lock(&dev->mode_config.mutex);
-       __drm_kms_helper_poll_enable(dev);
+       drm_kms_helper_poll_enable_locked(dev);
        mutex_unlock(&dev->mode_config.mutex);
 }
 EXPORT_SYMBOL(drm_kms_helper_poll_enable);
index 0f6cd33b531f104f5094513a0992eb99361e65b3..684bd4a138439ef254f7123c66ffde989fede279 100644 (file)
@@ -235,18 +235,12 @@ static ssize_t dpms_show(struct device *device,
                           char *buf)
 {
        struct drm_connector *connector = to_drm_connector(device);
-       struct drm_device *dev = connector->dev;
-       uint64_t dpms_status;
-       int ret;
+       int dpms;
 
-       ret = drm_object_property_get_value(&connector->base,
-                                           dev->mode_config.dpms_property,
-                                           &dpms_status);
-       if (ret)
-               return 0;
+       dpms = READ_ONCE(connector->dpms);
 
        return snprintf(buf, PAGE_SIZE, "%s\n",
-                       drm_get_dpms_name((int)dpms_status));
+                       drm_get_dpms_name(dpms));
 }
 
 static ssize_t enabled_show(struct device *device,
index cbdb78ef3baca57cd1ddf701425b953f140377f2..e6cbaca821a47b9740f4d35d7cfce00bbd0aa11a 100644 (file)
@@ -37,7 +37,6 @@
  * DECON stands for Display and Enhancement controller.
  */
 
-#define DECON_DEFAULT_FRAMERATE 60
 #define MIN_FB_WIDTH_FOR_16WORD_BURST 128
 
 #define WINDOWS_NR     2
@@ -165,16 +164,6 @@ static u32 decon_calc_clkdiv(struct decon_context *ctx,
        return (clkdiv < 0x100) ? clkdiv : 0xff;
 }
 
-static bool decon_mode_fixup(struct exynos_drm_crtc *crtc,
-               const struct drm_display_mode *mode,
-               struct drm_display_mode *adjusted_mode)
-{
-       if (adjusted_mode->vrefresh == 0)
-               adjusted_mode->vrefresh = DECON_DEFAULT_FRAMERATE;
-
-       return true;
-}
-
 static void decon_commit(struct exynos_drm_crtc *crtc)
 {
        struct decon_context *ctx = crtc->ctx;
@@ -637,7 +626,6 @@ static void decon_disable(struct exynos_drm_crtc *crtc)
 static const struct exynos_drm_crtc_ops decon_crtc_ops = {
        .enable = decon_enable,
        .disable = decon_disable,
-       .mode_fixup = decon_mode_fixup,
        .commit = decon_commit,
        .enable_vblank = decon_enable_vblank,
        .disable_vblank = decon_disable_vblank,
index d66ade0efac892b84ce7e26c4f9e132870806d33..124fb9a56f02b596b5a6c4cf6cbf3f28151f4470 100644 (file)
@@ -1383,28 +1383,6 @@ static int exynos_dp_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int exynos_dp_suspend(struct device *dev)
-{
-       struct exynos_dp_device *dp = dev_get_drvdata(dev);
-
-       exynos_dp_disable(&dp->encoder);
-       return 0;
-}
-
-static int exynos_dp_resume(struct device *dev)
-{
-       struct exynos_dp_device *dp = dev_get_drvdata(dev);
-
-       exynos_dp_enable(&dp->encoder);
-       return 0;
-}
-#endif
-
-static const struct dev_pm_ops exynos_dp_pm_ops = {
-       SET_SYSTEM_SLEEP_PM_OPS(exynos_dp_suspend, exynos_dp_resume)
-};
-
 static const struct of_device_id exynos_dp_match[] = {
        { .compatible = "samsung,exynos5-dp" },
        {},
@@ -1417,7 +1395,6 @@ struct platform_driver dp_driver = {
        .driver         = {
                .name   = "exynos-dp",
                .owner  = THIS_MODULE,
-               .pm     = &exynos_dp_pm_ops,
                .of_match_table = exynos_dp_match,
        },
 };
index c68a6a2a9b5794558015abdeefb0e58c4958049d..7f55ba6771c6b94e5f45bee6bdec078c27c74f5b 100644 (file)
@@ -28,7 +28,6 @@ int exynos_drm_subdrv_register(struct exynos_drm_subdrv *subdrv)
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(exynos_drm_subdrv_register);
 
 int exynos_drm_subdrv_unregister(struct exynos_drm_subdrv *subdrv)
 {
@@ -39,7 +38,6 @@ int exynos_drm_subdrv_unregister(struct exynos_drm_subdrv *subdrv)
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(exynos_drm_subdrv_unregister);
 
 int exynos_drm_device_subdrv_probe(struct drm_device *dev)
 {
@@ -69,7 +67,6 @@ int exynos_drm_device_subdrv_probe(struct drm_device *dev)
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(exynos_drm_device_subdrv_probe);
 
 int exynos_drm_device_subdrv_remove(struct drm_device *dev)
 {
@@ -87,7 +84,6 @@ int exynos_drm_device_subdrv_remove(struct drm_device *dev)
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(exynos_drm_device_subdrv_remove);
 
 int exynos_drm_subdrv_open(struct drm_device *dev, struct drm_file *file)
 {
@@ -111,7 +107,6 @@ err:
        }
        return ret;
 }
-EXPORT_SYMBOL_GPL(exynos_drm_subdrv_open);
 
 void exynos_drm_subdrv_close(struct drm_device *dev, struct drm_file *file)
 {
@@ -122,4 +117,3 @@ void exynos_drm_subdrv_close(struct drm_device *dev, struct drm_file *file)
                        subdrv->close(dev, subdrv->dev, file);
        }
 }
-EXPORT_SYMBOL_GPL(exynos_drm_subdrv_close);
index 0872aa2f450f273a992bc414081e8501e11bf787..ed28823d3b35ef704a5dded0c1c55c1eff6ef3ed 100644 (file)
@@ -41,20 +41,6 @@ static void exynos_drm_crtc_disable(struct drm_crtc *crtc)
                exynos_crtc->ops->disable(exynos_crtc);
 }
 
-static bool
-exynos_drm_crtc_mode_fixup(struct drm_crtc *crtc,
-                           const struct drm_display_mode *mode,
-                           struct drm_display_mode *adjusted_mode)
-{
-       struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
-
-       if (exynos_crtc->ops->mode_fixup)
-               return exynos_crtc->ops->mode_fixup(exynos_crtc, mode,
-                                                   adjusted_mode);
-
-       return true;
-}
-
 static void
 exynos_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
 {
@@ -99,7 +85,6 @@ static void exynos_crtc_atomic_flush(struct drm_crtc *crtc,
 static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
        .enable         = exynos_drm_crtc_enable,
        .disable        = exynos_drm_crtc_disable,
-       .mode_fixup     = exynos_drm_crtc_mode_fixup,
        .mode_set_nofb  = exynos_drm_crtc_mode_set_nofb,
        .atomic_begin   = exynos_crtc_atomic_begin,
        .atomic_flush   = exynos_crtc_atomic_flush,
index 831d2e4cacf9d0bb951f5bbd9d7bbfab4b681c91..ae9e6b2d3758a97104ac6be69f1a970e6c0f3bb6 100644 (file)
@@ -304,6 +304,7 @@ int exynos_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state,
        return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
 static int exynos_drm_suspend(struct drm_device *dev, pm_message_t state)
 {
        struct drm_connector *connector;
@@ -340,6 +341,7 @@ static int exynos_drm_resume(struct drm_device *dev)
 
        return 0;
 }
+#endif
 
 static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
 {
index b7ba21dfb69641f36410550711f024fde541bb72..6c717ba672dbc8ad41fcc3adedfc82c32c6de5bc 100644 (file)
@@ -82,7 +82,6 @@ struct exynos_drm_plane {
  *
  * @enable: enable the device
  * @disable: disable the device
- * @mode_fixup: fix mode data before applying it
  * @commit: set current hw specific display mode to hw.
  * @enable_vblank: specific driver callback for enabling vblank interrupt.
  * @disable_vblank: specific driver callback for disabling vblank interrupt.
@@ -103,9 +102,6 @@ struct exynos_drm_crtc;
 struct exynos_drm_crtc_ops {
        void (*enable)(struct exynos_drm_crtc *crtc);
        void (*disable)(struct exynos_drm_crtc *crtc);
-       bool (*mode_fixup)(struct exynos_drm_crtc *crtc,
-                               const struct drm_display_mode *mode,
-                               struct drm_display_mode *adjusted_mode);
        void (*commit)(struct exynos_drm_crtc *crtc);
        int (*enable_vblank)(struct exynos_drm_crtc *crtc);
        void (*disable_vblank)(struct exynos_drm_crtc *crtc);
index 2a652359af644b51f257cde7528d70b6016897da..dd3a5e6d58c8f04c43fb8afd7c7b6243f7312761 100644 (file)
@@ -1206,23 +1206,6 @@ static struct exynos_drm_ipp_ops fimc_dst_ops = {
        .set_addr = fimc_dst_set_addr,
 };
 
-static int fimc_clk_ctrl(struct fimc_context *ctx, bool enable)
-{
-       DRM_DEBUG_KMS("enable[%d]\n", enable);
-
-       if (enable) {
-               clk_prepare_enable(ctx->clocks[FIMC_CLK_GATE]);
-               clk_prepare_enable(ctx->clocks[FIMC_CLK_WB_A]);
-               ctx->suspended = false;
-       } else {
-               clk_disable_unprepare(ctx->clocks[FIMC_CLK_GATE]);
-               clk_disable_unprepare(ctx->clocks[FIMC_CLK_WB_A]);
-               ctx->suspended = true;
-       }
-
-       return 0;
-}
-
 static irqreturn_t fimc_irq_handler(int irq, void *dev_id)
 {
        struct fimc_context *ctx = dev_id;
@@ -1780,6 +1763,24 @@ static int fimc_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int fimc_clk_ctrl(struct fimc_context *ctx, bool enable)
+{
+       DRM_DEBUG_KMS("enable[%d]\n", enable);
+
+       if (enable) {
+               clk_prepare_enable(ctx->clocks[FIMC_CLK_GATE]);
+               clk_prepare_enable(ctx->clocks[FIMC_CLK_WB_A]);
+               ctx->suspended = false;
+       } else {
+               clk_disable_unprepare(ctx->clocks[FIMC_CLK_GATE]);
+               clk_disable_unprepare(ctx->clocks[FIMC_CLK_WB_A]);
+               ctx->suspended = true;
+       }
+
+       return 0;
+}
+
 #ifdef CONFIG_PM_SLEEP
 static int fimc_suspend(struct device *dev)
 {
@@ -1806,7 +1807,6 @@ static int fimc_resume(struct device *dev)
 }
 #endif
 
-#ifdef CONFIG_PM
 static int fimc_runtime_suspend(struct device *dev)
 {
        struct fimc_context *ctx = get_fimc_context(dev);
index 750a9e6b9e8d92c312e3bb685fb524f249ad0488..3d1aba67758baf4a4e25e4c383e300d5a6dd954e 100644 (file)
@@ -41,7 +41,6 @@
  * CPU Interface.
  */
 
-#define FIMD_DEFAULT_FRAMERATE 60
 #define MIN_FB_WIDTH_FOR_16WORD_BURST 128
 
 /* position control register for hardware window 0, 2 ~ 4.*/
@@ -377,16 +376,6 @@ static u32 fimd_calc_clkdiv(struct fimd_context *ctx,
        return (clkdiv < 0x100) ? clkdiv : 0xff;
 }
 
-static bool fimd_mode_fixup(struct exynos_drm_crtc *crtc,
-               const struct drm_display_mode *mode,
-               struct drm_display_mode *adjusted_mode)
-{
-       if (adjusted_mode->vrefresh == 0)
-               adjusted_mode->vrefresh = FIMD_DEFAULT_FRAMERATE;
-
-       return true;
-}
-
 static void fimd_commit(struct exynos_drm_crtc *crtc)
 {
        struct fimd_context *ctx = crtc->ctx;
@@ -882,13 +871,12 @@ static void fimd_dp_clock_enable(struct exynos_drm_crtc *crtc, bool enable)
                return;
 
        val = enable ? DP_MIE_CLK_DP_ENABLE : DP_MIE_CLK_DISABLE;
-       writel(DP_MIE_CLK_DP_ENABLE, ctx->regs + DP_MIE_CLKCON);
+       writel(val, ctx->regs + DP_MIE_CLKCON);
 }
 
 static const struct exynos_drm_crtc_ops fimd_crtc_ops = {
        .enable = fimd_enable,
        .disable = fimd_disable,
-       .mode_fixup = fimd_mode_fixup,
        .commit = fimd_commit,
        .enable_vblank = fimd_enable_vblank,
        .disable_vblank = fimd_disable_vblank,
index 3734c34aed16a22938509454cf794e5b4069ac35..c17efdb238a6e24f6fcecac58c395b8964b12703 100644 (file)
@@ -1059,7 +1059,6 @@ int exynos_g2d_get_ver_ioctl(struct drm_device *drm_dev, void *data,
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(exynos_g2d_get_ver_ioctl);
 
 int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
                                 struct drm_file *file)
@@ -1230,7 +1229,6 @@ err:
        g2d_put_cmdlist(g2d, node);
        return ret;
 }
-EXPORT_SYMBOL_GPL(exynos_g2d_set_cmdlist_ioctl);
 
 int exynos_g2d_exec_ioctl(struct drm_device *drm_dev, void *data,
                          struct drm_file *file)
@@ -1293,7 +1291,6 @@ int exynos_g2d_exec_ioctl(struct drm_device *drm_dev, void *data,
 out:
        return 0;
 }
-EXPORT_SYMBOL_GPL(exynos_g2d_exec_ioctl);
 
 static int g2d_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
 {
index f12fbc36b120065902c50253a4e91e9cc8952df5..407afedb60031a00f7f0cc5cb599cf7b3e57a9b8 100644 (file)
@@ -56,39 +56,35 @@ static int exynos_drm_alloc_buf(struct exynos_drm_gem_obj *obj)
        nr_pages = obj->size >> PAGE_SHIFT;
 
        if (!is_drm_iommu_supported(dev)) {
-               dma_addr_t start_addr;
-               unsigned int i = 0;
-
                obj->pages = drm_calloc_large(nr_pages, sizeof(struct page *));
                if (!obj->pages) {
                        DRM_ERROR("failed to allocate pages.\n");
                        return -ENOMEM;
                }
+       }
 
-               obj->cookie = dma_alloc_attrs(dev->dev,
-                                       obj->size,
-                                       &obj->dma_addr, GFP_KERNEL,
-                                       &obj->dma_attrs);
-               if (!obj->cookie) {
-                       DRM_ERROR("failed to allocate buffer.\n");
+       obj->cookie = dma_alloc_attrs(dev->dev, obj->size, &obj->dma_addr,
+                                     GFP_KERNEL, &obj->dma_attrs);
+       if (!obj->cookie) {
+               DRM_ERROR("failed to allocate buffer.\n");
+               if (obj->pages)
                        drm_free_large(obj->pages);
-                       return -ENOMEM;
-               }
+               return -ENOMEM;
+       }
+
+       if (obj->pages) {
+               dma_addr_t start_addr;
+               unsigned int i = 0;
 
                start_addr = obj->dma_addr;
                while (i < nr_pages) {
-                       obj->pages[i] = phys_to_page(start_addr);
+                       obj->pages[i] = pfn_to_page(dma_to_pfn(dev->dev,
+                                                              start_addr));
                        start_addr += PAGE_SIZE;
                        i++;
                }
        } else {
-               obj->pages = dma_alloc_attrs(dev->dev, obj->size,
-                                       &obj->dma_addr, GFP_KERNEL,
-                                       &obj->dma_attrs);
-               if (!obj->pages) {
-                       DRM_ERROR("failed to allocate buffer.\n");
-                       return -ENOMEM;
-               }
+               obj->pages = obj->cookie;
        }
 
        DRM_DEBUG_KMS("dma_addr(0x%lx), size(0x%lx)\n",
@@ -110,15 +106,11 @@ static void exynos_drm_free_buf(struct exynos_drm_gem_obj *obj)
        DRM_DEBUG_KMS("dma_addr(0x%lx), size(0x%lx)\n",
                        (unsigned long)obj->dma_addr, obj->size);
 
-       if (!is_drm_iommu_supported(dev)) {
-               dma_free_attrs(dev->dev, obj->size, obj->cookie,
-                               (dma_addr_t)obj->dma_addr, &obj->dma_attrs);
-               drm_free_large(obj->pages);
-       } else
-               dma_free_attrs(dev->dev, obj->size, obj->pages,
-                               (dma_addr_t)obj->dma_addr, &obj->dma_attrs);
+       dma_free_attrs(dev->dev, obj->size, obj->cookie,
+                       (dma_addr_t)obj->dma_addr, &obj->dma_attrs);
 
-       obj->dma_addr = (dma_addr_t)NULL;
+       if (!is_drm_iommu_supported(dev))
+               drm_free_large(obj->pages);
 }
 
 static int exynos_drm_gem_handle_create(struct drm_gem_object *obj,
@@ -156,18 +148,14 @@ void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj)
         * once dmabuf's refcount becomes 0.
         */
        if (obj->import_attach)
-               goto out;
-
-       exynos_drm_free_buf(exynos_gem_obj);
-
-out:
-       drm_gem_free_mmap_offset(obj);
+               drm_prime_gem_destroy(obj, exynos_gem_obj->sgt);
+       else
+               exynos_drm_free_buf(exynos_gem_obj);
 
        /* release file pointer to gem object. */
        drm_gem_object_release(obj);
 
        kfree(exynos_gem_obj);
-       exynos_gem_obj = NULL;
 }
 
 unsigned long exynos_drm_gem_get_size(struct drm_device *dev,
@@ -190,8 +178,7 @@ unsigned long exynos_drm_gem_get_size(struct drm_device *dev,
        return exynos_gem_obj->size;
 }
 
-
-struct exynos_drm_gem_obj *exynos_drm_gem_init(struct drm_device *dev,
+static struct exynos_drm_gem_obj *exynos_drm_gem_init(struct drm_device *dev,
                                                      unsigned long size)
 {
        struct exynos_drm_gem_obj *exynos_gem_obj;
@@ -212,6 +199,13 @@ struct exynos_drm_gem_obj *exynos_drm_gem_init(struct drm_device *dev,
                return ERR_PTR(ret);
        }
 
+       ret = drm_gem_create_mmap_offset(obj);
+       if (ret < 0) {
+               drm_gem_object_release(obj);
+               kfree(exynos_gem_obj);
+               return ERR_PTR(ret);
+       }
+
        DRM_DEBUG_KMS("created file object = 0x%x\n", (unsigned int)obj->filp);
 
        return exynos_gem_obj;
@@ -313,7 +307,7 @@ void exynos_drm_gem_put_dma_addr(struct drm_device *dev,
        drm_gem_object_unreference_unlocked(obj);
 }
 
-int exynos_drm_gem_mmap_buffer(struct exynos_drm_gem_obj *exynos_gem_obj,
+static int exynos_drm_gem_mmap_buffer(struct exynos_drm_gem_obj *exynos_gem_obj,
                                      struct vm_area_struct *vma)
 {
        struct drm_device *drm_dev = exynos_gem_obj->base.dev;
@@ -342,7 +336,8 @@ int exynos_drm_gem_mmap_buffer(struct exynos_drm_gem_obj *exynos_gem_obj,
 
 int exynos_drm_gem_get_ioctl(struct drm_device *dev, void *data,
                                      struct drm_file *file_priv)
-{      struct exynos_drm_gem_obj *exynos_gem_obj;
+{
+       struct exynos_drm_gem_obj *exynos_gem_obj;
        struct drm_exynos_gem_info *args = data;
        struct drm_gem_object *obj;
 
@@ -402,6 +397,7 @@ int exynos_drm_gem_dumb_create(struct drm_file *file_priv,
                               struct drm_mode_create_dumb *args)
 {
        struct exynos_drm_gem_obj *exynos_gem_obj;
+       unsigned int flags;
        int ret;
 
        /*
@@ -413,16 +409,12 @@ int exynos_drm_gem_dumb_create(struct drm_file *file_priv,
        args->pitch = args->width * ((args->bpp + 7) / 8);
        args->size = args->pitch * args->height;
 
-       if (is_drm_iommu_supported(dev)) {
-               exynos_gem_obj = exynos_drm_gem_create(dev,
-                       EXYNOS_BO_NONCONTIG | EXYNOS_BO_WC,
-                       args->size);
-       } else {
-               exynos_gem_obj = exynos_drm_gem_create(dev,
-                       EXYNOS_BO_CONTIG | EXYNOS_BO_WC,
-                       args->size);
-       }
+       if (is_drm_iommu_supported(dev))
+               flags = EXYNOS_BO_NONCONTIG | EXYNOS_BO_WC;
+       else
+               flags = EXYNOS_BO_CONTIG | EXYNOS_BO_WC;
 
+       exynos_gem_obj = exynos_drm_gem_create(dev, flags, args->size);
        if (IS_ERR(exynos_gem_obj)) {
                dev_warn(dev->dev, "FB allocation failed.\n");
                return PTR_ERR(exynos_gem_obj);
@@ -460,14 +452,9 @@ int exynos_drm_gem_dumb_map_offset(struct drm_file *file_priv,
                goto unlock;
        }
 
-       ret = drm_gem_create_mmap_offset(obj);
-       if (ret)
-               goto out;
-
        *offset = drm_vma_node_offset_addr(&obj->vma_node);
        DRM_DEBUG_KMS("offset = 0x%lx\n", (unsigned long)*offset);
 
-out:
        drm_gem_object_unreference(obj);
 unlock:
        mutex_unlock(&dev->struct_mutex);
@@ -543,7 +530,6 @@ int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
 
 err_close_vm:
        drm_gem_vm_close(vma);
-       drm_gem_free_mmap_offset(obj);
 
        return ret;
 }
@@ -588,6 +574,8 @@ exynos_drm_gem_prime_import_sg_table(struct drm_device *dev,
        if (ret < 0)
                goto err_free_large;
 
+       exynos_gem_obj->sgt = sgt;
+
        if (sgt->nents == 1) {
                /* always physically continuous memory if sgt->nents is 1. */
                exynos_gem_obj->flags |= EXYNOS_BO_CONTIG;
index cd62f8410d1e5d86f6dd221aebf924be1fe71db9..b62d1007c0e05f88e4cfc38970bb7baa9a87fe7a 100644 (file)
@@ -39,6 +39,7 @@
  *     - this address could be physical address without IOMMU and
  *     device address with IOMMU.
  * @pages: Array of backing pages.
+ * @sgt: Imported sg_table.
  *
  * P.S. this object would be transferred to user as kms_bo.handle so
  *     user can access the buffer through kms_bo.handle.
@@ -52,6 +53,7 @@ struct exynos_drm_gem_obj {
        dma_addr_t              dma_addr;
        struct dma_attrs        dma_attrs;
        struct page             **pages;
+       struct sg_table         *sgt;
 };
 
 struct page **exynos_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask);
@@ -59,10 +61,6 @@ struct page **exynos_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask);
 /* destroy a buffer with gem object */
 void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj);
 
-/* create a private gem object and initialize it. */
-struct exynos_drm_gem_obj *exynos_drm_gem_init(struct drm_device *dev,
-                                                     unsigned long size);
-
 /* create a new buffer with gem object */
 struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
                                                unsigned int flags,
index 425e7062538812c0613c055b9b4fdeea709c4be0..2f5c118f4c8ef5ea27a68532756ca77549e325f4 100644 (file)
@@ -786,6 +786,7 @@ static int rotator_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_PM
 static int rotator_clk_crtl(struct rot_context *rot, bool enable)
 {
        if (enable) {
@@ -822,7 +823,6 @@ static int rotator_resume(struct device *dev)
 }
 #endif
 
-#ifdef CONFIG_PM
 static int rotator_runtime_suspend(struct device *dev)
 {
        struct rot_context *rot = dev_get_drvdata(dev);
index 82be6b86a1686d20e6e46000b4bc5a2246cbddd4..d1e300dcd544a7cad7eb115849b307a6b73a7867 100644 (file)
@@ -58,7 +58,8 @@ static void fsl_dcu_drm_plane_atomic_disable(struct drm_plane *plane,
                                             struct drm_plane_state *old_state)
 {
        struct fsl_dcu_drm_device *fsl_dev = plane->dev->dev_private;
-       unsigned int index, value, ret;
+       unsigned int value;
+       int index, ret;
 
        index = fsl_dcu_drm_plane_index(plane);
        if (index < 0)
index f6ecbda2c60475297b36b1da6cff0766fb0fe833..674341708033b0aa2900ee0776db9a78424b2028 100644 (file)
@@ -143,7 +143,7 @@ i915_gem_shrink(struct drm_i915_private *dev_priv,
 }
 
 /**
- * i915_gem_shrink - Shrink buffer object caches completely
+ * i915_gem_shrink_all - Shrink buffer object caches completely
  * @dev_priv: i915 device
  *
  * This is a simple wraper around i915_gem_shrink() to aggressively shrink all
index 8fd431bcdfd3a33ffb6afda7a1584b44e33d8296..a96b9006a51e5a893eea071d1d638ef3c2cef6fb 100644 (file)
@@ -804,7 +804,10 @@ static const struct drm_i915_gem_object_ops i915_gem_userptr_ops = {
  * Also note, that the object created here is not currently a "first class"
  * object, in that several ioctls are banned. These are the CPU access
  * ioctls: mmap(), pwrite and pread. In practice, you are expected to use
- * direct access via your pointer rather than use those ioctls.
+ * direct access via your pointer rather than use those ioctls. Another
+ * restriction is that we do not allow userptr surfaces to be pinned to the
+ * hardware and so we reject any attempt to create a framebuffer out of a
+ * userptr.
  *
  * If you think this is a good interface to use to pass GPU memory between
  * drivers, please use dma-buf instead. In fact, wherever possible use
index 5a244ab9395ba2c9f61278a1293850d5e75bc9c4..39d73dbc1c4774857a96b7dedf0fe2d156177759 100644 (file)
@@ -639,6 +639,32 @@ static int __intel_get_crtc_scanline(struct intel_crtc *crtc)
        else
                position = __raw_i915_read32(dev_priv, PIPEDSL(pipe)) & DSL_LINEMASK_GEN3;
 
+       /*
+        * On HSW, the DSL reg (0x70000) appears to return 0 if we
+        * read it just before the start of vblank.  So try it again
+        * so we don't accidentally end up spanning a vblank frame
+        * increment, causing the pipe_update_end() code to squak at us.
+        *
+        * The nature of this problem means we can't simply check the ISR
+        * bit and return the vblank start value; nor can we use the scanline
+        * debug register in the transcoder as it appears to have the same
+        * problem.  We may need to extend this to include other platforms,
+        * but so far testing only shows the problem on HSW.
+        */
+       if (IS_HASWELL(dev) && !position) {
+               int i, temp;
+
+               for (i = 0; i < 100; i++) {
+                       udelay(1);
+                       temp = __raw_i915_read32(dev_priv, PIPEDSL(pipe)) &
+                               DSL_LINEMASK_GEN3;
+                       if (temp != position) {
+                               position = temp;
+                               break;
+                       }
+               }
+       }
+
        /*
         * See update_scanline_offset() for the details on the
         * scanline_offset adjustment.
index 89c1a8ce1f985b9d56b0159f6270eb94e2c09788..2a5c76faf9f8dbc19ec6d17c490ff833d61d6afd 100644 (file)
@@ -430,7 +430,7 @@ void intel_audio_codec_enable(struct intel_encoder *intel_encoder)
 
 /**
  * intel_audio_codec_disable - Disable the audio codec for HD audio
- * @encoder: encoder on which to disable audio
+ * @intel_encoder: encoder on which to disable audio
  *
  * The disable sequences must be performed before disabling the transcoder or
  * port.
index b3e437b3bb54fe4d3e64839b87a161a7dd1240d8..c19e669ffe504e32218afd4aee47670afc3982c9 100644 (file)
@@ -42,7 +42,7 @@ find_section(const void *_bdb, int section_id)
        const struct bdb_header *bdb = _bdb;
        const u8 *base = _bdb;
        int index = 0;
-       u16 total, current_size;
+       u32 total, current_size;
        u8 current_id;
 
        /* skip to first section */
@@ -57,6 +57,10 @@ find_section(const void *_bdb, int section_id)
                current_size = *((const u16 *)(base + index));
                index += 2;
 
+               /* The MIPI Sequence Block v3+ has a separate size field. */
+               if (current_id == BDB_MIPI_SEQUENCE && *(base + index) >= 3)
+                       current_size = *((const u32 *)(base + index + 1));
+
                if (index + current_size > total)
                        return NULL;
 
@@ -799,6 +803,12 @@ parse_mipi(struct drm_i915_private *dev_priv, const struct bdb_header *bdb)
                return;
        }
 
+       /* Fail gracefully for forward incompatible sequence block. */
+       if (sequence->version >= 3) {
+               DRM_ERROR("Unable to parse MIPI Sequence Block v3+\n");
+               return;
+       }
+
        DRM_DEBUG_DRIVER("Found MIPI sequence block\n");
 
        block_size = get_blocksize(sequence);
index 8cc9264f78094c8cfcb101c16d61caf40729323e..b2270d576979bd2acf42b6bec10d48eed947ab57 100644 (file)
@@ -1724,6 +1724,15 @@ static void i9xx_enable_pll(struct intel_crtc *crtc)
                           I915_READ(DPLL(!crtc->pipe)) | DPLL_DVO_2X_MODE);
        }
 
+       /*
+        * Apparently we need to have VGA mode enabled prior to changing
+        * the P1/P2 dividers. Otherwise the DPLL will keep using the old
+        * dividers, even though the register value does change.
+        */
+       I915_WRITE(reg, 0);
+
+       I915_WRITE(reg, dpll);
+
        /* Wait for the clocks to stabilize. */
        POSTING_READ(reg);
        udelay(150);
@@ -14107,6 +14116,11 @@ static int intel_user_framebuffer_create_handle(struct drm_framebuffer *fb,
        struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
        struct drm_i915_gem_object *obj = intel_fb->obj;
 
+       if (obj->userptr.mm) {
+               DRM_DEBUG("attempting to use a userptr for a framebuffer, denied\n");
+               return -EINVAL;
+       }
+
        return drm_gem_handle_create(file, &obj->base, handle);
 }
 
@@ -14897,9 +14911,19 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
        /* restore vblank interrupts to correct state */
        drm_crtc_vblank_reset(&crtc->base);
        if (crtc->active) {
+               struct intel_plane *plane;
+
                drm_calc_timestamping_constants(&crtc->base, &crtc->base.hwmode);
                update_scanline_offset(crtc);
                drm_crtc_vblank_on(&crtc->base);
+
+               /* Disable everything but the primary plane */
+               for_each_intel_plane_on_crtc(dev, crtc, plane) {
+                       if (plane->base.type == DRM_PLANE_TYPE_PRIMARY)
+                               continue;
+
+                       plane->disable_plane(&plane->base, &crtc->base);
+               }
        }
 
        /* We need to sanitize the plane -> pipe mapping first because this will
@@ -15067,35 +15091,25 @@ void i915_redisable_vga(struct drm_device *dev)
        i915_redisable_vga_power_on(dev);
 }
 
-static bool primary_get_hw_state(struct intel_crtc *crtc)
+static bool primary_get_hw_state(struct intel_plane *plane)
 {
-       struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 
-       return !!(I915_READ(DSPCNTR(crtc->plane)) & DISPLAY_PLANE_ENABLE);
+       return I915_READ(DSPCNTR(plane->plane)) & DISPLAY_PLANE_ENABLE;
 }
 
-static void readout_plane_state(struct intel_crtc *crtc,
-                               struct intel_crtc_state *crtc_state)
+/* FIXME read out full plane state for all planes */
+static void readout_plane_state(struct intel_crtc *crtc)
 {
-       struct intel_plane *p;
-       struct intel_plane_state *plane_state;
-       bool active = crtc_state->base.active;
-
-       for_each_intel_plane(crtc->base.dev, p) {
-               if (crtc->pipe != p->pipe)
-                       continue;
-
-               plane_state = to_intel_plane_state(p->base.state);
+       struct drm_plane *primary = crtc->base.primary;
+       struct intel_plane_state *plane_state =
+               to_intel_plane_state(primary->state);
 
-               if (p->base.type == DRM_PLANE_TYPE_PRIMARY)
-                       plane_state->visible = primary_get_hw_state(crtc);
-               else {
-                       if (active)
-                               p->disable_plane(&p->base, &crtc->base);
+       plane_state->visible =
+               primary_get_hw_state(to_intel_plane(primary));
 
-                       plane_state->visible = false;
-               }
-       }
+       if (plane_state->visible)
+               crtc->base.state->plane_mask |= 1 << drm_plane_index(primary);
 }
 
 static void intel_modeset_readout_hw_state(struct drm_device *dev)
@@ -15118,34 +15132,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
                crtc->base.state->active = crtc->active;
                crtc->base.enabled = crtc->active;
 
-               memset(&crtc->base.mode, 0, sizeof(crtc->base.mode));
-               if (crtc->base.state->active) {
-                       intel_mode_from_pipe_config(&crtc->base.mode, crtc->config);
-                       intel_mode_from_pipe_config(&crtc->base.state->adjusted_mode, crtc->config);
-                       WARN_ON(drm_atomic_set_mode_for_crtc(crtc->base.state, &crtc->base.mode));
-
-                       /*
-                        * The initial mode needs to be set in order to keep
-                        * the atomic core happy. It wants a valid mode if the
-                        * crtc's enabled, so we do the above call.
-                        *
-                        * At this point some state updated by the connectors
-                        * in their ->detect() callback has not run yet, so
-                        * no recalculation can be done yet.
-                        *
-                        * Even if we could do a recalculation and modeset
-                        * right now it would cause a double modeset if
-                        * fbdev or userspace chooses a different initial mode.
-                        *
-                        * If that happens, someone indicated they wanted a
-                        * mode change, which means it's safe to do a full
-                        * recalculation.
-                        */
-                       crtc->base.state->mode.private_flags = I915_MODE_FLAG_INHERITED;
-               }
-
-               crtc->base.hwmode = crtc->config->base.adjusted_mode;
-               readout_plane_state(crtc, to_intel_crtc_state(crtc->base.state));
+               readout_plane_state(crtc);
 
                DRM_DEBUG_KMS("[CRTC:%d] hw state readout: %s\n",
                              crtc->base.base.id,
@@ -15204,6 +15191,36 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
                              connector->base.name,
                              connector->base.encoder ? "enabled" : "disabled");
        }
+
+       for_each_intel_crtc(dev, crtc) {
+               crtc->base.hwmode = crtc->config->base.adjusted_mode;
+
+               memset(&crtc->base.mode, 0, sizeof(crtc->base.mode));
+               if (crtc->base.state->active) {
+                       intel_mode_from_pipe_config(&crtc->base.mode, crtc->config);
+                       intel_mode_from_pipe_config(&crtc->base.state->adjusted_mode, crtc->config);
+                       WARN_ON(drm_atomic_set_mode_for_crtc(crtc->base.state, &crtc->base.mode));
+
+                       /*
+                        * The initial mode needs to be set in order to keep
+                        * the atomic core happy. It wants a valid mode if the
+                        * crtc's enabled, so we do the above call.
+                        *
+                        * At this point some state updated by the connectors
+                        * in their ->detect() callback has not run yet, so
+                        * no recalculation can be done yet.
+                        *
+                        * Even if we could do a recalculation and modeset
+                        * right now it would cause a double modeset if
+                        * fbdev or userspace chooses a different initial mode.
+                        *
+                        * If that happens, someone indicated they wanted a
+                        * mode change, which means it's safe to do a full
+                        * recalculation.
+                        */
+                       crtc->base.state->mode.private_flags = I915_MODE_FLAG_INHERITED;
+               }
+       }
 }
 
 /* Scan out the current hw modeset state,
index 3e4be5a3becdddf9fd2a23e6be26f02da90a28f2..6ade068884328680ffe024dd91eabb9ffe6d9013 100644 (file)
@@ -462,11 +462,17 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo
        drm_object_attach_property(&connector->base, dev->mode_config.tile_property, 0);
 
        drm_mode_connector_set_path_property(connector, pathprop);
+       return connector;
+}
+
+static void intel_dp_register_mst_connector(struct drm_connector *connector)
+{
+       struct intel_connector *intel_connector = to_intel_connector(connector);
+       struct drm_device *dev = connector->dev;
        drm_modeset_lock_all(dev);
        intel_connector_add_to_fbdev(intel_connector);
        drm_modeset_unlock_all(dev);
        drm_connector_register(&intel_connector->base);
-       return connector;
 }
 
 static void intel_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
@@ -512,6 +518,7 @@ static void intel_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr)
 
 static struct drm_dp_mst_topology_cbs mst_cbs = {
        .add_connector = intel_dp_add_mst_connector,
+       .register_connector = intel_dp_register_mst_connector,
        .destroy_connector = intel_dp_destroy_mst_connector,
        .hotplug = intel_dp_mst_hotplug,
 };
index 53c0173a39fe182d5d2e50ac2ffc6637f77526fd..b17785719598c9ca867340dc77aaed858f0c72db 100644 (file)
@@ -180,7 +180,7 @@ static void intel_hpd_irq_storm_disable(struct drm_i915_private *dev_priv)
 
        /* Enable polling and queue hotplug re-enabling. */
        if (hpd_disabled) {
-               drm_kms_helper_poll_enable(dev);
+               drm_kms_helper_poll_enable_locked(dev);
                mod_delayed_work(system_wq, &dev_priv->hotplug.reenable_work,
                                 msecs_to_jiffies(HPD_STORM_REENABLE_DELAY));
        }
index 72e0edd7bbde77d3b12812bead2a3f676589385a..29dd4488dc49856b6518ba5fce760cbd4710a1e8 100644 (file)
@@ -484,18 +484,18 @@ void intel_lrc_irq_handler(struct intel_engine_cs *ring)
        status_pointer = I915_READ(RING_CONTEXT_STATUS_PTR(ring));
 
        read_pointer = ring->next_context_status_buffer;
-       write_pointer = status_pointer & 0x07;
+       write_pointer = status_pointer & GEN8_CSB_PTR_MASK;
        if (read_pointer > write_pointer)
-               write_pointer += 6;
+               write_pointer += GEN8_CSB_ENTRIES;
 
        spin_lock(&ring->execlist_lock);
 
        while (read_pointer < write_pointer) {
                read_pointer++;
                status = I915_READ(RING_CONTEXT_STATUS_BUF(ring) +
-                               (read_pointer % 6) * 8);
+                               (read_pointer % GEN8_CSB_ENTRIES) * 8);
                status_id = I915_READ(RING_CONTEXT_STATUS_BUF(ring) +
-                               (read_pointer % 6) * 8 + 4);
+                               (read_pointer % GEN8_CSB_ENTRIES) * 8 + 4);
 
                if (status & GEN8_CTX_STATUS_IDLE_ACTIVE)
                        continue;
@@ -521,10 +521,12 @@ void intel_lrc_irq_handler(struct intel_engine_cs *ring)
        spin_unlock(&ring->execlist_lock);
 
        WARN(submit_contexts > 2, "More than two context complete events?\n");
-       ring->next_context_status_buffer = write_pointer % 6;
+       ring->next_context_status_buffer = write_pointer % GEN8_CSB_ENTRIES;
 
        I915_WRITE(RING_CONTEXT_STATUS_PTR(ring),
-                  _MASKED_FIELD(0x07 << 8, ((u32)ring->next_context_status_buffer & 0x07) << 8));
+                  _MASKED_FIELD(GEN8_CSB_PTR_MASK << 8,
+                                ((u32)ring->next_context_status_buffer &
+                                 GEN8_CSB_PTR_MASK) << 8));
 }
 
 static int execlists_context_queue(struct drm_i915_gem_request *request)
@@ -1422,6 +1424,7 @@ static int gen8_init_common_ring(struct intel_engine_cs *ring)
 {
        struct drm_device *dev = ring->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       u8 next_context_status_buffer_hw;
 
        I915_WRITE_IMR(ring, ~(ring->irq_enable_mask | ring->irq_keep_mask));
        I915_WRITE(RING_HWSTAM(ring->mmio_base), 0xffffffff);
@@ -1436,7 +1439,29 @@ static int gen8_init_common_ring(struct intel_engine_cs *ring)
                   _MASKED_BIT_DISABLE(GFX_REPLAY_MODE) |
                   _MASKED_BIT_ENABLE(GFX_RUN_LIST_ENABLE));
        POSTING_READ(RING_MODE_GEN7(ring));
-       ring->next_context_status_buffer = 0;
+
+       /*
+        * Instead of resetting the Context Status Buffer (CSB) read pointer to
+        * zero, we need to read the write pointer from hardware and use its
+        * value because "this register is power context save restored".
+        * Effectively, these states have been observed:
+        *
+        *      | Suspend-to-idle (freeze) | Suspend-to-RAM (mem) |
+        * BDW  | CSB regs not reset       | CSB regs reset       |
+        * CHT  | CSB regs not reset       | CSB regs not reset   |
+        */
+       next_context_status_buffer_hw = (I915_READ(RING_CONTEXT_STATUS_PTR(ring))
+                                                  & GEN8_CSB_PTR_MASK);
+
+       /*
+        * When the CSB registers are reset (also after power-up / gpu reset),
+        * CSB write pointer is set to all 1's, which is not valid, use '5' in
+        * this special case, so the first element read is CSB[0].
+        */
+       if (next_context_status_buffer_hw == GEN8_CSB_PTR_MASK)
+               next_context_status_buffer_hw = (GEN8_CSB_ENTRIES - 1);
+
+       ring->next_context_status_buffer = next_context_status_buffer_hw;
        DRM_DEBUG_DRIVER("Execlists enabled for %s\n", ring->name);
 
        memset(&ring->hangcheck, 0, sizeof(ring->hangcheck));
@@ -1634,6 +1659,7 @@ static int gen8_emit_flush_render(struct drm_i915_gem_request *request,
        if (flush_domains) {
                flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
                flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
+               flags |= PIPE_CONTROL_FLUSH_ENABLE;
        }
 
        if (invalidate_domains) {
index 64f89f9982a20f745cb41ef5950cd637437000ca..3c63bb32ad81c657e418b1b7143ed934d036c66f 100644 (file)
@@ -25,6 +25,8 @@
 #define _INTEL_LRC_H_
 
 #define GEN8_LR_CONTEXT_ALIGN 4096
+#define GEN8_CSB_ENTRIES 6
+#define GEN8_CSB_PTR_MASK 0x07
 
 /* Execlists regs */
 #define RING_ELSP(ring)                        ((ring)->mmio_base+0x230)
index 6e6b8db996ef2450c615a71ef10b7ffcbbc62479..61b451fbd09e6ec9de8a42b20a1bb11b6438496f 100644 (file)
@@ -347,6 +347,7 @@ gen7_render_ring_flush(struct drm_i915_gem_request *req,
        if (flush_domains) {
                flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
                flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
+               flags |= PIPE_CONTROL_FLUSH_ENABLE;
        }
        if (invalidate_domains) {
                flags |= PIPE_CONTROL_TLB_INVALIDATE;
@@ -418,6 +419,7 @@ gen8_render_ring_flush(struct drm_i915_gem_request *req,
        if (flush_domains) {
                flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
                flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
+               flags |= PIPE_CONTROL_FLUSH_ENABLE;
        }
        if (invalidate_domains) {
                flags |= PIPE_CONTROL_TLB_INVALIDATE;
index af7fdb3bd663aef062a5cd41a2cdacbb4492515d..7401cf90b0dbcd1eb335e0c6defc42d22c9bb631 100644 (file)
@@ -246,7 +246,8 @@ static void skl_power_well_post_enable(struct drm_i915_private *dev_priv,
        }
 
        if (power_well->data == SKL_DISP_PW_1) {
-               intel_prepare_ddi(dev);
+               if (!dev_priv->power_domains.initializing)
+                       intel_prepare_ddi(dev);
                gen8_irq_power_well_post_enable(dev_priv, 1 << PIPE_A);
        }
 }
index 87de15ea1f93fd72cc05ad358995b313d75a1b76..b35b5b2db4ec30adc822d372d6c5cf2cf74969d0 100644 (file)
@@ -186,17 +186,19 @@ static int mgag200fb_create(struct drm_fb_helper *helper,
 
        sysram = vmalloc(size);
        if (!sysram)
-               return -ENOMEM;
+               goto err_sysram;
 
        info = drm_fb_helper_alloc_fbi(helper);
-       if (IS_ERR(info))
-               return PTR_ERR(info);
+       if (IS_ERR(info)) {
+               ret = PTR_ERR(info);
+               goto err_alloc_fbi;
+       }
 
        info->par = mfbdev;
 
        ret = mgag200_framebuffer_init(dev, &mfbdev->mfb, &mode_cmd, gobj);
        if (ret)
-               return ret;
+               goto err_framebuffer_init;
 
        mfbdev->sysram = sysram;
        mfbdev->size = size;
@@ -225,7 +227,17 @@ static int mgag200fb_create(struct drm_fb_helper *helper,
 
        DRM_DEBUG_KMS("allocated %dx%d\n",
                      fb->width, fb->height);
+
        return 0;
+
+err_framebuffer_init:
+       drm_fb_helper_release_fbi(helper);
+err_alloc_fbi:
+       vfree(sysram);
+err_sysram:
+       drm_gem_object_unreference_unlocked(gobj);
+
+       return ret;
 }
 
 static int mga_fbdev_destroy(struct drm_device *dev,
@@ -276,23 +288,26 @@ int mgag200_fbdev_init(struct mga_device *mdev)
        ret = drm_fb_helper_init(mdev->dev, &mfbdev->helper,
                                 mdev->num_crtc, MGAG200FB_CONN_LIMIT);
        if (ret)
-               return ret;
+               goto err_fb_helper;
 
        ret = drm_fb_helper_single_add_all_connectors(&mfbdev->helper);
        if (ret)
-               goto fini;
+               goto err_fb_setup;
 
        /* disable all the possible outputs/crtcs before entering KMS mode */
        drm_helper_disable_unused_functions(mdev->dev);
 
        ret = drm_fb_helper_initial_config(&mfbdev->helper, bpp_sel);
        if (ret)
-               goto fini;
+               goto err_fb_setup;
 
        return 0;
 
-fini:
+err_fb_setup:
        drm_fb_helper_fini(&mfbdev->helper);
+err_fb_helper:
+       mdev->mfbdev = NULL;
+
        return ret;
 }
 
index de06388069e7cf81af76dee743c888e7f1eac4e1..b1a0f565617510d5797349004f1ee3dd63063042 100644 (file)
@@ -220,7 +220,7 @@ int mgag200_driver_load(struct drm_device *dev, unsigned long flags)
        }
        r = mgag200_mm_init(mdev);
        if (r)
-               goto out;
+               goto err_mm;
 
        drm_mode_config_init(dev);
        dev->mode_config.funcs = (void *)&mga_mode_funcs;
@@ -233,7 +233,7 @@ int mgag200_driver_load(struct drm_device *dev, unsigned long flags)
        r = mgag200_modeset_init(mdev);
        if (r) {
                dev_err(&dev->pdev->dev, "Fatal error during modeset init: %d\n", r);
-               goto out;
+               goto err_modeset;
        }
 
        /* Make small buffers to store a hardware cursor (double buffered icon updates) */
@@ -241,20 +241,24 @@ int mgag200_driver_load(struct drm_device *dev, unsigned long flags)
                                          &mdev->cursor.pixels_1);
        mgag200_bo_create(dev, roundup(48*64, PAGE_SIZE), 0, 0,
                                          &mdev->cursor.pixels_2);
-       if (!mdev->cursor.pixels_2 || !mdev->cursor.pixels_1)
-               goto cursor_nospace;
-       mdev->cursor.pixels_current = mdev->cursor.pixels_1;
-       mdev->cursor.pixels_prev = mdev->cursor.pixels_2;
-       goto cursor_done;
- cursor_nospace:
-       mdev->cursor.pixels_1 = NULL;
-       mdev->cursor.pixels_2 = NULL;
-       dev_warn(&dev->pdev->dev, "Could not allocate space for cursors. Not doing hardware cursors.\n");
- cursor_done:
-
-out:
-       if (r)
-               mgag200_driver_unload(dev);
+       if (!mdev->cursor.pixels_2 || !mdev->cursor.pixels_1) {
+               mdev->cursor.pixels_1 = NULL;
+               mdev->cursor.pixels_2 = NULL;
+               dev_warn(&dev->pdev->dev,
+                       "Could not allocate space for cursors. Not doing hardware cursors.\n");
+       } else {
+               mdev->cursor.pixels_current = mdev->cursor.pixels_1;
+               mdev->cursor.pixels_prev = mdev->cursor.pixels_2;
+       }
+
+       return 0;
+
+err_modeset:
+       drm_mode_config_cleanup(dev);
+       mgag200_mm_fini(mdev);
+err_mm:
+       dev->dev_private = NULL;
+
        return r;
 }
 
index b1f73bee13682a29e1bc68a84f991e55fa170723..b0d4b53b97f4c2f045e37c17324b58b5984042f0 100644 (file)
@@ -178,7 +178,6 @@ static int mdp5_hw_irqdomain_map(struct irq_domain *d,
 
        irq_set_chip_and_handler(irq, &mdp5_hw_irq_chip, handle_level_irq);
        irq_set_chip_data(irq, mdp5_kms);
-       set_irq_flags(irq, IRQF_VALID);
 
        return 0;
 }
index cc6c228e11c83566d1ac1a2c59fcefa959345463..e905c00acf1a37baef92d66a6f38b888372b9834 100644 (file)
@@ -469,9 +469,13 @@ nouveau_display_create(struct drm_device *dev)
        if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA) {
                dev->mode_config.max_width = 4096;
                dev->mode_config.max_height = 4096;
-       } else {
+       } else
+       if (drm->device.info.family < NV_DEVICE_INFO_V0_FERMI) {
                dev->mode_config.max_width = 8192;
                dev->mode_config.max_height = 8192;
+       } else {
+               dev->mode_config.max_width = 16384;
+               dev->mode_config.max_height = 16384;
        }
 
        dev->mode_config.preferred_depth = 24;
index 2791701685dc82bf4e2655ce3ea8ea6c3b278e49..59f27e774acb5e9c98c9854bd72195efdbec3a48 100644 (file)
@@ -178,8 +178,30 @@ nouveau_fbcon_sync(struct fb_info *info)
        return 0;
 }
 
+static int
+nouveau_fbcon_open(struct fb_info *info, int user)
+{
+       struct nouveau_fbdev *fbcon = info->par;
+       struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
+       int ret = pm_runtime_get_sync(drm->dev->dev);
+       if (ret < 0 && ret != -EACCES)
+               return ret;
+       return 0;
+}
+
+static int
+nouveau_fbcon_release(struct fb_info *info, int user)
+{
+       struct nouveau_fbdev *fbcon = info->par;
+       struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
+       pm_runtime_put(drm->dev->dev);
+       return 0;
+}
+
 static struct fb_ops nouveau_fbcon_ops = {
        .owner = THIS_MODULE,
+       .fb_open = nouveau_fbcon_open,
+       .fb_release = nouveau_fbcon_release,
        .fb_check_var = drm_fb_helper_check_var,
        .fb_set_par = drm_fb_helper_set_par,
        .fb_fillrect = nouveau_fbcon_fillrect,
@@ -195,6 +217,8 @@ static struct fb_ops nouveau_fbcon_ops = {
 
 static struct fb_ops nouveau_fbcon_sw_ops = {
        .owner = THIS_MODULE,
+       .fb_open = nouveau_fbcon_open,
+       .fb_release = nouveau_fbcon_release,
        .fb_check_var = drm_fb_helper_check_var,
        .fb_set_par = drm_fb_helper_set_par,
        .fb_fillrect = drm_fb_helper_cfb_fillrect,
index 2c9981512d27b7702f6f196f64b54276acd8b86e..41be584147b936a921d0c6bdd4e5fe0b4251c70c 100644 (file)
@@ -227,11 +227,12 @@ nouveau_gem_info(struct drm_file *file_priv, struct drm_gem_object *gem,
        struct nouveau_bo *nvbo = nouveau_gem_object(gem);
        struct nvkm_vma *vma;
 
-       if (nvbo->bo.mem.mem_type == TTM_PL_TT)
+       if (is_power_of_2(nvbo->valid_domains))
+               rep->domain = nvbo->valid_domains;
+       else if (nvbo->bo.mem.mem_type == TTM_PL_TT)
                rep->domain = NOUVEAU_GEM_DOMAIN_GART;
        else
                rep->domain = NOUVEAU_GEM_DOMAIN_VRAM;
-
        rep->offset = nvbo->bo.offset;
        if (cli->vm) {
                vma = nouveau_bo_vma_find(nvbo, cli->vm);
index 65af31441e9c29496647084d927c11f393974653..a7d69ce7abc1ad33b5fd283a5f4b5321feb89f18 100644 (file)
@@ -267,6 +267,12 @@ init_i2c(struct nvbios_init *init, int index)
                index = NVKM_I2C_BUS_PRI;
                if (init->outp && init->outp->i2c_upper_default)
                        index = NVKM_I2C_BUS_SEC;
+       } else
+       if (index == 0x80) {
+               index = NVKM_I2C_BUS_PRI;
+       } else
+       if (index == 0x81) {
+               index = NVKM_I2C_BUS_SEC;
        }
 
        bus = nvkm_i2c_bus_find(i2c, index);
index e0ec2a6b7b795c964e119eae2dfed644d24e4ae2..212800ecdce99e4eb1a3a23ebdab9c207cd860da 100644 (file)
@@ -8,7 +8,10 @@ struct nvbios_source {
        void *(*init)(struct nvkm_bios *, const char *);
        void  (*fini)(void *);
        u32   (*read)(void *, u32 offset, u32 length, struct nvkm_bios *);
+       u32   (*size)(void *);
        bool rw;
+       bool ignore_checksum;
+       bool no_pcir;
 };
 
 int nvbios_extend(struct nvkm_bios *, u32 length);
index 792f017525f689bb1d38b86c0bf2e746f9495c8d..b2557e87afdd6d0e95910b3b4b91e37ce9a3e269 100644 (file)
@@ -45,7 +45,7 @@ shadow_fetch(struct nvkm_bios *bios, struct shadow *mthd, u32 upto)
                u32 read = mthd->func->read(data, start, limit - start, bios);
                bios->size = start + read;
        }
-       return bios->size >= limit;
+       return bios->size >= upto;
 }
 
 static int
@@ -55,14 +55,22 @@ shadow_image(struct nvkm_bios *bios, int idx, u32 offset, struct shadow *mthd)
        struct nvbios_image image;
        int score = 1;
 
-       if (!shadow_fetch(bios, mthd, offset + 0x1000)) {
-               nvkm_debug(subdev, "%08x: header fetch failed\n", offset);
-               return 0;
-       }
+       if (mthd->func->no_pcir) {
+               image.base = 0;
+               image.type = 0;
+               image.size = mthd->func->size(mthd->data);
+               image.last = 1;
+       } else {
+               if (!shadow_fetch(bios, mthd, offset + 0x1000)) {
+                       nvkm_debug(subdev, "%08x: header fetch failed\n",
+                                  offset);
+                       return 0;
+               }
 
-       if (!nvbios_image(bios, idx, &image)) {
-               nvkm_debug(subdev, "image %d invalid\n", idx);
-               return 0;
+               if (!nvbios_image(bios, idx, &image)) {
+                       nvkm_debug(subdev, "image %d invalid\n", idx);
+                       return 0;
+               }
        }
        nvkm_debug(subdev, "%08x: type %02x, %d bytes\n",
                   image.base, image.type, image.size);
@@ -74,7 +82,8 @@ shadow_image(struct nvkm_bios *bios, int idx, u32 offset, struct shadow *mthd)
 
        switch (image.type) {
        case 0x00:
-               if (nvbios_checksum(&bios->data[image.base], image.size)) {
+               if (!mthd->func->ignore_checksum &&
+                   nvbios_checksum(&bios->data[image.base], image.size)) {
                        nvkm_debug(subdev, "%08x: checksum failed\n",
                                   image.base);
                        if (mthd->func->rw)
index bd60d7dd09f51a45b70f120597ca38adaf8c102b..4bf486b57101367708bba2b6fe4bdd1d985f1d19 100644 (file)
@@ -21,6 +21,7 @@
  *
  */
 #include "priv.h"
+
 #include <core/pci.h>
 
 #if defined(__powerpc__)
@@ -33,17 +34,26 @@ static u32
 of_read(void *data, u32 offset, u32 length, struct nvkm_bios *bios)
 {
        struct priv *priv = data;
-       if (offset + length <= priv->size) {
+       if (offset < priv->size) {
+               length = min_t(u32, length, priv->size - offset);
                memcpy_fromio(bios->data + offset, priv->data + offset, length);
                return length;
        }
        return 0;
 }
 
+static u32
+of_size(void *data)
+{
+       struct priv *priv = data;
+       return priv->size;
+}
+
 static void *
 of_init(struct nvkm_bios *bios, const char *name)
 {
-       struct pci_dev *pdev = bios->subdev.device->func->pci(bios->subdev.device)->pdev;
+       struct nvkm_device *device = bios->subdev.device;
+       struct pci_dev *pdev = device->func->pci(device)->pdev;
        struct device_node *dn;
        struct priv *priv;
        if (!(dn = pci_device_to_OF_node(pdev)))
@@ -62,7 +72,10 @@ nvbios_of = {
        .init = of_init,
        .fini = (void(*)(void *))kfree,
        .read = of_read,
+       .size = of_size,
        .rw = false,
+       .ignore_checksum = true,
+       .no_pcir = true,
 };
 #else
 const struct nvbios_source
index 814cb51cc87372bd4c18225b16b1401d10285b60..385a90f91ed6a14e394ba1e8b4743d9c38c06412 100644 (file)
@@ -35,6 +35,8 @@ static const struct nvkm_device_agp_quirk
 nvkm_device_agp_quirks[] = {
        /* VIA Apollo PRO133x / GeForce FX 5600 Ultra - fdo#20341 */
        { PCI_VENDOR_ID_VIA, 0x0691, PCI_VENDOR_ID_NVIDIA, 0x0311, 2 },
+       /* SiS 761 does not support AGP cards, use PCI mode */
+       { PCI_VENDOR_ID_SI, 0x0761, PCI_ANY_ID, PCI_ANY_ID, 0 },
        {},
 };
 
@@ -137,8 +139,10 @@ nvkm_agp_ctor(struct nvkm_pci *pci)
        while (quirk->hostbridge_vendor) {
                if (info.device->vendor == quirk->hostbridge_vendor &&
                    info.device->device == quirk->hostbridge_device &&
-                   pci->pdev->vendor == quirk->chip_vendor &&
-                   pci->pdev->device == quirk->chip_device) {
+                   (quirk->chip_vendor == (u16)PCI_ANY_ID ||
+                   pci->pdev->vendor == quirk->chip_vendor) &&
+                   (quirk->chip_device == (u16)PCI_ANY_ID ||
+                   pci->pdev->device == quirk->chip_device)) {
                        nvkm_info(subdev, "forcing default agp mode to %dX, "
                                          "use NvAGP=<mode> to override\n",
                                  quirk->mode);
index 7c6225c84ba6745919377fa9bfbd3506a7d8f7e5..183aea1abebc4afe5ad28f4694bc92ccc788ee8d 100644 (file)
@@ -242,6 +242,10 @@ static int qxl_crtc_page_flip(struct drm_crtc *crtc,
        bo->is_primary = true;
 
        ret = qxl_bo_reserve(bo, false);
+       if (ret)
+               return ret;
+       ret = qxl_bo_pin(bo, bo->type, NULL);
+       qxl_bo_unreserve(bo);
        if (ret)
                return ret;
 
@@ -257,7 +261,11 @@ static int qxl_crtc_page_flip(struct drm_crtc *crtc,
        }
        drm_vblank_put(dev, qcrtc->index);
 
-       qxl_bo_unreserve(bo);
+       ret = qxl_bo_reserve(bo, false);
+       if (!ret) {
+               qxl_bo_unpin(bo);
+               qxl_bo_unreserve(bo);
+       }
 
        return 0;
 }
@@ -618,7 +626,7 @@ static int qxl_crtc_mode_set(struct drm_crtc *crtc,
                  adjusted_mode->hdisplay,
                  adjusted_mode->vdisplay);
 
-       if (qcrtc->index == 0)
+       if (bo->is_primary == false)
                recreate_primary = true;
 
        if (bo->surf.stride * bo->surf.height > qdev->vram_size) {
@@ -886,13 +894,15 @@ static enum drm_connector_status qxl_conn_detect(
                drm_connector_to_qxl_output(connector);
        struct drm_device *ddev = connector->dev;
        struct qxl_device *qdev = ddev->dev_private;
-       int connected;
+       bool connected = false;
 
        /* The first monitor is always connected */
-       connected = (output->index == 0) ||
-                   (qdev->client_monitors_config &&
-                    qdev->client_monitors_config->count > output->index &&
-                    qxl_head_enabled(&qdev->client_monitors_config->heads[output->index]));
+       if (!qdev->client_monitors_config) {
+               if (output->index == 0)
+                       connected = true;
+       } else
+               connected = qdev->client_monitors_config->count > output->index &&
+                    qxl_head_enabled(&qdev->client_monitors_config->heads[output->index]);
 
        DRM_DEBUG("#%d connected: %d\n", output->index, connected);
        if (!connected)
index 41c422fee31a02dbc932964bc4686921e533fdd3..c4a552637c9353d70cab76083b7d7786dc436d29 100644 (file)
@@ -144,14 +144,17 @@ static void qxl_dirty_update(struct qxl_fbdev *qfbdev,
 
        spin_lock_irqsave(&qfbdev->dirty.lock, flags);
 
-       if (qfbdev->dirty.y1 < y)
-               y = qfbdev->dirty.y1;
-       if (qfbdev->dirty.y2 > y2)
-               y2 = qfbdev->dirty.y2;
-       if (qfbdev->dirty.x1 < x)
-               x = qfbdev->dirty.x1;
-       if (qfbdev->dirty.x2 > x2)
-               x2 = qfbdev->dirty.x2;
+       if ((qfbdev->dirty.y2 - qfbdev->dirty.y1) &&
+           (qfbdev->dirty.x2 - qfbdev->dirty.x1)) {
+               if (qfbdev->dirty.y1 < y)
+                       y = qfbdev->dirty.y1;
+               if (qfbdev->dirty.y2 > y2)
+                       y2 = qfbdev->dirty.y2;
+               if (qfbdev->dirty.x1 < x)
+                       x = qfbdev->dirty.x1;
+               if (qfbdev->dirty.x2 > x2)
+                       x2 = qfbdev->dirty.x2;
+       }
 
        qfbdev->dirty.x1 = x;
        qfbdev->dirty.x2 = x2;
index b66ec331c17cd51f1b81022ebd29d18944258b43..4efa8e261baf59546ca24eb39920bc4159358ab7 100644 (file)
@@ -307,7 +307,7 @@ int qxl_alloc_surface_release_reserved(struct qxl_device *qdev,
                idr_ret = qxl_release_alloc(qdev, QXL_RELEASE_SURFACE_CMD, release);
                if (idr_ret < 0)
                        return idr_ret;
-               bo = qxl_bo_ref(to_qxl_bo(entry->tv.bo));
+               bo = to_qxl_bo(entry->tv.bo);
 
                (*release)->release_offset = create_rel->release_offset + 64;
 
@@ -316,8 +316,6 @@ int qxl_alloc_surface_release_reserved(struct qxl_device *qdev,
                info = qxl_release_map(qdev, *release);
                info->id = idr_ret;
                qxl_release_unmap(qdev, *release, info);
-
-               qxl_bo_unref(&bo);
                return 0;
        }
 
index c3872598b85a3856787b1bf0b7113633a468e020..bb292143997ee8ccce3e6e6898edba2a5eeb12b6 100644 (file)
@@ -237,6 +237,7 @@ void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder,
        backlight_update_status(bd);
 
        DRM_INFO("radeon atom DIG backlight initialized\n");
+       rdev->mode_info.bl_encoder = radeon_encoder;
 
        return;
 
@@ -1624,8 +1625,14 @@ radeon_atom_encoder_dpms_avivo(struct drm_encoder *encoder, int mode)
                } else
                        atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
                if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
-                       args.ucAction = ATOM_LCD_BLON;
-                       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+                       if (rdev->mode_info.bl_encoder) {
+                               struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+
+                               atombios_set_backlight_level(radeon_encoder, dig->backlight_level);
+                       } else {
+                               args.ucAction = ATOM_LCD_BLON;
+                               atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+                       }
                }
                break;
        case DRM_MODE_DPMS_STANDBY:
@@ -1705,9 +1712,13 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
                        if (ASIC_IS_DCE4(rdev))
                                atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0);
                }
-               if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
-                       atombios_dig_transmitter_setup(encoder,
-                                                      ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
+               if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+                       if (rdev->mode_info.bl_encoder)
+                               atombios_set_backlight_level(radeon_encoder, dig->backlight_level);
+                       else
+                               atombios_dig_transmitter_setup(encoder,
+                                                              ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
+               }
                if (ext_encoder)
                        atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
                break;
index f03b7eb152336d1f799ab33d1d195c1fba40b360..b6cbd816537e7e69bc920482961cdb47b6dfd68d 100644 (file)
@@ -1658,6 +1658,7 @@ struct radeon_pm {
        u8                      fan_max_rpm;
        /* dpm */
        bool                    dpm_enabled;
+       bool                    sysfs_initialized;
        struct radeon_dpm       dpm;
 };
 
index d8319dae8358846cfc4b8121e7786dbd8c6d17fa..f3f562f6d848d17d3cc4e48d2701f5de5a14a46a 100644 (file)
@@ -1573,10 +1573,12 @@ int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon)
 
        drm_kms_helper_poll_disable(dev);
 
+       drm_modeset_lock_all(dev);
        /* turn off display hw */
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
                drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
        }
+       drm_modeset_unlock_all(dev);
 
        /* unpin the front buffers and cursors */
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
@@ -1734,9 +1736,11 @@ int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon)
        if (fbcon) {
                drm_helper_resume_force_mode(dev);
                /* turn on display hw */
+               drm_modeset_lock_all(dev);
                list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
                        drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
                }
+               drm_modeset_unlock_all(dev);
        }
 
        drm_kms_helper_poll_enable(dev);
index d2e9e9efc159c053b954aed21840ebe7d91f2739..6743174acdbcd22b5d357d0275f1e564dc653d81 100644 (file)
@@ -1633,18 +1633,8 @@ int radeon_modeset_init(struct radeon_device *rdev)
        radeon_fbdev_init(rdev);
        drm_kms_helper_poll_init(rdev->ddev);
 
-       if (rdev->pm.dpm_enabled) {
-               /* do dpm late init */
-               ret = radeon_pm_late_init(rdev);
-               if (ret) {
-                       rdev->pm.dpm_enabled = false;
-                       DRM_ERROR("radeon_pm_late_init failed, disabling dpm\n");
-               }
-               /* set the dpm state for PX since there won't be
-                * a modeset to call this.
-                */
-               radeon_pm_compute_clocks(rdev);
-       }
+       /* do pm late init */
+       ret = radeon_pm_late_init(rdev);
 
        return 0;
 }
index 5e09c061847f50c688650d12625a462e8c4737cd..744f5c49c66463c56187dbc2130a77539a264130 100644 (file)
@@ -265,7 +265,6 @@ static struct drm_connector *radeon_dp_add_mst_connector(struct drm_dp_mst_topol
 {
        struct radeon_connector *master = container_of(mgr, struct radeon_connector, mst_mgr);
        struct drm_device *dev = master->base.dev;
-       struct radeon_device *rdev = dev->dev_private;
        struct radeon_connector *radeon_connector;
        struct drm_connector *connector;
 
@@ -284,14 +283,22 @@ static struct drm_connector *radeon_dp_add_mst_connector(struct drm_dp_mst_topol
        radeon_connector->mst_encoder = radeon_dp_create_fake_mst_encoder(master);
 
        drm_object_attach_property(&connector->base, dev->mode_config.path_property, 0);
+       drm_object_attach_property(&connector->base, dev->mode_config.tile_property, 0);
        drm_mode_connector_set_path_property(connector, pathprop);
 
+       return connector;
+}
+
+static void radeon_dp_register_mst_connector(struct drm_connector *connector)
+{
+       struct drm_device *dev = connector->dev;
+       struct radeon_device *rdev = dev->dev_private;
+
        drm_modeset_lock_all(dev);
        radeon_fb_add_connector(rdev, connector);
        drm_modeset_unlock_all(dev);
 
        drm_connector_register(connector);
-       return connector;
 }
 
 static void radeon_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
@@ -324,6 +331,7 @@ static void radeon_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr)
 
 struct drm_dp_mst_topology_cbs mst_cbs = {
        .add_connector = radeon_dp_add_mst_connector,
+       .register_connector = radeon_dp_register_mst_connector,
        .destroy_connector = radeon_dp_destroy_mst_connector,
        .hotplug = radeon_dp_mst_hotplug,
 };
index ef99917f000d96a7dcf3fc88f089bdf08e0afc28..c6ee80216cf4a71f510bf239fc4fdf6f67235f48 100644 (file)
@@ -194,7 +194,6 @@ static void radeon_encoder_add_backlight(struct radeon_encoder *radeon_encoder,
                        radeon_atom_backlight_init(radeon_encoder, connector);
                else
                        radeon_legacy_backlight_init(radeon_encoder, connector);
-               rdev->mode_info.bl_encoder = radeon_encoder;
        }
 }
 
index 7214858ffceaa8c20409206533dcc332fd663705..26da2f4d7b4f56fca3948af07bca9c061bb5ddaf 100644 (file)
@@ -48,40 +48,10 @@ struct radeon_fbdev {
        struct radeon_device *rdev;
 };
 
-/**
- * radeon_fb_helper_set_par - Hide cursor on CRTCs used by fbdev.
- *
- * @info: fbdev info
- *
- * This function hides the cursor on all CRTCs used by fbdev.
- */
-static int radeon_fb_helper_set_par(struct fb_info *info)
-{
-       int ret;
-
-       ret = drm_fb_helper_set_par(info);
-
-       /* XXX: with universal plane support fbdev will automatically disable
-        * all non-primary planes (including the cursor)
-        */
-       if (ret == 0) {
-               struct drm_fb_helper *fb_helper = info->par;
-               int i;
-
-               for (i = 0; i < fb_helper->crtc_count; i++) {
-                       struct drm_crtc *crtc = fb_helper->crtc_info[i].mode_set.crtc;
-
-                       radeon_crtc_cursor_set2(crtc, NULL, 0, 0, 0, 0, 0);
-               }
-       }
-
-       return ret;
-}
-
 static struct fb_ops radeonfb_ops = {
        .owner = THIS_MODULE,
        .fb_check_var = drm_fb_helper_check_var,
-       .fb_set_par = radeon_fb_helper_set_par,
+       .fb_set_par = drm_fb_helper_set_par,
        .fb_fillrect = drm_fb_helper_cfb_fillrect,
        .fb_copyarea = drm_fb_helper_cfb_copyarea,
        .fb_imageblit = drm_fb_helper_cfb_imageblit,
@@ -427,3 +397,19 @@ void radeon_fb_remove_connector(struct radeon_device *rdev, struct drm_connector
 {
        drm_fb_helper_remove_one_connector(&rdev->mode_info.rfbdev->helper, connector);
 }
+
+void radeon_fbdev_restore_mode(struct radeon_device *rdev)
+{
+       struct radeon_fbdev *rfbdev = rdev->mode_info.rfbdev;
+       struct drm_fb_helper *fb_helper;
+       int ret;
+
+       if (!rfbdev)
+               return;
+
+       fb_helper = &rfbdev->helper;
+
+       ret = drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper);
+       if (ret)
+               DRM_DEBUG("failed to restore crtc mode\n");
+}
index 4a119c255ba9709692b234c51a928d826cc22ec2..0e932bf932c11f95a59a57bb3c9126e01a6baf3d 100644 (file)
@@ -598,7 +598,7 @@ static int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file
  * Outdated mess for old drm with Xorg being in charge (void function now).
  */
 /**
- * radeon_driver_firstopen_kms - drm callback for last close
+ * radeon_driver_lastclose_kms - drm callback for last close
  *
  * @dev: drm dev pointer
  *
@@ -606,6 +606,9 @@ static int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file
  */
 void radeon_driver_lastclose_kms(struct drm_device *dev)
 {
+       struct radeon_device *rdev = dev->dev_private;
+
+       radeon_fbdev_restore_mode(rdev);
        vga_switcheroo_process_delayed_switch();
 }
 
index 45715307db7177a9af7393a697d255c8ed277344..30de43366eae806d0afd45192ce9da032c08490c 100644 (file)
@@ -441,6 +441,7 @@ void radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
        backlight_update_status(bd);
 
        DRM_INFO("radeon legacy LVDS backlight initialized\n");
+       rdev->mode_info.bl_encoder = radeon_encoder;
 
        return;
 
index aecc3e3dec0ca093441e3871df414627b51e92ec..457b026a0972782fc6d777b1069b683c1fda037f 100644 (file)
@@ -980,6 +980,7 @@ int radeon_fbdev_init(struct radeon_device *rdev);
 void radeon_fbdev_fini(struct radeon_device *rdev);
 void radeon_fbdev_set_suspend(struct radeon_device *rdev, int state);
 bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj);
+void radeon_fbdev_restore_mode(struct radeon_device *rdev);
 
 void radeon_fb_output_poll_changed(struct radeon_device *rdev);
 
index 05751f3f84449d40457b3f989f0d7ab874935bbf..5feee3b4c55741011ae3501f501f72df0e1311ac 100644 (file)
@@ -717,10 +717,14 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
        struct radeon_device *rdev = dev_get_drvdata(dev);
        umode_t effective_mode = attr->mode;
 
-       /* Skip limit attributes if DPM is not enabled */
+       /* Skip attributes if DPM is not enabled */
        if (rdev->pm.pm_method != PM_METHOD_DPM &&
            (attr == &sensor_dev_attr_temp1_crit.dev_attr.attr ||
-            attr == &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr))
+            attr == &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr ||
+            attr == &sensor_dev_attr_pwm1.dev_attr.attr ||
+            attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr ||
+            attr == &sensor_dev_attr_pwm1_max.dev_attr.attr ||
+            attr == &sensor_dev_attr_pwm1_min.dev_attr.attr))
                return 0;
 
        /* Skip fan attributes if fan is not present */
@@ -1326,14 +1330,6 @@ static int radeon_pm_init_old(struct radeon_device *rdev)
        INIT_DELAYED_WORK(&rdev->pm.dynpm_idle_work, radeon_dynpm_idle_work_handler);
 
        if (rdev->pm.num_power_states > 1) {
-               /* where's the best place to put these? */
-               ret = device_create_file(rdev->dev, &dev_attr_power_profile);
-               if (ret)
-                       DRM_ERROR("failed to create device file for power profile\n");
-               ret = device_create_file(rdev->dev, &dev_attr_power_method);
-               if (ret)
-                       DRM_ERROR("failed to create device file for power method\n");
-
                if (radeon_debugfs_pm_init(rdev)) {
                        DRM_ERROR("Failed to register debugfs file for PM!\n");
                }
@@ -1391,20 +1387,6 @@ static int radeon_pm_init_dpm(struct radeon_device *rdev)
                goto dpm_failed;
        rdev->pm.dpm_enabled = true;
 
-       ret = device_create_file(rdev->dev, &dev_attr_power_dpm_state);
-       if (ret)
-               DRM_ERROR("failed to create device file for dpm state\n");
-       ret = device_create_file(rdev->dev, &dev_attr_power_dpm_force_performance_level);
-       if (ret)
-               DRM_ERROR("failed to create device file for dpm state\n");
-       /* XXX: these are noops for dpm but are here for backwards compat */
-       ret = device_create_file(rdev->dev, &dev_attr_power_profile);
-       if (ret)
-               DRM_ERROR("failed to create device file for power profile\n");
-       ret = device_create_file(rdev->dev, &dev_attr_power_method);
-       if (ret)
-               DRM_ERROR("failed to create device file for power method\n");
-
        if (radeon_debugfs_pm_init(rdev)) {
                DRM_ERROR("Failed to register debugfs file for dpm!\n");
        }
@@ -1545,9 +1527,51 @@ int radeon_pm_late_init(struct radeon_device *rdev)
        int ret = 0;
 
        if (rdev->pm.pm_method == PM_METHOD_DPM) {
-               mutex_lock(&rdev->pm.mutex);
-               ret = radeon_dpm_late_enable(rdev);
-               mutex_unlock(&rdev->pm.mutex);
+               if (rdev->pm.dpm_enabled) {
+                       if (!rdev->pm.sysfs_initialized) {
+                               ret = device_create_file(rdev->dev, &dev_attr_power_dpm_state);
+                               if (ret)
+                                       DRM_ERROR("failed to create device file for dpm state\n");
+                               ret = device_create_file(rdev->dev, &dev_attr_power_dpm_force_performance_level);
+                               if (ret)
+                                       DRM_ERROR("failed to create device file for dpm state\n");
+                               /* XXX: these are noops for dpm but are here for backwards compat */
+                               ret = device_create_file(rdev->dev, &dev_attr_power_profile);
+                               if (ret)
+                                       DRM_ERROR("failed to create device file for power profile\n");
+                               ret = device_create_file(rdev->dev, &dev_attr_power_method);
+                               if (ret)
+                                       DRM_ERROR("failed to create device file for power method\n");
+                               if (!ret)
+                                       rdev->pm.sysfs_initialized = true;
+                       }
+
+                       mutex_lock(&rdev->pm.mutex);
+                       ret = radeon_dpm_late_enable(rdev);
+                       mutex_unlock(&rdev->pm.mutex);
+                       if (ret) {
+                               rdev->pm.dpm_enabled = false;
+                               DRM_ERROR("radeon_pm_late_init failed, disabling dpm\n");
+                       } else {
+                               /* set the dpm state for PX since there won't be
+                                * a modeset to call this.
+                                */
+                               radeon_pm_compute_clocks(rdev);
+                       }
+               }
+       } else {
+               if ((rdev->pm.num_power_states > 1) &&
+                   (!rdev->pm.sysfs_initialized)) {
+                       /* where's the best place to put these? */
+                       ret = device_create_file(rdev->dev, &dev_attr_power_profile);
+                       if (ret)
+                               DRM_ERROR("failed to create device file for power profile\n");
+                       ret = device_create_file(rdev->dev, &dev_attr_power_method);
+                       if (ret)
+                               DRM_ERROR("failed to create device file for power method\n");
+                       if (!ret)
+                               rdev->pm.sysfs_initialized = true;
+               }
        }
        return ret;
 }
index 787cd8fd897faf52e5874cb0183a07bc36594fdc..e72bf46042e0a42f469cbfd8ff285b1ae9abb155 100644 (file)
@@ -2927,6 +2927,8 @@ static struct si_dpm_quirk si_dpm_quirk_list[] = {
        { PCI_VENDOR_ID_ATI, 0x6810, 0x1462, 0x3036, 0, 120000 },
        { PCI_VENDOR_ID_ATI, 0x6811, 0x174b, 0xe271, 0, 120000 },
        { PCI_VENDOR_ID_ATI, 0x6810, 0x174b, 0xe271, 85000, 90000 },
+       { PCI_VENDOR_ID_ATI, 0x6811, 0x1762, 0x2015, 0, 120000 },
+       { PCI_VENDOR_ID_ATI, 0x6811, 0x1043, 0x2015, 0, 120000 },
        { 0, 0, 0, 0 },
 };
 
index 8d9b7de2561339b03e2b191e45454eadfd454668..745e996d2dbcde4ec9b563f73d5791cc3aa4dbef 100644 (file)
@@ -882,6 +882,8 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo,
                if (ret)
                        return ret;
                man = &bdev->man[mem_type];
+               if (!man->has_type || !man->use_type)
+                       continue;
 
                type_ok = ttm_bo_mt_compatible(man, mem_type, place,
                                                &cur_flags);
@@ -889,6 +891,7 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo,
                if (!type_ok)
                        continue;
 
+               type_found = true;
                cur_flags = ttm_bo_select_caching(man, bo->mem.placement,
                                                  cur_flags);
                /*
@@ -901,12 +904,10 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo,
                if (mem_type == TTM_PL_SYSTEM)
                        break;
 
-               if (man->has_type && man->use_type) {
-                       type_found = true;
-                       ret = (*man->func->get_node)(man, bo, place, mem);
-                       if (unlikely(ret))
-                               return ret;
-               }
+               ret = (*man->func->get_node)(man, bo, place, mem);
+               if (unlikely(ret))
+                       return ret;
+               
                if (mem->mm_node)
                        break;
        }
@@ -917,9 +918,6 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo,
                return 0;
        }
 
-       if (!type_found)
-               return -EINVAL;
-
        for (i = 0; i < placement->num_busy_placement; ++i) {
                const struct ttm_place *place = &placement->busy_placement[i];
 
@@ -927,11 +925,12 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo,
                if (ret)
                        return ret;
                man = &bdev->man[mem_type];
-               if (!man->has_type)
+               if (!man->has_type || !man->use_type)
                        continue;
                if (!ttm_bo_mt_compatible(man, mem_type, place, &cur_flags))
                        continue;
 
+               type_found = true;
                cur_flags = ttm_bo_select_caching(man, bo->mem.placement,
                                                  cur_flags);
                /*
@@ -957,8 +956,13 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo,
                if (ret == -ERESTARTSYS)
                        has_erestartsys = true;
        }
-       ret = (has_erestartsys) ? -ERESTARTSYS : -ENOMEM;
-       return ret;
+
+       if (!type_found) {
+               printk(KERN_ERR TTM_PFX "No compatible memory type found.\n");
+               return -EINVAL;
+       }
+
+       return (has_erestartsys) ? -ERESTARTSYS : -ENOMEM;
 }
 EXPORT_SYMBOL(ttm_bo_mem_space);
 
index db8b49101a8b620f742af39c24154933bf3d1ff7..512263919282328cb55505abf2542987c5f9f9cd 100644 (file)
@@ -34,8 +34,8 @@ virtio_gpu_debugfs_irq_info(struct seq_file *m, void *data)
        struct drm_info_node *node = (struct drm_info_node *) m->private;
        struct virtio_gpu_device *vgdev = node->minor->dev->dev_private;
 
-       seq_printf(m, "fence %ld %lld\n",
-                  atomic64_read(&vgdev->fence_drv.last_seq),
+       seq_printf(m, "fence %llu %lld\n",
+                  (u64)atomic64_read(&vgdev->fence_drv.last_seq),
                   vgdev->fence_drv.sync_seq);
        return 0;
 }
index 1da632631dac808e8273fe3aa77a5426950f9156..67097c9ce9c143e2d6ac3534c4379d0f024d4887 100644 (file)
@@ -61,7 +61,7 @@ static void virtio_timeline_value_str(struct fence *f, char *str, int size)
 {
        struct virtio_gpu_fence *fence = to_virtio_fence(f);
 
-       snprintf(str, size, "%lu", atomic64_read(&fence->drv->last_seq));
+       snprintf(str, size, "%llu", (u64)atomic64_read(&fence->drv->last_seq));
 }
 
 static const struct fence_ops virtio_fence_ops = {
index 67720f70fe29bb10a36ea8ce67ab278cd8e20c33..b49445df8a7e6c672f5ec7e590ded51647288b62 100644 (file)
@@ -1,6 +1,6 @@
 config DRM_VMWGFX
        tristate "DRM driver for VMware Virtual GPU"
-       depends on DRM && PCI
+       depends on DRM && PCI && X86
        select FB_DEFERRED_IO
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
index 5ae8f921da2a478bef55b617c3a28f66ed1e2773..6377e8151000f5401309133b635150acf128c2ad 100644 (file)
@@ -415,16 +415,16 @@ static void vmw_cmdbuf_ctx_process(struct vmw_cmdbuf_man *man,
  *
  * Calls vmw_cmdbuf_ctx_process() on all contexts. If any context has
  * command buffers left that are not submitted to hardware, Make sure
- * IRQ handling is turned on. Otherwise, make sure it's turned off. This
- * function may return -EAGAIN to indicate it should be rerun due to
- * possibly missed IRQs if IRQs has just been turned on.
+ * IRQ handling is turned on. Otherwise, make sure it's turned off.
  */
-static int vmw_cmdbuf_man_process(struct vmw_cmdbuf_man *man)
+static void vmw_cmdbuf_man_process(struct vmw_cmdbuf_man *man)
 {
-       int notempty = 0;
+       int notempty;
        struct vmw_cmdbuf_context *ctx;
        int i;
 
+retry:
+       notempty = 0;
        for_each_cmdbuf_ctx(man, i, ctx)
                vmw_cmdbuf_ctx_process(man, ctx, &notempty);
 
@@ -440,10 +440,8 @@ static int vmw_cmdbuf_man_process(struct vmw_cmdbuf_man *man)
                man->irq_on = true;
 
                /* Rerun in case we just missed an irq. */
-               return -EAGAIN;
+               goto retry;
        }
-
-       return 0;
 }
 
 /**
@@ -468,8 +466,7 @@ static void vmw_cmdbuf_ctx_add(struct vmw_cmdbuf_man *man,
        header->cb_context = cb_context;
        list_add_tail(&header->list, &man->ctx[cb_context].submitted);
 
-       if (vmw_cmdbuf_man_process(man) == -EAGAIN)
-               vmw_cmdbuf_man_process(man);
+       vmw_cmdbuf_man_process(man);
 }
 
 /**
@@ -488,8 +485,7 @@ static void vmw_cmdbuf_man_tasklet(unsigned long data)
        struct vmw_cmdbuf_man *man = (struct vmw_cmdbuf_man *) data;
 
        spin_lock(&man->lock);
-       if (vmw_cmdbuf_man_process(man) == -EAGAIN)
-               (void) vmw_cmdbuf_man_process(man);
+       vmw_cmdbuf_man_process(man);
        spin_unlock(&man->lock);
 }
 
@@ -507,6 +503,7 @@ static void vmw_cmdbuf_work_func(struct work_struct *work)
        struct vmw_cmdbuf_man *man =
                container_of(work, struct vmw_cmdbuf_man, work);
        struct vmw_cmdbuf_header *entry, *next;
+       uint32_t dummy;
        bool restart = false;
 
        spin_lock_bh(&man->lock);
@@ -523,6 +520,8 @@ static void vmw_cmdbuf_work_func(struct work_struct *work)
        if (restart && vmw_cmdbuf_startstop(man, true))
                DRM_ERROR("Failed restarting command buffer context 0.\n");
 
+       /* Send a new fence in case one was removed */
+       vmw_fifo_send_fence(man->dev_priv, &dummy);
 }
 
 /**
@@ -681,6 +680,14 @@ static bool vmw_cmdbuf_try_alloc(struct vmw_cmdbuf_man *man,
                                         0, 0,
                                         DRM_MM_SEARCH_DEFAULT,
                                         DRM_MM_CREATE_DEFAULT);
+       if (ret) {
+               vmw_cmdbuf_man_process(man);
+               ret = drm_mm_insert_node_generic(&man->mm, info->node,
+                                                info->page_size, 0, 0,
+                                                DRM_MM_SEARCH_DEFAULT,
+                                                DRM_MM_CREATE_DEFAULT);
+       }
+
        spin_unlock_bh(&man->lock);
        info->done = !ret;
 
@@ -1160,7 +1167,14 @@ int vmw_cmdbuf_set_pool_size(struct vmw_cmdbuf_man *man,
        drm_mm_init(&man->mm, 0, size >> PAGE_SHIFT);
 
        man->has_pool = true;
-       man->default_size = default_size;
+
+       /*
+        * For now, set the default size to VMW_CMDBUF_INLINE_SIZE to
+        * prevent deadlocks from happening when vmw_cmdbuf_space_pool()
+        * needs to wait for space and we block on further command
+        * submissions to be able to free up space.
+        */
+       man->default_size = VMW_CMDBUF_INLINE_SIZE;
        DRM_INFO("Using command buffers with %s pool.\n",
                 (man->using_mob) ? "MOB" : "DMA");
 
index ce659a125f2b36f72c8df4c62241fb85d151e724..092ea81eeff7116266caba8012fb2bc4fe38e42a 100644 (file)
@@ -311,7 +311,6 @@ static int vmw_cotable_unbind(struct vmw_resource *res,
        struct vmw_private *dev_priv = res->dev_priv;
        struct ttm_buffer_object *bo = val_buf->bo;
        struct vmw_fence_obj *fence;
-       int ret;
 
        if (list_empty(&res->mob_head))
                return 0;
@@ -328,7 +327,7 @@ static int vmw_cotable_unbind(struct vmw_resource *res,
        if (likely(fence != NULL))
                vmw_fence_obj_unreference(&fence);
 
-       return ret;
+       return 0;
 }
 
 /**
index e13b20bd9908d65b4b906d11f2a9d3aae0d8e847..2c7a25c71af2979c784b6cb4a87ee2088d4f8fbb 100644 (file)
@@ -752,12 +752,8 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
        ttm_lock_set_kill(&dev_priv->fbdev_master.lock, false, SIGTERM);
        dev_priv->active_master = &dev_priv->fbdev_master;
 
-
-       dev_priv->mmio_mtrr = arch_phys_wc_add(dev_priv->mmio_start,
-                                              dev_priv->mmio_size);
-
-       dev_priv->mmio_virt = ioremap_wc(dev_priv->mmio_start,
-                                        dev_priv->mmio_size);
+       dev_priv->mmio_virt = ioremap_cache(dev_priv->mmio_start,
+                                           dev_priv->mmio_size);
 
        if (unlikely(dev_priv->mmio_virt == NULL)) {
                ret = -ENOMEM;
@@ -913,7 +909,6 @@ out_no_device:
 out_err4:
        iounmap(dev_priv->mmio_virt);
 out_err3:
-       arch_phys_wc_del(dev_priv->mmio_mtrr);
        vmw_ttm_global_release(dev_priv);
 out_err0:
        for (i = vmw_res_context; i < vmw_res_max; ++i)
@@ -964,7 +959,6 @@ static int vmw_driver_unload(struct drm_device *dev)
 
        ttm_object_device_release(&dev_priv->tdev);
        iounmap(dev_priv->mmio_virt);
-       arch_phys_wc_del(dev_priv->mmio_mtrr);
        if (dev_priv->ctx.staged_bindings)
                vmw_binding_state_free(dev_priv->ctx.staged_bindings);
        vmw_ttm_global_release(dev_priv);
index 6d02de6dc36c2957993fc7b3e1ab465ec99d9743..f19fd39b43e178ff0ba5ed0655b77e11f219dc68 100644 (file)
@@ -376,7 +376,6 @@ struct vmw_private {
        uint32_t initial_width;
        uint32_t initial_height;
        u32 __iomem *mmio_virt;
-       int mmio_mtrr;
        uint32_t capabilities;
        uint32_t max_gmr_ids;
        uint32_t max_gmr_pages;
@@ -631,7 +630,8 @@ extern int vmw_user_dmabuf_alloc(struct vmw_private *dev_priv,
                                 uint32_t size,
                                 bool shareable,
                                 uint32_t *handle,
-                                struct vmw_dma_buffer **p_dma_buf);
+                                struct vmw_dma_buffer **p_dma_buf,
+                                struct ttm_base_object **p_base);
 extern int vmw_user_dmabuf_reference(struct ttm_object_file *tfile,
                                     struct vmw_dma_buffer *dma_buf,
                                     uint32_t *handle);
@@ -645,7 +645,8 @@ extern uint32_t vmw_dmabuf_validate_node(struct ttm_buffer_object *bo,
                                         uint32_t cur_validate_node);
 extern void vmw_dmabuf_validate_clear(struct ttm_buffer_object *bo);
 extern int vmw_user_dmabuf_lookup(struct ttm_object_file *tfile,
-                                 uint32_t id, struct vmw_dma_buffer **out);
+                                 uint32_t id, struct vmw_dma_buffer **out,
+                                 struct ttm_base_object **base);
 extern int vmw_stream_claim_ioctl(struct drm_device *dev, void *data,
                                  struct drm_file *file_priv);
 extern int vmw_stream_unref_ioctl(struct drm_device *dev, void *data,
index b56565457c968b32ba8a1f532664c79dadffb9af..5da5de0cb52203809fb7f2ffa591fe54204d9bc9 100644 (file)
@@ -1236,7 +1236,8 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv,
        struct vmw_relocation *reloc;
        int ret;
 
-       ret = vmw_user_dmabuf_lookup(sw_context->fp->tfile, handle, &vmw_bo);
+       ret = vmw_user_dmabuf_lookup(sw_context->fp->tfile, handle, &vmw_bo,
+                                    NULL);
        if (unlikely(ret != 0)) {
                DRM_ERROR("Could not find or use MOB buffer.\n");
                ret = -EINVAL;
@@ -1296,7 +1297,8 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv,
        struct vmw_relocation *reloc;
        int ret;
 
-       ret = vmw_user_dmabuf_lookup(sw_context->fp->tfile, handle, &vmw_bo);
+       ret = vmw_user_dmabuf_lookup(sw_context->fp->tfile, handle, &vmw_bo,
+                                    NULL);
        if (unlikely(ret != 0)) {
                DRM_ERROR("Could not find or use GMR region.\n");
                ret = -EINVAL;
index 61fb7f3de3119ae3f94ad6dd9fef57f0c9c780c4..15a6c01cd016b28dfe9cfec9d1d5515f1166f835 100644 (file)
@@ -1685,7 +1685,6 @@ int vmw_kms_helper_dirty(struct vmw_private *dev_priv,
        struct drm_crtc *crtc;
        u32 num_units = 0;
        u32 i, k;
-       int ret;
 
        dirty->dev_priv = dev_priv;
 
@@ -1711,7 +1710,7 @@ int vmw_kms_helper_dirty(struct vmw_private *dev_priv,
                        if (!dirty->cmd) {
                                DRM_ERROR("Couldn't reserve fifo space "
                                          "for dirty blits.\n");
-                               return ret;
+                               return -ENOMEM;
                        }
                        memset(dirty->cmd, 0, dirty->fifo_reserve_size);
                }
index 76069f093ccfc1bba5eaae519598af5a0e4c1c81..222c9c2123a1ef5e761128d7c6c9ceb11e5131e7 100644 (file)
@@ -484,7 +484,7 @@ int vmw_overlay_ioctl(struct drm_device *dev, void *data,
                goto out_unlock;
        }
 
-       ret = vmw_user_dmabuf_lookup(tfile, arg->handle, &buf);
+       ret = vmw_user_dmabuf_lookup(tfile, arg->handle, &buf, NULL);
        if (ret)
                goto out_unlock;
 
index c1912f852b42ece95531e6194954228c5a84ab25..e57667ca75573d720cc7ec5143babb0da1e5693d 100644 (file)
@@ -354,7 +354,7 @@ int vmw_user_lookup_handle(struct vmw_private *dev_priv,
        }
 
        *out_surf = NULL;
-       ret = vmw_user_dmabuf_lookup(tfile, handle, out_buf);
+       ret = vmw_user_dmabuf_lookup(tfile, handle, out_buf, NULL);
        return ret;
 }
 
@@ -481,7 +481,8 @@ int vmw_user_dmabuf_alloc(struct vmw_private *dev_priv,
                          uint32_t size,
                          bool shareable,
                          uint32_t *handle,
-                         struct vmw_dma_buffer **p_dma_buf)
+                         struct vmw_dma_buffer **p_dma_buf,
+                         struct ttm_base_object **p_base)
 {
        struct vmw_user_dma_buffer *user_bo;
        struct ttm_buffer_object *tmp;
@@ -515,6 +516,10 @@ int vmw_user_dmabuf_alloc(struct vmw_private *dev_priv,
        }
 
        *p_dma_buf = &user_bo->dma;
+       if (p_base) {
+               *p_base = &user_bo->prime.base;
+               kref_get(&(*p_base)->refcount);
+       }
        *handle = user_bo->prime.base.hash.key;
 
 out_no_base_object:
@@ -631,6 +636,7 @@ int vmw_user_dmabuf_synccpu_ioctl(struct drm_device *dev, void *data,
        struct vmw_dma_buffer *dma_buf;
        struct vmw_user_dma_buffer *user_bo;
        struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+       struct ttm_base_object *buffer_base;
        int ret;
 
        if ((arg->flags & (drm_vmw_synccpu_read | drm_vmw_synccpu_write)) == 0
@@ -643,7 +649,8 @@ int vmw_user_dmabuf_synccpu_ioctl(struct drm_device *dev, void *data,
 
        switch (arg->op) {
        case drm_vmw_synccpu_grab:
-               ret = vmw_user_dmabuf_lookup(tfile, arg->handle, &dma_buf);
+               ret = vmw_user_dmabuf_lookup(tfile, arg->handle, &dma_buf,
+                                            &buffer_base);
                if (unlikely(ret != 0))
                        return ret;
 
@@ -651,6 +658,7 @@ int vmw_user_dmabuf_synccpu_ioctl(struct drm_device *dev, void *data,
                                       dma);
                ret = vmw_user_dmabuf_synccpu_grab(user_bo, tfile, arg->flags);
                vmw_dmabuf_unreference(&dma_buf);
+               ttm_base_object_unref(&buffer_base);
                if (unlikely(ret != 0 && ret != -ERESTARTSYS &&
                             ret != -EBUSY)) {
                        DRM_ERROR("Failed synccpu grab on handle 0x%08x.\n",
@@ -692,7 +700,8 @@ int vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data,
                return ret;
 
        ret = vmw_user_dmabuf_alloc(dev_priv, vmw_fpriv(file_priv)->tfile,
-                                   req->size, false, &handle, &dma_buf);
+                                   req->size, false, &handle, &dma_buf,
+                                   NULL);
        if (unlikely(ret != 0))
                goto out_no_dmabuf;
 
@@ -721,7 +730,8 @@ int vmw_dmabuf_unref_ioctl(struct drm_device *dev, void *data,
 }
 
 int vmw_user_dmabuf_lookup(struct ttm_object_file *tfile,
-                          uint32_t handle, struct vmw_dma_buffer **out)
+                          uint32_t handle, struct vmw_dma_buffer **out,
+                          struct ttm_base_object **p_base)
 {
        struct vmw_user_dma_buffer *vmw_user_bo;
        struct ttm_base_object *base;
@@ -743,7 +753,10 @@ int vmw_user_dmabuf_lookup(struct ttm_object_file *tfile,
        vmw_user_bo = container_of(base, struct vmw_user_dma_buffer,
                                   prime.base);
        (void)ttm_bo_reference(&vmw_user_bo->dma.base);
-       ttm_base_object_unref(&base);
+       if (p_base)
+               *p_base = base;
+       else
+               ttm_base_object_unref(&base);
        *out = &vmw_user_bo->dma;
 
        return 0;
@@ -1004,7 +1017,7 @@ int vmw_dumb_create(struct drm_file *file_priv,
 
        ret = vmw_user_dmabuf_alloc(dev_priv, vmw_fpriv(file_priv)->tfile,
                                    args->size, false, &args->handle,
-                                   &dma_buf);
+                                   &dma_buf, NULL);
        if (unlikely(ret != 0))
                goto out_no_dmabuf;
 
@@ -1032,7 +1045,7 @@ int vmw_dumb_map_offset(struct drm_file *file_priv,
        struct vmw_dma_buffer *out_buf;
        int ret;
 
-       ret = vmw_user_dmabuf_lookup(tfile, handle, &out_buf);
+       ret = vmw_user_dmabuf_lookup(tfile, handle, &out_buf, NULL);
        if (ret != 0)
                return -EINVAL;
 
index bba1ee3954786232f2c6605793fc81071bc9cc23..fd47547b0234c6e1299e3311ab9f23be03c08810 100644 (file)
@@ -855,7 +855,7 @@ static int vmw_shader_define(struct drm_device *dev, struct drm_file *file_priv,
 
        if (buffer_handle != SVGA3D_INVALID_ID) {
                ret = vmw_user_dmabuf_lookup(tfile, buffer_handle,
-                                            &buffer);
+                                            &buffer, NULL);
                if (unlikely(ret != 0)) {
                        DRM_ERROR("Could not find buffer for shader "
                                  "creation.\n");
index 3361769842f4d91a3b7dc68a3e2818c2572d75a8..03f63c749c02333f412c82184f20def8ce1d8d74 100644 (file)
@@ -46,6 +46,7 @@ struct vmw_user_surface {
        struct vmw_surface srf;
        uint32_t size;
        struct drm_master *master;
+       struct ttm_base_object *backup_base;
 };
 
 /**
@@ -656,6 +657,8 @@ static void vmw_user_surface_base_release(struct ttm_base_object **p_base)
        struct vmw_resource *res = &user_srf->srf.res;
 
        *p_base = NULL;
+       if (user_srf->backup_base)
+               ttm_base_object_unref(&user_srf->backup_base);
        vmw_resource_unreference(&res);
 }
 
@@ -851,7 +854,8 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
                                            res->backup_size,
                                            true,
                                            &backup_handle,
-                                           &res->backup);
+                                           &res->backup,
+                                           &user_srf->backup_base);
                if (unlikely(ret != 0)) {
                        vmw_resource_unreference(&res);
                        goto out_unlock;
@@ -1321,7 +1325,8 @@ int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data,
 
        if (req->buffer_handle != SVGA3D_INVALID_ID) {
                ret = vmw_user_dmabuf_lookup(tfile, req->buffer_handle,
-                                            &res->backup);
+                                            &res->backup,
+                                            &user_srf->backup_base);
                if (ret == 0 && res->backup->base.num_pages * PAGE_SIZE <
                    res->backup_size) {
                        DRM_ERROR("Surface backup buffer is too small.\n");
@@ -1335,7 +1340,8 @@ int vmw_gb_surface_define_ioctl(struct drm_device *dev, void *data,
                                            req->drm_surface_flags &
                                            drm_vmw_surface_flag_shareable,
                                            &backup_handle,
-                                           &res->backup);
+                                           &res->backup,
+                                           &user_srf->backup_base);
 
        if (unlikely(ret != 0)) {
                vmw_resource_unreference(&res);
index 243f99a802535cd7ab9e876c439a206846b20d22..e5a38d202a21134f12e51061ef503afa29b81d73 100644 (file)
@@ -912,7 +912,7 @@ static void ipu_irq_handle(struct ipu_soc *ipu, const int *regs, int num_regs)
        }
 }
 
-static void ipu_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void ipu_irq_handler(struct irq_desc *desc)
 {
        struct ipu_soc *ipu = irq_desc_get_handler_data(desc);
        struct irq_chip *chip = irq_desc_get_chip(desc);
@@ -925,7 +925,7 @@ static void ipu_irq_handler(unsigned int irq, struct irq_desc *desc)
        chained_irq_exit(chip, desc);
 }
 
-static void ipu_err_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void ipu_err_irq_handler(struct irq_desc *desc)
 {
        struct ipu_soc *ipu = irq_desc_get_handler_data(desc);
        struct irq_chip *chip = irq_desc_get_chip(desc);
@@ -1099,8 +1099,7 @@ static int ipu_irq_init(struct ipu_soc *ipu)
        }
 
        ret = irq_alloc_domain_generic_chips(ipu->domain, 32, 1, "IPU",
-                                            handle_level_irq, 0,
-                                            IRQF_VALID, 0);
+                                            handle_level_irq, 0, 0, 0);
        if (ret < 0) {
                dev_err(ipu->dev, "failed to alloc generic irq chips\n");
                irq_domain_remove(ipu->domain);
index 2f9aead4ecfc0e696d1fe4f3c8d8fdddbe9e49fc..652afd11a9efdceb545add8bad4980b41f698340 100644 (file)
@@ -204,6 +204,8 @@ void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid)
                spin_lock_irqsave(&vmbus_connection.channel_lock, flags);
                list_del(&channel->listentry);
                spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags);
+
+               primary_channel = channel;
        } else {
                primary_channel = channel->primary_channel;
                spin_lock_irqsave(&primary_channel->lock, flags);
@@ -211,6 +213,14 @@ void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid)
                primary_channel->num_sc--;
                spin_unlock_irqrestore(&primary_channel->lock, flags);
        }
+
+       /*
+        * We need to free the bit for init_vp_index() to work in the case
+        * of sub-channel, when we reload drivers like hv_netvsc.
+        */
+       cpumask_clear_cpu(channel->target_cpu,
+                         &primary_channel->alloced_cpus_in_node);
+
        free_channel(channel);
 }
 
@@ -458,6 +468,13 @@ static void init_vp_index(struct vmbus_channel *channel, const uuid_le *type_gui
                        continue;
                }
 
+               /*
+                * NOTE: in the case of sub-channel, we clear the sub-channel
+                * related bit(s) in primary->alloced_cpus_in_node in
+                * hv_process_channel_removal(), so when we reload drivers
+                * like hv_netvsc in SMP guest, here we're able to re-allocate
+                * bit from primary->alloced_cpus_in_node.
+                */
                if (!cpumask_test_cpu(cur_cpu,
                                &primary->alloced_cpus_in_node)) {
                        cpumask_set_cpu(cur_cpu,
index 500b262b89bb15ee9859caa097fdb2b2f6977849..e13c902e8966977581f1959155b3f83774e94aa5 100644 (file)
@@ -1140,8 +1140,8 @@ config SENSORS_NCT6775
        help
          If you say yes here you get support for the hardware monitoring
          functionality of the Nuvoton NCT6106D, NCT6775F, NCT6776F, NCT6779D,
-         NCT6791D, NCT6792D and compatible Super-I/O chips. This driver
-         replaces the w83627ehf driver for NCT6775F and NCT6776F.
+         NCT6791D, NCT6792D, NCT6793D, and compatible Super-I/O chips. This
+         driver replaces the w83627ehf driver for NCT6775F and NCT6776F.
 
          This driver can also be built as a module.  If so, the module
          will be called nct6775.
index 6cb89c0ebab6df03f7e8b38fc81cecd3136e57de..1fd46859ed29ded69dbb479c980316142bde5fd7 100644 (file)
@@ -470,6 +470,7 @@ static const struct of_device_id abx500_temp_match[] = {
        { .compatible = "stericsson,abx500-temp" },
        {},
 };
+MODULE_DEVICE_TABLE(of, abx500_temp_match);
 #endif
 
 static struct platform_driver abx500_temp_driver = {
index a3dae6d0082a0d08e4183f63e27b79ae5510b863..82de3deeb18a7ddf5e041e695b35cc8b1500abea 100644 (file)
@@ -539,6 +539,7 @@ static const struct of_device_id of_gpio_fan_match[] = {
        { .compatible = "gpio-fan", },
        {},
 };
+MODULE_DEVICE_TABLE(of, of_gpio_fan_match);
 #endif /* CONFIG_OF_GPIO */
 
 static int gpio_fan_probe(struct platform_device *pdev)
index bd1c99deac71b73dadf15615c1e8442027bccee9..8b4fa55e46c6afceb3895515bc0df0cb3b8a4b85 100644 (file)
@@ -39,6 +39,7 @@
  * nct6779d    15      5       5       2+6    0xc560 0xc1    0x5ca3
  * nct6791d    15      6       6       2+6    0xc800 0xc1    0x5ca3
  * nct6792d    15      6       6       2+6    0xc910 0xc1    0x5ca3
+ * nct6793d    15      6       6       2+6    0xd120 0xc1    0x5ca3
  *
  * #temp lists the number of monitored temperature sources (first value) plus
  * the number of directly connectable temperature sensors (second value).
@@ -63,7 +64,7 @@
 
 #define USE_ALTERNATE
 
-enum kinds { nct6106, nct6775, nct6776, nct6779, nct6791, nct6792 };
+enum kinds { nct6106, nct6775, nct6776, nct6779, nct6791, nct6792, nct6793 };
 
 /* used to set data->name = nct6775_device_names[data->sio_kind] */
 static const char * const nct6775_device_names[] = {
@@ -73,6 +74,17 @@ static const char * const nct6775_device_names[] = {
        "nct6779",
        "nct6791",
        "nct6792",
+       "nct6793",
+};
+
+static const char * const nct6775_sio_names[] __initconst = {
+       "NCT6106D",
+       "NCT6775F",
+       "NCT6776D/F",
+       "NCT6779D",
+       "NCT6791D",
+       "NCT6792D",
+       "NCT6793D",
 };
 
 static unsigned short force_id;
@@ -104,6 +116,7 @@ MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal");
 #define SIO_NCT6779_ID         0xc560
 #define SIO_NCT6791_ID         0xc800
 #define SIO_NCT6792_ID         0xc910
+#define SIO_NCT6793_ID         0xd120
 #define SIO_ID_MASK            0xFFF0
 
 enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 };
@@ -354,6 +367,10 @@ static const u16 NCT6775_REG_TEMP_CRIT[ARRAY_SIZE(nct6775_temp_label) - 1]
 
 /* NCT6776 specific data */
 
+/* STEP_UP_TIME and STEP_DOWN_TIME regs are swapped for all chips but NCT6775 */
+#define NCT6776_REG_FAN_STEP_UP_TIME NCT6775_REG_FAN_STEP_DOWN_TIME
+#define NCT6776_REG_FAN_STEP_DOWN_TIME NCT6775_REG_FAN_STEP_UP_TIME
+
 static const s8 NCT6776_ALARM_BITS[] = {
        0, 1, 2, 3, 8, 21, 20, 16,      /* in0.. in7 */
        17, -1, -1, -1, -1, -1, -1,     /* in8..in14 */
@@ -533,7 +550,7 @@ static const s8 NCT6791_ALARM_BITS[] = {
        4, 5, 13, -1, -1, -1,           /* temp1..temp6 */
        12, 9 };                        /* intrusion0, intrusion1 */
 
-/* NCT6792 specific data */
+/* NCT6792/NCT6793 specific data */
 
 static const u16 NCT6792_REG_TEMP_MON[] = {
        0x73, 0x75, 0x77, 0x79, 0x7b, 0x7d };
@@ -1056,6 +1073,7 @@ static bool is_word_sized(struct nct6775_data *data, u16 reg)
        case nct6779:
        case nct6791:
        case nct6792:
+       case nct6793:
                return reg == 0x150 || reg == 0x153 || reg == 0x155 ||
                  ((reg & 0xfff0) == 0x4b0 && (reg & 0x000f) < 0x0b) ||
                  reg == 0x402 ||
@@ -1407,6 +1425,7 @@ static void nct6775_update_pwm_limits(struct device *dev)
                case nct6779:
                case nct6791:
                case nct6792:
+               case nct6793:
                        reg = nct6775_read_value(data,
                                        data->REG_CRITICAL_PWM_ENABLE[i]);
                        if (reg & data->CRITICAL_PWM_ENABLE_MASK)
@@ -2822,6 +2841,7 @@ store_auto_pwm(struct device *dev, struct device_attribute *attr,
                case nct6779:
                case nct6791:
                case nct6792:
+               case nct6793:
                        nct6775_write_value(data, data->REG_CRITICAL_PWM[nr],
                                            val);
                        reg = nct6775_read_value(data,
@@ -3256,7 +3276,7 @@ nct6775_check_fan_inputs(struct nct6775_data *data)
                pwm4pin = false;
                pwm5pin = false;
                pwm6pin = false;
-       } else {        /* NCT6779D, NCT6791D, or NCT6792D */
+       } else {        /* NCT6779D, NCT6791D, NCT6792D, or NCT6793D */
                regval = superio_inb(sioreg, 0x1c);
 
                fan3pin = !(regval & (1 << 5));
@@ -3269,7 +3289,8 @@ nct6775_check_fan_inputs(struct nct6775_data *data)
 
                fan4min = fan4pin;
 
-               if (data->kind == nct6791 || data->kind == nct6792) {
+               if (data->kind == nct6791 || data->kind == nct6792 ||
+                   data->kind == nct6793) {
                        regval = superio_inb(sioreg, 0x2d);
                        fan6pin = (regval & (1 << 1));
                        pwm6pin = (regval & (1 << 0));
@@ -3528,8 +3549,8 @@ static int nct6775_probe(struct platform_device *pdev)
                data->REG_FAN_PULSES = NCT6776_REG_FAN_PULSES;
                data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
                data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
-               data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
-               data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
+               data->REG_FAN_TIME[1] = NCT6776_REG_FAN_STEP_UP_TIME;
+               data->REG_FAN_TIME[2] = NCT6776_REG_FAN_STEP_DOWN_TIME;
                data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
                data->REG_PWM[0] = NCT6775_REG_PWM;
                data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
@@ -3600,8 +3621,8 @@ static int nct6775_probe(struct platform_device *pdev)
                data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES;
                data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
                data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
-               data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
-               data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
+               data->REG_FAN_TIME[1] = NCT6776_REG_FAN_STEP_UP_TIME;
+               data->REG_FAN_TIME[2] = NCT6776_REG_FAN_STEP_DOWN_TIME;
                data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
                data->REG_PWM[0] = NCT6775_REG_PWM;
                data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
@@ -3643,6 +3664,7 @@ static int nct6775_probe(struct platform_device *pdev)
                break;
        case nct6791:
        case nct6792:
+       case nct6793:
                data->in_num = 15;
                data->pwm_num = 6;
                data->auto_pwm_num = 4;
@@ -3677,8 +3699,8 @@ static int nct6775_probe(struct platform_device *pdev)
                data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES;
                data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT;
                data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
-               data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
-               data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
+               data->REG_FAN_TIME[1] = NCT6776_REG_FAN_STEP_UP_TIME;
+               data->REG_FAN_TIME[2] = NCT6776_REG_FAN_STEP_DOWN_TIME;
                data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H;
                data->REG_PWM[0] = NCT6775_REG_PWM;
                data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
@@ -3918,6 +3940,7 @@ static int nct6775_probe(struct platform_device *pdev)
        case nct6779:
        case nct6791:
        case nct6792:
+       case nct6793:
                break;
        }
 
@@ -3950,6 +3973,7 @@ static int nct6775_probe(struct platform_device *pdev)
                        break;
                case nct6791:
                case nct6792:
+               case nct6793:
                        tmp |= 0x7e;
                        break;
                }
@@ -4047,7 +4071,8 @@ static int __maybe_unused nct6775_resume(struct device *dev)
        if (reg != data->sio_reg_enable)
                superio_outb(sioreg, SIO_REG_ENABLE, data->sio_reg_enable);
 
-       if (data->kind == nct6791 || data->kind == nct6792)
+       if (data->kind == nct6791 || data->kind == nct6792 ||
+           data->kind == nct6793)
                nct6791_enable_io_mapping(sioreg);
 
        superio_exit(sioreg);
@@ -4106,15 +4131,6 @@ static struct platform_driver nct6775_driver = {
        .probe          = nct6775_probe,
 };
 
-static const char * const nct6775_sio_names[] __initconst = {
-       "NCT6106D",
-       "NCT6775F",
-       "NCT6776D/F",
-       "NCT6779D",
-       "NCT6791D",
-       "NCT6792D",
-};
-
 /* nct6775_find() looks for a '627 in the Super-I/O config space */
 static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
 {
@@ -4150,6 +4166,9 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
        case SIO_NCT6792_ID:
                sio_data->kind = nct6792;
                break;
+       case SIO_NCT6793_ID:
+               sio_data->kind = nct6793;
+               break;
        default:
                if (val != 0xffff)
                        pr_debug("unsupported chip ID: 0x%04x\n", val);
@@ -4175,7 +4194,8 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
                superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01);
        }
 
-       if (sio_data->kind == nct6791 || sio_data->kind == nct6792)
+       if (sio_data->kind == nct6791 || sio_data->kind == nct6792 ||
+           sio_data->kind == nct6793)
                nct6791_enable_io_mapping(sioaddr);
 
        superio_exit(sioaddr);
@@ -4285,7 +4305,7 @@ static void __exit sensors_nct6775_exit(void)
 }
 
 MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
-MODULE_DESCRIPTION("NCT6106D/NCT6775F/NCT6776F/NCT6779D/NCT6791D/NCT6792D driver");
+MODULE_DESCRIPTION("Driver for NCT6775F and compatible chips");
 MODULE_LICENSE("GPL");
 
 module_init(sensors_nct6775_init);
index 2d9a712699ff5d541e831629834b23882b4fa606..3e23003f78b01ca731e8c232f38e1132eccf251f 100644 (file)
@@ -323,6 +323,7 @@ static const struct of_device_id of_pwm_fan_match[] = {
        { .compatible = "pwm-fan", },
        {},
 };
+MODULE_DEVICE_TABLE(of, of_pwm_fan_match);
 
 static struct platform_driver pwm_fan_driver = {
        .probe          = pwm_fan_probe,
index 3dd2de31a2f8d380f71ff61c562a53d8638f9eb5..472b88285c755e5f18d25ba2c935dbdaca449546 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/delay.h>
+#include <linux/dmi.h>
 #include <linux/i2c.h>
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
@@ -51,6 +52,22 @@ static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev)
 }
 
 #ifdef CONFIG_ACPI
+/*
+ * The HCNT/LCNT information coming from ACPI should be the most accurate
+ * for given platform. However, some systems get it wrong. On such systems
+ * we get better results by calculating those based on the input clock.
+ */
+static const struct dmi_system_id dw_i2c_no_acpi_params[] = {
+       {
+               .ident = "Dell Inspiron 7348",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7348"),
+               },
+       },
+       { }
+};
+
 static void dw_i2c_acpi_params(struct platform_device *pdev, char method[],
                               u16 *hcnt, u16 *lcnt, u32 *sda_hold)
 {
@@ -58,6 +75,9 @@ static void dw_i2c_acpi_params(struct platform_device *pdev, char method[],
        acpi_handle handle = ACPI_HANDLE(&pdev->dev);
        union acpi_object *obj;
 
+       if (dmi_check_system(dw_i2c_no_acpi_params))
+               return;
+
        if (ACPI_FAILURE(acpi_evaluate_object(handle, method, NULL, &buf)))
                return;
 
@@ -253,12 +273,6 @@ static int dw_i2c_probe(struct platform_device *pdev)
        adap->dev.parent = &pdev->dev;
        adap->dev.of_node = pdev->dev.of_node;
 
-       r = i2c_add_numbered_adapter(adap);
-       if (r) {
-               dev_err(&pdev->dev, "failure adding adapter\n");
-               return r;
-       }
-
        if (dev->pm_runtime_disabled) {
                pm_runtime_forbid(&pdev->dev);
        } else {
@@ -268,6 +282,13 @@ static int dw_i2c_probe(struct platform_device *pdev)
                pm_runtime_enable(&pdev->dev);
        }
 
+       r = i2c_add_numbered_adapter(adap);
+       if (r) {
+               dev_err(&pdev->dev, "failure adding adapter\n");
+               pm_runtime_disable(&pdev->dev);
+               return r;
+       }
+
        return 0;
 }
 
index 30059c1df2a3b57ea559fc984b559c79e2f06ce6..5801227b97ab089022f90608f6fc425ebd13cd87 100644 (file)
@@ -669,8 +669,6 @@ mv64xxx_i2c_can_offload(struct mv64xxx_i2c_data *drv_data)
        struct i2c_msg *msgs = drv_data->msgs;
        int num = drv_data->num_msgs;
 
-       return false;
-
        if (!drv_data->offload_enabled)
                return false;
 
index e814a36d9b78f26436cd8cf1745dd2aaa3b36db8..6f8b446be5b0e5787deede7f675044332d72f8cb 100644 (file)
@@ -600,7 +600,7 @@ static int i2c_pnx_controller_suspend(struct device *dev)
 {
        struct i2c_pnx_algo_data *alg_data = dev_get_drvdata(dev);
 
-       clk_disable(alg_data->clk);
+       clk_disable_unprepare(alg_data->clk);
 
        return 0;
 }
@@ -609,7 +609,7 @@ static int i2c_pnx_controller_resume(struct device *dev)
 {
        struct i2c_pnx_algo_data *alg_data = dev_get_drvdata(dev);
 
-       return clk_enable(alg_data->clk);
+       return clk_prepare_enable(alg_data->clk);
 }
 
 static SIMPLE_DEV_PM_OPS(i2c_pnx_pm,
@@ -672,7 +672,7 @@ static int i2c_pnx_probe(struct platform_device *pdev)
        if (IS_ERR(alg_data->ioaddr))
                return PTR_ERR(alg_data->ioaddr);
 
-       ret = clk_enable(alg_data->clk);
+       ret = clk_prepare_enable(alg_data->clk);
        if (ret)
                return ret;
 
@@ -726,7 +726,7 @@ static int i2c_pnx_probe(struct platform_device *pdev)
        return 0;
 
 out_clock:
-       clk_disable(alg_data->clk);
+       clk_disable_unprepare(alg_data->clk);
        return ret;
 }
 
@@ -735,7 +735,7 @@ static int i2c_pnx_remove(struct platform_device *pdev)
        struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev);
 
        i2c_del_adapter(&alg_data->adapter);
-       clk_disable(alg_data->clk);
+       clk_disable_unprepare(alg_data->clk);
 
        return 0;
 }
index d8361dada584556baccc2c6bd861eb11028c6d51..d8b5a8fee1e6c85588dd569b80894306b1c76b1a 100644 (file)
@@ -690,15 +690,16 @@ static int rcar_i2c_probe(struct platform_device *pdev)
                return ret;
        }
 
+       pm_runtime_enable(dev);
+       platform_set_drvdata(pdev, priv);
+
        ret = i2c_add_numbered_adapter(adap);
        if (ret < 0) {
                dev_err(dev, "reg adap failed: %d\n", ret);
+               pm_runtime_disable(dev);
                return ret;
        }
 
-       pm_runtime_enable(dev);
-       platform_set_drvdata(pdev, priv);
-
        dev_info(dev, "probed\n");
 
        return 0;
index 50bfd8cef5f224aebb189a5b6635b62316f6117c..5df819610d5280cc1fee176344be4d226fc5ea56 100644 (file)
@@ -1243,17 +1243,19 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
        i2c->adap.nr = i2c->pdata->bus_num;
        i2c->adap.dev.of_node = pdev->dev.of_node;
 
+       platform_set_drvdata(pdev, i2c);
+
+       pm_runtime_enable(&pdev->dev);
+
        ret = i2c_add_numbered_adapter(&i2c->adap);
        if (ret < 0) {
                dev_err(&pdev->dev, "failed to add bus to i2c core\n");
+               pm_runtime_disable(&pdev->dev);
                s3c24xx_i2c_deregister_cpufreq(i2c);
                clk_unprepare(i2c->clk);
                return ret;
        }
 
-       platform_set_drvdata(pdev, i2c);
-
-       pm_runtime_enable(&pdev->dev);
        pm_runtime_enable(&i2c->adap.dev);
 
        dev_info(&pdev->dev, "%s: S3C I2C adapter\n", dev_name(&i2c->adap.dev));
index 5f89f1e3c2f24fc562a519eb173d33de8c280f42..a59c3111f7fb98df957e19d1fa93faac16322e20 100644 (file)
@@ -694,12 +694,12 @@ static int i2c_device_probe(struct device *dev)
                goto err_clear_wakeup_irq;
 
        status = dev_pm_domain_attach(&client->dev, true);
-       if (status != -EPROBE_DEFER) {
-               status = driver->probe(client, i2c_match_id(driver->id_table,
-                                       client));
-               if (status)
-                       goto err_detach_pm_domain;
-       }
+       if (status == -EPROBE_DEFER)
+               goto err_clear_wakeup_irq;
+
+       status = driver->probe(client, i2c_match_id(driver->id_table, client));
+       if (status)
+               goto err_detach_pm_domain;
 
        return 0;
 
index 3a3738fe016b3af0a2e0b723396822b786e2c20f..cd4510a6337548d26344b8ccc5cb427ab13dd4ef 100644 (file)
@@ -620,7 +620,7 @@ static struct cpuidle_state skl_cstates[] = {
                .name = "C6-SKL",
                .desc = "MWAIT 0x20",
                .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
-               .exit_latency = 75,
+               .exit_latency = 85,
                .target_residency = 200,
                .enter = &intel_idle,
                .enter_freeze = intel_idle_freeze, },
@@ -636,10 +636,18 @@ static struct cpuidle_state skl_cstates[] = {
                .name = "C8-SKL",
                .desc = "MWAIT 0x40",
                .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED,
-               .exit_latency = 174,
+               .exit_latency = 200,
                .target_residency = 800,
                .enter = &intel_idle,
                .enter_freeze = intel_idle_freeze, },
+       {
+               .name = "C9-SKL",
+               .desc = "MWAIT 0x50",
+               .flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED,
+               .exit_latency = 480,
+               .target_residency = 5000,
+               .enter = &intel_idle,
+               .enter_freeze = intel_idle_freeze, },
        {
                .name = "C10-SKL",
                .desc = "MWAIT 0x60",
index ff30f880688019fa099d79d7fce3f53b28cfb828..fb93111104249bcc93d390e7492c96f4c211ac27 100644 (file)
 #define ST_ACCEL_4_BDU_MASK                    0x40
 #define ST_ACCEL_4_DRDY_IRQ_ADDR               0x21
 #define ST_ACCEL_4_DRDY_IRQ_INT1_MASK          0x04
-#define ST_ACCEL_4_IG1_EN_ADDR                 0x21
-#define ST_ACCEL_4_IG1_EN_MASK                 0x08
 #define ST_ACCEL_4_MULTIREAD_BIT               true
 
 /* CUSTOM VALUES FOR SENSOR 5 */
@@ -489,10 +487,6 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
                .drdy_irq = {
                        .addr = ST_ACCEL_4_DRDY_IRQ_ADDR,
                        .mask_int1 = ST_ACCEL_4_DRDY_IRQ_INT1_MASK,
-                       .ig1 = {
-                               .en_addr = ST_ACCEL_4_IG1_EN_ADDR,
-                               .en_mask = ST_ACCEL_4_IG1_EN_MASK,
-                       },
                },
                .multi_read_bit = ST_ACCEL_4_MULTIREAD_BIT,
                .bootime = 2, /* guess */
index ebe415f1064000c95c88f5d20da48a7f52f71d84..0c74869a540ad390a0f995a702ee953cf53e0669 100644 (file)
 #include <linux/types.h>
 #include <linux/gfp.h>
 #include <linux/err.h>
+#include <linux/regulator/consumer.h>
 
 #include <linux/iio/iio.h>
 
+#define TWL4030_USB_SEL_MADC_MCPC      (1<<3)
+#define TWL4030_USB_CARKIT_ANA_CTRL    0xBB
+
 /**
  * struct twl4030_madc_data - a container for madc info
  * @dev:               Pointer to device structure for madc
  * @lock:              Mutex protecting this data structure
+ * @regulator:         Pointer to bias regulator for madc
  * @requests:          Array of request struct corresponding to SW1, SW2 and RT
  * @use_second_irq:    IRQ selection (main or co-processor)
  * @imr:               Interrupt mask register of MADC
@@ -60,6 +65,7 @@
 struct twl4030_madc_data {
        struct device *dev;
        struct mutex lock;      /* mutex protecting this data structure */
+       struct regulator *usb3v1;
        struct twl4030_madc_request requests[TWL4030_MADC_NUM_METHODS];
        bool use_second_irq;
        u8 imr;
@@ -841,6 +847,32 @@ static int twl4030_madc_probe(struct platform_device *pdev)
        }
        twl4030_madc = madc;
 
+       /* Configure MADC[3:6] */
+       ret = twl_i2c_read_u8(TWL_MODULE_USB, &regval,
+                       TWL4030_USB_CARKIT_ANA_CTRL);
+       if (ret) {
+               dev_err(&pdev->dev, "unable to read reg CARKIT_ANA_CTRL  0x%X\n",
+                               TWL4030_USB_CARKIT_ANA_CTRL);
+               goto err_i2c;
+       }
+       regval |= TWL4030_USB_SEL_MADC_MCPC;
+       ret = twl_i2c_write_u8(TWL_MODULE_USB, regval,
+                                TWL4030_USB_CARKIT_ANA_CTRL);
+       if (ret) {
+               dev_err(&pdev->dev, "unable to write reg CARKIT_ANA_CTRL 0x%X\n",
+                               TWL4030_USB_CARKIT_ANA_CTRL);
+               goto err_i2c;
+       }
+
+       /* Enable 3v1 bias regulator for MADC[3:6] */
+       madc->usb3v1 = devm_regulator_get(madc->dev, "vusb3v1");
+       if (IS_ERR(madc->usb3v1))
+               return -ENODEV;
+
+       ret = regulator_enable(madc->usb3v1);
+       if (ret)
+               dev_err(madc->dev, "could not enable 3v1 bias regulator\n");
+
        ret = iio_device_register(iio_dev);
        if (ret) {
                dev_err(&pdev->dev, "could not register iio device\n");
@@ -866,6 +898,8 @@ static int twl4030_madc_remove(struct platform_device *pdev)
        twl4030_madc_set_current_generator(madc, 0, 0);
        twl4030_madc_set_power(madc, 0);
 
+       regulator_disable(madc->usb3v1);
+
        return 0;
 }
 
index da4c6979fbb8ed310e41e7e585aab421af9deb3d..aa26f3c3416bbbcd04dac1ec5381fcb081105d5e 100644 (file)
@@ -56,7 +56,6 @@ config INFINIBAND_ADDR_TRANS
 
 source "drivers/infiniband/hw/mthca/Kconfig"
 source "drivers/infiniband/hw/qib/Kconfig"
-source "drivers/infiniband/hw/ehca/Kconfig"
 source "drivers/infiniband/hw/cxgb3/Kconfig"
 source "drivers/infiniband/hw/cxgb4/Kconfig"
 source "drivers/infiniband/hw/mlx4/Kconfig"
index 8f66c67ff0df09380dc7c486dce44d92efac1f18..87471ef371986c11f59e6761e7566ebec78cc1cd 100644 (file)
@@ -508,12 +508,12 @@ void ib_cache_gid_set_default_gid(struct ib_device *ib_dev, u8 port,
        memset(&gid_attr, 0, sizeof(gid_attr));
        gid_attr.ndev = ndev;
 
+       mutex_lock(&table->lock);
        ix = find_gid(table, NULL, NULL, true, GID_ATTR_FIND_MASK_DEFAULT);
 
        /* Coudn't find default GID location */
        WARN_ON(ix < 0);
 
-       mutex_lock(&table->lock);
        if (!__ib_cache_gid_get(ib_dev, port, ix,
                                &current_gid, &current_gid_attr) &&
            mode == IB_CACHE_GID_DEFAULT_MODE_SET &&
index ea4db9c1d44fba56ea5798649f3744c78b148e87..4f918b929eca955532cd5dc0541bc842272a0a3b 100644 (file)
@@ -835,6 +835,11 @@ retest:
        case IB_CM_SIDR_REQ_RCVD:
                spin_unlock_irq(&cm_id_priv->lock);
                cm_reject_sidr_req(cm_id_priv, IB_SIDR_REJECT);
+               spin_lock_irq(&cm.lock);
+               if (!RB_EMPTY_NODE(&cm_id_priv->sidr_id_node))
+                       rb_erase(&cm_id_priv->sidr_id_node,
+                                &cm.remote_sidr_table);
+               spin_unlock_irq(&cm.lock);
                break;
        case IB_CM_REQ_SENT:
        case IB_CM_MRA_REQ_RCVD:
@@ -3172,7 +3177,10 @@ int ib_send_cm_sidr_rep(struct ib_cm_id *cm_id,
        spin_unlock_irqrestore(&cm_id_priv->lock, flags);
 
        spin_lock_irqsave(&cm.lock, flags);
-       rb_erase(&cm_id_priv->sidr_id_node, &cm.remote_sidr_table);
+       if (!RB_EMPTY_NODE(&cm_id_priv->sidr_id_node)) {
+               rb_erase(&cm_id_priv->sidr_id_node, &cm.remote_sidr_table);
+               RB_CLEAR_NODE(&cm_id_priv->sidr_id_node);
+       }
        spin_unlock_irqrestore(&cm.lock, flags);
        return 0;
 
index b1ab13f3e182bb520cc986512d11e9016ecf1362..36b12d560e17e5a862a2e37d1f56875b46425f4b 100644 (file)
@@ -1067,14 +1067,14 @@ static int cma_save_req_info(const struct ib_cm_event *ib_event,
                       sizeof(req->local_gid));
                req->has_gid    = true;
                req->service_id = req_param->primary_path->service_id;
-               req->pkey       = req_param->bth_pkey;
+               req->pkey       = be16_to_cpu(req_param->primary_path->pkey);
                break;
        case IB_CM_SIDR_REQ_RECEIVED:
                req->device     = sidr_param->listen_id->device;
                req->port       = sidr_param->port;
                req->has_gid    = false;
                req->service_id = sidr_param->service_id;
-               req->pkey       = sidr_param->bth_pkey;
+               req->pkey       = sidr_param->pkey;
                break;
        default:
                return -EINVAL;
@@ -1232,14 +1232,32 @@ static bool cma_match_private_data(struct rdma_id_private *id_priv,
        return true;
 }
 
+static bool cma_protocol_roce_dev_port(struct ib_device *device, int port_num)
+{
+       enum rdma_link_layer ll = rdma_port_get_link_layer(device, port_num);
+       enum rdma_transport_type transport =
+               rdma_node_get_transport(device->node_type);
+
+       return ll == IB_LINK_LAYER_ETHERNET && transport == RDMA_TRANSPORT_IB;
+}
+
+static bool cma_protocol_roce(const struct rdma_cm_id *id)
+{
+       struct ib_device *device = id->device;
+       const int port_num = id->port_num ?: rdma_start_port(device);
+
+       return cma_protocol_roce_dev_port(device, port_num);
+}
+
 static bool cma_match_net_dev(const struct rdma_id_private *id_priv,
                              const struct net_device *net_dev)
 {
        const struct rdma_addr *addr = &id_priv->id.route.addr;
 
        if (!net_dev)
-               /* This request is an AF_IB request */
-               return addr->src_addr.ss_family == AF_IB;
+               /* This request is an AF_IB request or a RoCE request */
+               return addr->src_addr.ss_family == AF_IB ||
+                      cma_protocol_roce(&id_priv->id);
 
        return !addr->dev_addr.bound_dev_if ||
               (net_eq(dev_net(net_dev), &init_net) &&
@@ -1294,6 +1312,10 @@ static struct rdma_id_private *cma_id_from_event(struct ib_cm_id *cm_id,
                if (PTR_ERR(*net_dev) == -EAFNOSUPPORT) {
                        /* Assuming the protocol is AF_IB */
                        *net_dev = NULL;
+               } else if (cma_protocol_roce_dev_port(req.device, req.port)) {
+                       /* TODO find the net dev matching the request parameters
+                        * through the RoCE GID table */
+                       *net_dev = NULL;
                } else {
                        return ERR_CAST(*net_dev);
                }
@@ -1302,7 +1324,7 @@ static struct rdma_id_private *cma_id_from_event(struct ib_cm_id *cm_id,
        bind_list = cma_ps_find(rdma_ps_from_service_id(req.service_id),
                                cma_port_from_service_id(req.service_id));
        id_priv = cma_find_listener(bind_list, cm_id, ib_event, &req, *net_dev);
-       if (IS_ERR(id_priv)) {
+       if (IS_ERR(id_priv) && *net_dev) {
                dev_put(*net_dev);
                *net_dev = NULL;
        }
@@ -1593,11 +1615,16 @@ static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id,
                if (ret)
                        goto err;
        } else {
-               /* An AF_IB connection */
-               WARN_ON_ONCE(ss_family != AF_IB);
-
-               cma_translate_ib((struct sockaddr_ib *)cma_src_addr(id_priv),
-                                &rt->addr.dev_addr);
+               if (!cma_protocol_roce(listen_id) &&
+                   cma_any_addr(cma_src_addr(id_priv))) {
+                       rt->addr.dev_addr.dev_type = ARPHRD_INFINIBAND;
+                       rdma_addr_set_sgid(&rt->addr.dev_addr, &rt->path_rec[0].sgid);
+                       ib_addr_set_pkey(&rt->addr.dev_addr, be16_to_cpu(rt->path_rec[0].pkey));
+               } else if (!cma_any_addr(cma_src_addr(id_priv))) {
+                       ret = cma_translate_addr(cma_src_addr(id_priv), &rt->addr.dev_addr);
+                       if (ret)
+                               goto err;
+               }
        }
        rdma_addr_set_dgid(&rt->addr.dev_addr, &rt->path_rec[0].dgid);
 
@@ -1635,13 +1662,12 @@ static struct rdma_id_private *cma_new_udp_id(struct rdma_cm_id *listen_id,
                if (ret)
                        goto err;
        } else {
-               /* An AF_IB connection */
-               WARN_ON_ONCE(ss_family != AF_IB);
-
-               if (!cma_any_addr(cma_src_addr(id_priv)))
-                       cma_translate_ib((struct sockaddr_ib *)
-                                               cma_src_addr(id_priv),
-                                        &id->route.addr.dev_addr);
+               if (!cma_any_addr(cma_src_addr(id_priv))) {
+                       ret = cma_translate_addr(cma_src_addr(id_priv),
+                                                &id->route.addr.dev_addr);
+                       if (ret)
+                               goto err;
+               }
        }
 
        id_priv->state = RDMA_CM_CONNECT;
index 6b24cba1e474df33002186275fb2a7ca81c83717..178f98482e13e217c16d447978a855a900808bc0 100644 (file)
@@ -250,25 +250,44 @@ static void enum_netdev_ipv4_ips(struct ib_device *ib_dev,
                                 u8 port, struct net_device *ndev)
 {
        struct in_device *in_dev;
+       struct sin_list {
+               struct list_head        list;
+               struct sockaddr_in      ip;
+       };
+       struct sin_list *sin_iter;
+       struct sin_list *sin_temp;
 
+       LIST_HEAD(sin_list);
        if (ndev->reg_state >= NETREG_UNREGISTERING)
                return;
 
-       in_dev = in_dev_get(ndev);
-       if (!in_dev)
+       rcu_read_lock();
+       in_dev = __in_dev_get_rcu(ndev);
+       if (!in_dev) {
+               rcu_read_unlock();
                return;
+       }
 
        for_ifa(in_dev) {
-               struct sockaddr_in ip;
+               struct sin_list *entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
 
-               ip.sin_family = AF_INET;
-               ip.sin_addr.s_addr = ifa->ifa_address;
-               update_gid_ip(GID_ADD, ib_dev, port, ndev,
-                             (struct sockaddr *)&ip);
+               if (!entry) {
+                       pr_warn("roce_gid_mgmt: couldn't allocate entry for IPv4 update\n");
+                       continue;
+               }
+               entry->ip.sin_family = AF_INET;
+               entry->ip.sin_addr.s_addr = ifa->ifa_address;
+               list_add_tail(&entry->list, &sin_list);
        }
        endfor_ifa(in_dev);
+       rcu_read_unlock();
 
-       in_dev_put(in_dev);
+       list_for_each_entry_safe(sin_iter, sin_temp, &sin_list, list) {
+               update_gid_ip(GID_ADD, ib_dev, port, ndev,
+                             (struct sockaddr *)&sin_iter->ip);
+               list_del(&sin_iter->list);
+               kfree(sin_iter);
+       }
 }
 
 static void enum_netdev_ipv6_ips(struct ib_device *ib_dev,
index a53fc9b01c69957cb6d45433c4a34a0a69a5c367..30467d10df91b170e40657864354356153545e76 100644 (file)
@@ -1624,11 +1624,16 @@ static int ucma_open(struct inode *inode, struct file *filp)
        if (!file)
                return -ENOMEM;
 
+       file->close_wq = create_singlethread_workqueue("ucma_close_id");
+       if (!file->close_wq) {
+               kfree(file);
+               return -ENOMEM;
+       }
+
        INIT_LIST_HEAD(&file->event_list);
        INIT_LIST_HEAD(&file->ctx_list);
        init_waitqueue_head(&file->poll_wait);
        mutex_init(&file->mut);
-       file->close_wq = create_singlethread_workqueue("ucma_close_id");
 
        filp->private_data = file;
        file->filp = filp;
index 1bdb9996d371b5e3eefbb57958f265e71e3743f7..aded2a5cc2d5d677cabe42707704119e68116c5d 100644 (file)
@@ -1,6 +1,5 @@
 obj-$(CONFIG_INFINIBAND_MTHCA)         += mthca/
 obj-$(CONFIG_INFINIBAND_QIB)           += qib/
-obj-$(CONFIG_INFINIBAND_EHCA)          += ehca/
 obj-$(CONFIG_INFINIBAND_CXGB3)         += cxgb3/
 obj-$(CONFIG_INFINIBAND_CXGB4)         += cxgb4/
 obj-$(CONFIG_MLX4_INFINIBAND)          += mlx4/
diff --git a/drivers/infiniband/hw/ehca/Kconfig b/drivers/infiniband/hw/ehca/Kconfig
deleted file mode 100644 (file)
index 59f807d..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-config INFINIBAND_EHCA
-       tristate "eHCA support"
-       depends on IBMEBUS
-       ---help---
-       This driver supports the IBM pSeries eHCA InfiniBand adapter.
-
-       To compile the driver as a module, choose M here. The module
-       will be called ib_ehca.
-
diff --git a/drivers/infiniband/hw/ehca/Makefile b/drivers/infiniband/hw/ehca/Makefile
deleted file mode 100644 (file)
index 74d284e..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#  Authors: Heiko J Schick <schickhj@de.ibm.com>
-#           Christoph Raisch <raisch@de.ibm.com>
-#           Joachim Fenkes <fenkes@de.ibm.com>
-#
-#  Copyright (c) 2005 IBM Corporation
-#
-#  All rights reserved.
-#
-#  This source code is distributed under a dual license of GPL v2.0 and OpenIB BSD.
-
-obj-$(CONFIG_INFINIBAND_EHCA) += ib_ehca.o
-
-ib_ehca-objs  = ehca_main.o ehca_hca.o ehca_mcast.o ehca_pd.o ehca_av.o ehca_eq.o \
-               ehca_cq.o ehca_qp.o ehca_sqp.o ehca_mrmw.o ehca_reqs.o ehca_irq.o \
-               ehca_uverbs.o ipz_pt_fn.o hcp_if.o hcp_phyp.o
-
diff --git a/drivers/infiniband/hw/ehca/ehca_av.c b/drivers/infiniband/hw/ehca/ehca_av.c
deleted file mode 100644 (file)
index 4659263..0000000
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- *  IBM eServer eHCA Infiniband device driver for Linux on POWER
- *
- *  address vector functions
- *
- *  Authors: Hoang-Nam Nguyen <hnguyen@de.ibm.com>
- *           Khadija Souissi <souissik@de.ibm.com>
- *           Reinhard Ernst <rernst@de.ibm.com>
- *           Christoph Raisch <raisch@de.ibm.com>
- *
- *  Copyright (c) 2005 IBM Corporation
- *
- *  All rights reserved.
- *
- *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
- *  BSD.
- *
- * OpenIB BSD License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <linux/slab.h>
-
-#include "ehca_tools.h"
-#include "ehca_iverbs.h"
-#include "hcp_if.h"
-
-static struct kmem_cache *av_cache;
-
-int ehca_calc_ipd(struct ehca_shca *shca, int port,
-                 enum ib_rate path_rate, u32 *ipd)
-{
-       int path = ib_rate_to_mult(path_rate);
-       int link, ret;
-       struct ib_port_attr pa;
-
-       if (path_rate == IB_RATE_PORT_CURRENT) {
-               *ipd = 0;
-               return 0;
-       }
-
-       if (unlikely(path < 0)) {
-               ehca_err(&shca->ib_device, "Invalid static rate! path_rate=%x",
-                        path_rate);
-               return -EINVAL;
-       }
-
-       ret = ehca_query_port(&shca->ib_device, port, &pa);
-       if (unlikely(ret < 0)) {
-               ehca_err(&shca->ib_device, "Failed to query port  ret=%i", ret);
-               return ret;
-       }
-
-       link = ib_width_enum_to_int(pa.active_width) * pa.active_speed;
-
-       if (path >= link)
-               /* no need to throttle if path faster than link */
-               *ipd = 0;
-       else
-               /* IPD = round((link / path) - 1) */
-               *ipd = ((link + (path >> 1)) / path) - 1;
-
-       return 0;
-}
-
-struct ib_ah *ehca_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
-{
-       int ret;
-       struct ehca_av *av;
-       struct ehca_shca *shca = container_of(pd->device, struct ehca_shca,
-                                             ib_device);
-
-       av = kmem_cache_alloc(av_cache, GFP_KERNEL);
-       if (!av) {
-               ehca_err(pd->device, "Out of memory pd=%p ah_attr=%p",
-                        pd, ah_attr);
-               return ERR_PTR(-ENOMEM);
-       }
-
-       av->av.sl = ah_attr->sl;
-       av->av.dlid = ah_attr->dlid;
-       av->av.slid_path_bits = ah_attr->src_path_bits;
-
-       if (ehca_static_rate < 0) {
-               u32 ipd;
-               if (ehca_calc_ipd(shca, ah_attr->port_num,
-                                 ah_attr->static_rate, &ipd)) {
-                       ret = -EINVAL;
-                       goto create_ah_exit1;
-               }
-               av->av.ipd = ipd;
-       } else
-               av->av.ipd = ehca_static_rate;
-
-       av->av.lnh = ah_attr->ah_flags;
-       av->av.grh.word_0 = EHCA_BMASK_SET(GRH_IPVERSION_MASK, 6);
-       av->av.grh.word_0 |= EHCA_BMASK_SET(GRH_TCLASS_MASK,
-                                           ah_attr->grh.traffic_class);
-       av->av.grh.word_0 |= EHCA_BMASK_SET(GRH_FLOWLABEL_MASK,
-                                           ah_attr->grh.flow_label);
-       av->av.grh.word_0 |= EHCA_BMASK_SET(GRH_HOPLIMIT_MASK,
-                                           ah_attr->grh.hop_limit);
-       av->av.grh.word_0 |= EHCA_BMASK_SET(GRH_NEXTHEADER_MASK, 0x1B);
-       /* set sgid in grh.word_1 */
-       if (ah_attr->ah_flags & IB_AH_GRH) {
-               int rc;
-               struct ib_port_attr port_attr;
-               union ib_gid gid;
-               memset(&port_attr, 0, sizeof(port_attr));
-               rc = ehca_query_port(pd->device, ah_attr->port_num,
-                                    &port_attr);
-               if (rc) { /* invalid port number */
-                       ret = -EINVAL;
-                       ehca_err(pd->device, "Invalid port number "
-                                "ehca_query_port() returned %x "
-                                "pd=%p ah_attr=%p", rc, pd, ah_attr);
-                       goto create_ah_exit1;
-               }
-               memset(&gid, 0, sizeof(gid));
-               rc = ehca_query_gid(pd->device,
-                                   ah_attr->port_num,
-                                   ah_attr->grh.sgid_index, &gid);
-               if (rc) {
-                       ret = -EINVAL;
-                       ehca_err(pd->device, "Failed to retrieve sgid "
-                                "ehca_query_gid() returned %x "
-                                "pd=%p ah_attr=%p", rc, pd, ah_attr);
-                       goto create_ah_exit1;
-               }
-               memcpy(&av->av.grh.word_1, &gid, sizeof(gid));
-       }
-       av->av.pmtu = shca->max_mtu;
-
-       /* dgid comes in grh.word_3 */
-       memcpy(&av->av.grh.word_3, &ah_attr->grh.dgid,
-              sizeof(ah_attr->grh.dgid));
-
-       return &av->ib_ah;
-
-create_ah_exit1:
-       kmem_cache_free(av_cache, av);
-
-       return ERR_PTR(ret);
-}
-
-int ehca_modify_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr)
-{
-       struct ehca_av *av;
-       struct ehca_ud_av new_ehca_av;
-       struct ehca_shca *shca = container_of(ah->pd->device, struct ehca_shca,
-                                             ib_device);
-
-       memset(&new_ehca_av, 0, sizeof(new_ehca_av));
-       new_ehca_av.sl = ah_attr->sl;
-       new_ehca_av.dlid = ah_attr->dlid;
-       new_ehca_av.slid_path_bits = ah_attr->src_path_bits;
-       new_ehca_av.ipd = ah_attr->static_rate;
-       new_ehca_av.lnh = EHCA_BMASK_SET(GRH_FLAG_MASK,
-                                        (ah_attr->ah_flags & IB_AH_GRH) > 0);
-       new_ehca_av.grh.word_0 = EHCA_BMASK_SET(GRH_TCLASS_MASK,
-                                               ah_attr->grh.traffic_class);
-       new_ehca_av.grh.word_0 |= EHCA_BMASK_SET(GRH_FLOWLABEL_MASK,
-                                                ah_attr->grh.flow_label);
-       new_ehca_av.grh.word_0 |= EHCA_BMASK_SET(GRH_HOPLIMIT_MASK,
-                                                ah_attr->grh.hop_limit);
-       new_ehca_av.grh.word_0 |= EHCA_BMASK_SET(GRH_NEXTHEADER_MASK, 0x1b);
-
-       /* set sgid in grh.word_1 */
-       if (ah_attr->ah_flags & IB_AH_GRH) {
-               int rc;
-               struct ib_port_attr port_attr;
-               union ib_gid gid;
-               memset(&port_attr, 0, sizeof(port_attr));
-               rc = ehca_query_port(ah->device, ah_attr->port_num,
-                                    &port_attr);
-               if (rc) { /* invalid port number */
-                       ehca_err(ah->device, "Invalid port number "
-                                "ehca_query_port() returned %x "
-                                "ah=%p ah_attr=%p port_num=%x",
-                                rc, ah, ah_attr, ah_attr->port_num);
-                       return -EINVAL;
-               }
-               memset(&gid, 0, sizeof(gid));
-               rc = ehca_query_gid(ah->device,
-                                   ah_attr->port_num,
-                                   ah_attr->grh.sgid_index, &gid);
-               if (rc) {
-                       ehca_err(ah->device, "Failed to retrieve sgid "
-                                "ehca_query_gid() returned %x "
-                                "ah=%p ah_attr=%p port_num=%x "
-                                "sgid_index=%x",
-                                rc, ah, ah_attr, ah_attr->port_num,
-                                ah_attr->grh.sgid_index);
-                       return -EINVAL;
-               }
-               memcpy(&new_ehca_av.grh.word_1, &gid, sizeof(gid));
-       }
-
-       new_ehca_av.pmtu = shca->max_mtu;
-
-       memcpy(&new_ehca_av.grh.word_3, &ah_attr->grh.dgid,
-              sizeof(ah_attr->grh.dgid));
-
-       av = container_of(ah, struct ehca_av, ib_ah);
-       av->av = new_ehca_av;
-
-       return 0;
-}
-
-int ehca_query_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr)
-{
-       struct ehca_av *av = container_of(ah, struct ehca_av, ib_ah);
-
-       memcpy(&ah_attr->grh.dgid, &av->av.grh.word_3,
-              sizeof(ah_attr->grh.dgid));
-       ah_attr->sl = av->av.sl;
-
-       ah_attr->dlid = av->av.dlid;
-
-       ah_attr->src_path_bits = av->av.slid_path_bits;
-       ah_attr->static_rate = av->av.ipd;
-       ah_attr->ah_flags = EHCA_BMASK_GET(GRH_FLAG_MASK, av->av.lnh);
-       ah_attr->grh.traffic_class = EHCA_BMASK_GET(GRH_TCLASS_MASK,
-                                                   av->av.grh.word_0);
-       ah_attr->grh.hop_limit = EHCA_BMASK_GET(GRH_HOPLIMIT_MASK,
-                                               av->av.grh.word_0);
-       ah_attr->grh.flow_label = EHCA_BMASK_GET(GRH_FLOWLABEL_MASK,
-                                                av->av.grh.word_0);
-
-       return 0;
-}
-
-int ehca_destroy_ah(struct ib_ah *ah)
-{
-       kmem_cache_free(av_cache, container_of(ah, struct ehca_av, ib_ah));
-
-       return 0;
-}
-
-int ehca_init_av_cache(void)
-{
-       av_cache = kmem_cache_create("ehca_cache_av",
-                                  sizeof(struct ehca_av), 0,
-                                  SLAB_HWCACHE_ALIGN,
-                                  NULL);
-       if (!av_cache)
-               return -ENOMEM;
-       return 0;
-}
-
-void ehca_cleanup_av_cache(void)
-{
-       if (av_cache)
-               kmem_cache_destroy(av_cache);
-}
diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
deleted file mode 100644 (file)
index bd45e0f..0000000
+++ /dev/null
@@ -1,482 +0,0 @@
-/*
- *  IBM eServer eHCA Infiniband device driver for Linux on POWER
- *
- *  Struct definition for eHCA internal structures
- *
- *  Authors: Heiko J Schick <schickhj@de.ibm.com>
- *           Christoph Raisch <raisch@de.ibm.com>
- *           Joachim Fenkes <fenkes@de.ibm.com>
- *
- *  Copyright (c) 2005 IBM Corporation
- *
- *  All rights reserved.
- *
- *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
- *  BSD.
- *
- * OpenIB BSD License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __EHCA_CLASSES_H__
-#define __EHCA_CLASSES_H__
-
-struct ehca_module;
-struct ehca_qp;
-struct ehca_cq;
-struct ehca_eq;
-struct ehca_mr;
-struct ehca_mw;
-struct ehca_pd;
-struct ehca_av;
-
-#include <linux/wait.h>
-#include <linux/mutex.h>
-
-#include <rdma/ib_verbs.h>
-#include <rdma/ib_user_verbs.h>
-
-#ifdef CONFIG_PPC64
-#include "ehca_classes_pSeries.h"
-#endif
-#include "ipz_pt_fn.h"
-#include "ehca_qes.h"
-#include "ehca_irq.h"
-
-#define EHCA_EQE_CACHE_SIZE 20
-#define EHCA_MAX_NUM_QUEUES 0xffff
-
-struct ehca_eqe_cache_entry {
-       struct ehca_eqe *eqe;
-       struct ehca_cq *cq;
-};
-
-struct ehca_eq {
-       u32 length;
-       struct ipz_queue ipz_queue;
-       struct ipz_eq_handle ipz_eq_handle;
-       struct work_struct work;
-       struct h_galpas galpas;
-       int is_initialized;
-       struct ehca_pfeq pf;
-       spinlock_t spinlock;
-       struct tasklet_struct interrupt_task;
-       u32 ist;
-       spinlock_t irq_spinlock;
-       struct ehca_eqe_cache_entry eqe_cache[EHCA_EQE_CACHE_SIZE];
-};
-
-struct ehca_sma_attr {
-       u16 lid, lmc, sm_sl, sm_lid;
-       u16 pkey_tbl_len, pkeys[16];
-};
-
-struct ehca_sport {
-       struct ib_cq *ibcq_aqp1;
-       struct ib_qp *ibqp_sqp[2];
-       /* lock to serialze modify_qp() calls for sqp in normal
-        * and irq path (when event PORT_ACTIVE is received first time)
-        */
-       spinlock_t mod_sqp_lock;
-       enum ib_port_state port_state;
-       struct ehca_sma_attr saved_attr;
-       u32 pma_qp_nr;
-};
-
-#define HCA_CAP_MR_PGSIZE_4K  0x80000000
-#define HCA_CAP_MR_PGSIZE_64K 0x40000000
-#define HCA_CAP_MR_PGSIZE_1M  0x20000000
-#define HCA_CAP_MR_PGSIZE_16M 0x10000000
-
-struct ehca_shca {
-       struct ib_device ib_device;
-       struct platform_device *ofdev;
-       u8 num_ports;
-       int hw_level;
-       struct list_head shca_list;
-       struct ipz_adapter_handle ipz_hca_handle;
-       struct ehca_sport sport[2];
-       struct ehca_eq eq;
-       struct ehca_eq neq;
-       struct ehca_mr *maxmr;
-       struct ehca_pd *pd;
-       struct h_galpas galpas;
-       struct mutex modify_mutex;
-       u64 hca_cap;
-       /* MR pgsize: bit 0-3 means 4K, 64K, 1M, 16M respectively */
-       u32 hca_cap_mr_pgsize;
-       int max_mtu;
-       int max_num_qps;
-       int max_num_cqs;
-       atomic_t num_cqs;
-       atomic_t num_qps;
-};
-
-struct ehca_pd {
-       struct ib_pd ib_pd;
-       struct ipz_pd fw_pd;
-       /* small queue mgmt */
-       struct mutex lock;
-       struct list_head free[2];
-       struct list_head full[2];
-};
-
-enum ehca_ext_qp_type {
-       EQPT_NORMAL    = 0,
-       EQPT_LLQP      = 1,
-       EQPT_SRQBASE   = 2,
-       EQPT_SRQ       = 3,
-};
-
-/* struct to cache modify_qp()'s parms for GSI/SMI qp */
-struct ehca_mod_qp_parm {
-       int mask;
-       struct ib_qp_attr attr;
-};
-
-#define EHCA_MOD_QP_PARM_MAX 4
-
-#define QMAP_IDX_MASK 0xFFFFULL
-
-/* struct for tracking if cqes have been reported to the application */
-struct ehca_qmap_entry {
-       u16 app_wr_id;
-       u8 reported;
-       u8 cqe_req;
-};
-
-struct ehca_queue_map {
-       struct ehca_qmap_entry *map;
-       unsigned int entries;
-       unsigned int tail;
-       unsigned int left_to_poll;
-       unsigned int next_wqe_idx;   /* Idx to first wqe to be flushed */
-};
-
-/* function to calculate the next index for the qmap */
-static inline unsigned int next_index(unsigned int cur_index, unsigned int limit)
-{
-       unsigned int temp = cur_index + 1;
-       return (temp == limit) ? 0 : temp;
-}
-
-struct ehca_qp {
-       union {
-               struct ib_qp ib_qp;
-               struct ib_srq ib_srq;
-       };
-       u32 qp_type;
-       enum ehca_ext_qp_type ext_type;
-       enum ib_qp_state state;
-       struct ipz_queue ipz_squeue;
-       struct ehca_queue_map sq_map;
-       struct ipz_queue ipz_rqueue;
-       struct ehca_queue_map rq_map;
-       struct h_galpas galpas;
-       u32 qkey;
-       u32 real_qp_num;
-       u32 token;
-       spinlock_t spinlock_s;
-       spinlock_t spinlock_r;
-       u32 sq_max_inline_data_size;
-       struct ipz_qp_handle ipz_qp_handle;
-       struct ehca_pfqp pf;
-       struct ib_qp_init_attr init_attr;
-       struct ehca_cq *send_cq;
-       struct ehca_cq *recv_cq;
-       unsigned int sqerr_purgeflag;
-       struct hlist_node list_entries;
-       /* array to cache modify_qp()'s parms for GSI/SMI qp */
-       struct ehca_mod_qp_parm *mod_qp_parm;
-       int mod_qp_parm_idx;
-       /* mmap counter for resources mapped into user space */
-       u32 mm_count_squeue;
-       u32 mm_count_rqueue;
-       u32 mm_count_galpa;
-       /* unsolicited ack circumvention */
-       int unsol_ack_circ;
-       int mtu_shift;
-       u32 message_count;
-       u32 packet_count;
-       atomic_t nr_events; /* events seen */
-       wait_queue_head_t wait_completion;
-       int mig_armed;
-       struct list_head sq_err_node;
-       struct list_head rq_err_node;
-};
-
-#define IS_SRQ(qp) (qp->ext_type == EQPT_SRQ)
-#define HAS_SQ(qp) (qp->ext_type != EQPT_SRQ)
-#define HAS_RQ(qp) (qp->ext_type != EQPT_SRQBASE)
-
-/* must be power of 2 */
-#define QP_HASHTAB_LEN 8
-
-struct ehca_cq {
-       struct ib_cq ib_cq;
-       struct ipz_queue ipz_queue;
-       struct h_galpas galpas;
-       spinlock_t spinlock;
-       u32 cq_number;
-       u32 token;
-       u32 nr_of_entries;
-       struct ipz_cq_handle ipz_cq_handle;
-       struct ehca_pfcq pf;
-       spinlock_t cb_lock;
-       struct hlist_head qp_hashtab[QP_HASHTAB_LEN];
-       struct list_head entry;
-       u32 nr_callbacks;   /* #events assigned to cpu by scaling code */
-       atomic_t nr_events; /* #events seen */
-       wait_queue_head_t wait_completion;
-       spinlock_t task_lock;
-       /* mmap counter for resources mapped into user space */
-       u32 mm_count_queue;
-       u32 mm_count_galpa;
-       struct list_head sqp_err_list;
-       struct list_head rqp_err_list;
-};
-
-enum ehca_mr_flag {
-       EHCA_MR_FLAG_FMR = 0x80000000,   /* FMR, created with ehca_alloc_fmr */
-       EHCA_MR_FLAG_MAXMR = 0x40000000, /* max-MR                           */
-};
-
-struct ehca_mr {
-       union {
-               struct ib_mr ib_mr;     /* must always be first in ehca_mr */
-               struct ib_fmr ib_fmr;   /* must always be first in ehca_mr */
-       } ib;
-       struct ib_umem *umem;
-       spinlock_t mrlock;
-
-       enum ehca_mr_flag flags;
-       u32 num_kpages;         /* number of kernel pages */
-       u32 num_hwpages;        /* number of hw pages to form MR */
-       u64 hwpage_size;        /* hw page size used for this MR */
-       int acl;                /* ACL (stored here for usage in reregister) */
-       u64 *start;             /* virtual start address (stored here for */
-                               /* usage in reregister) */
-       u64 size;               /* size (stored here for usage in reregister) */
-       u32 fmr_page_size;      /* page size for FMR */
-       u32 fmr_max_pages;      /* max pages for FMR */
-       u32 fmr_max_maps;       /* max outstanding maps for FMR */
-       u32 fmr_map_cnt;        /* map counter for FMR */
-       /* fw specific data */
-       struct ipz_mrmw_handle ipz_mr_handle;   /* MR handle for h-calls */
-       struct h_galpas galpas;
-};
-
-struct ehca_mw {
-       struct ib_mw ib_mw;     /* gen2 mw, must always be first in ehca_mw */
-       spinlock_t mwlock;
-
-       u8 never_bound;         /* indication MW was never bound */
-       struct ipz_mrmw_handle ipz_mw_handle;   /* MW handle for h-calls */
-       struct h_galpas galpas;
-};
-
-enum ehca_mr_pgi_type {
-       EHCA_MR_PGI_PHYS   = 1,  /* type of ehca_reg_phys_mr,
-                                 * ehca_rereg_phys_mr,
-                                 * ehca_reg_internal_maxmr */
-       EHCA_MR_PGI_USER   = 2,  /* type of ehca_reg_user_mr */
-       EHCA_MR_PGI_FMR    = 3   /* type of ehca_map_phys_fmr */
-};
-
-struct ehca_mr_pginfo {
-       enum ehca_mr_pgi_type type;
-       u64 num_kpages;
-       u64 kpage_cnt;
-       u64 hwpage_size;     /* hw page size used for this MR */
-       u64 num_hwpages;     /* number of hw pages */
-       u64 hwpage_cnt;      /* counter for hw pages */
-       u64 next_hwpage;     /* next hw page in buffer/chunk/listelem */
-
-       union {
-               struct { /* type EHCA_MR_PGI_PHYS section */
-                       int num_phys_buf;
-                       struct ib_phys_buf *phys_buf_array;
-                       u64 next_buf;
-               } phy;
-               struct { /* type EHCA_MR_PGI_USER section */
-                       struct ib_umem *region;
-                       struct scatterlist *next_sg;
-                       u64 next_nmap;
-               } usr;
-               struct { /* type EHCA_MR_PGI_FMR section */
-                       u64 fmr_pgsize;
-                       u64 *page_list;
-                       u64 next_listelem;
-               } fmr;
-       } u;
-};
-
-/* output parameters for MR/FMR hipz calls */
-struct ehca_mr_hipzout_parms {
-       struct ipz_mrmw_handle handle;
-       u32 lkey;
-       u32 rkey;
-       u64 len;
-       u64 vaddr;
-       u32 acl;
-};
-
-/* output parameters for MW hipz calls */
-struct ehca_mw_hipzout_parms {
-       struct ipz_mrmw_handle handle;
-       u32 rkey;
-};
-
-struct ehca_av {
-       struct ib_ah ib_ah;
-       struct ehca_ud_av av;
-};
-
-struct ehca_ucontext {
-       struct ib_ucontext ib_ucontext;
-};
-
-int ehca_init_pd_cache(void);
-void ehca_cleanup_pd_cache(void);
-int ehca_init_cq_cache(void);
-void ehca_cleanup_cq_cache(void);
-int ehca_init_qp_cache(void);
-void ehca_cleanup_qp_cache(void);
-int ehca_init_av_cache(void);
-void ehca_cleanup_av_cache(void);
-int ehca_init_mrmw_cache(void);
-void ehca_cleanup_mrmw_cache(void);
-int ehca_init_small_qp_cache(void);
-void ehca_cleanup_small_qp_cache(void);
-
-extern rwlock_t ehca_qp_idr_lock;
-extern rwlock_t ehca_cq_idr_lock;
-extern struct idr ehca_qp_idr;
-extern struct idr ehca_cq_idr;
-extern spinlock_t shca_list_lock;
-
-extern int ehca_static_rate;
-extern int ehca_port_act_time;
-extern bool ehca_use_hp_mr;
-extern bool ehca_scaling_code;
-extern int ehca_lock_hcalls;
-extern int ehca_nr_ports;
-extern int ehca_max_cq;
-extern int ehca_max_qp;
-
-struct ipzu_queue_resp {
-       u32 qe_size;      /* queue entry size */
-       u32 act_nr_of_sg;
-       u32 queue_length; /* queue length allocated in bytes */
-       u32 pagesize;
-       u32 toggle_state;
-       u32 offset; /* save offset within a page for small_qp */
-};
-
-struct ehca_create_cq_resp {
-       u32 cq_number;
-       u32 token;
-       struct ipzu_queue_resp ipz_queue;
-       u32 fw_handle_ofs;
-       u32 dummy;
-};
-
-struct ehca_create_qp_resp {
-       u32 qp_num;
-       u32 token;
-       u32 qp_type;
-       u32 ext_type;
-       u32 qkey;
-       /* qp_num assigned by ehca: sqp0/1 may have got different numbers */
-       u32 real_qp_num;
-       u32 fw_handle_ofs;
-       u32 dummy;
-       struct ipzu_queue_resp ipz_squeue;
-       struct ipzu_queue_resp ipz_rqueue;
-};
-
-struct ehca_alloc_cq_parms {
-       u32 nr_cqe;
-       u32 act_nr_of_entries;
-       u32 act_pages;
-       struct ipz_eq_handle eq_handle;
-};
-
-enum ehca_service_type {
-       ST_RC  = 0,
-       ST_UC  = 1,
-       ST_RD  = 2,
-       ST_UD  = 3,
-};
-
-enum ehca_ll_comp_flags {
-       LLQP_SEND_COMP = 0x20,
-       LLQP_RECV_COMP = 0x40,
-       LLQP_COMP_MASK = 0x60,
-};
-
-struct ehca_alloc_queue_parms {
-       /* input parameters */
-       int max_wr;
-       int max_sge;
-       int page_size;
-       int is_small;
-
-       /* output parameters */
-       u16 act_nr_wqes;
-       u8  act_nr_sges;
-       u32 queue_size; /* bytes for small queues, pages otherwise */
-};
-
-struct ehca_alloc_qp_parms {
-       struct ehca_alloc_queue_parms squeue;
-       struct ehca_alloc_queue_parms rqueue;
-
-       /* input parameters */
-       enum ehca_service_type servicetype;
-       int qp_storage;
-       int sigtype;
-       enum ehca_ext_qp_type ext_type;
-       enum ehca_ll_comp_flags ll_comp_flags;
-       int ud_av_l_key_ctl;
-
-       u32 token;
-       struct ipz_eq_handle eq_handle;
-       struct ipz_pd pd;
-       struct ipz_cq_handle send_cq_handle, recv_cq_handle;
-
-       u32 srq_qpn, srq_token, srq_limit;
-
-       /* output parameters */
-       u32 real_qp_num;
-       struct ipz_qp_handle qp_handle;
-       struct h_galpas galpas;
-};
-
-int ehca_cq_assign_qp(struct ehca_cq *cq, struct ehca_qp *qp);
-int ehca_cq_unassign_qp(struct ehca_cq *cq, unsigned int qp_num);
-struct ehca_qp *ehca_cq_get_qp(struct ehca_cq *cq, int qp_num);
-
-#endif
diff --git a/drivers/infiniband/hw/ehca/ehca_classes_pSeries.h b/drivers/infiniband/hw/ehca/ehca_classes_pSeries.h
deleted file mode 100644 (file)
index 689c357..0000000
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- *  IBM eServer eHCA Infiniband device driver for Linux on POWER
- *
- *  pSeries interface definitions
- *
- *  Authors: Waleri Fomin <fomin@de.ibm.com>
- *           Christoph Raisch <raisch@de.ibm.com>
- *
- *  Copyright (c) 2005 IBM Corporation
- *
- *  All rights reserved.
- *
- *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
- *  BSD.
- *
- * OpenIB BSD License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __EHCA_CLASSES_PSERIES_H__
-#define __EHCA_CLASSES_PSERIES_H__
-
-#include "hcp_phyp.h"
-#include "ipz_pt_fn.h"
-
-
-struct ehca_pfqp {
-       struct ipz_qpt sqpt;
-       struct ipz_qpt rqpt;
-};
-
-struct ehca_pfcq {
-       struct ipz_qpt qpt;
-       u32 cqnr;
-};
-
-struct ehca_pfeq {
-       struct ipz_qpt qpt;
-       struct h_galpa galpa;
-       u32 eqnr;
-};
-
-struct ipz_adapter_handle {
-       u64 handle;
-};
-
-struct ipz_cq_handle {
-       u64 handle;
-};
-
-struct ipz_eq_handle {
-       u64 handle;
-};
-
-struct ipz_qp_handle {
-       u64 handle;
-};
-struct ipz_mrmw_handle {
-       u64 handle;
-};
-
-struct ipz_pd {
-       u32 value;
-};
-
-struct hcp_modify_qp_control_block {
-       u32 qkey;                      /* 00 */
-       u32 rdd;                       /* reliable datagram domain */
-       u32 send_psn;                  /* 02 */
-       u32 receive_psn;               /* 03 */
-       u32 prim_phys_port;            /* 04 */
-       u32 alt_phys_port;             /* 05 */
-       u32 prim_p_key_idx;            /* 06 */
-       u32 alt_p_key_idx;             /* 07 */
-       u32 rdma_atomic_ctrl;          /* 08 */
-       u32 qp_state;                  /* 09 */
-       u32 reserved_10;               /* 10 */
-       u32 rdma_nr_atomic_resp_res;   /* 11 */
-       u32 path_migration_state;      /* 12 */
-       u32 rdma_atomic_outst_dest_qp; /* 13 */
-       u32 dest_qp_nr;                /* 14 */
-       u32 min_rnr_nak_timer_field;   /* 15 */
-       u32 service_level;             /* 16 */
-       u32 send_grh_flag;             /* 17 */
-       u32 retry_count;               /* 18 */
-       u32 timeout;                   /* 19 */
-       u32 path_mtu;                  /* 20 */
-       u32 max_static_rate;           /* 21 */
-       u32 dlid;                      /* 22 */
-       u32 rnr_retry_count;           /* 23 */
-       u32 source_path_bits;          /* 24 */
-       u32 traffic_class;             /* 25 */
-       u32 hop_limit;                 /* 26 */
-       u32 source_gid_idx;            /* 27 */
-       u32 flow_label;                /* 28 */
-       u32 reserved_29;               /* 29 */
-       union {                        /* 30 */
-               u64 dw[2];
-               u8 byte[16];
-       } dest_gid;
-       u32 service_level_al;          /* 34 */
-       u32 send_grh_flag_al;          /* 35 */
-       u32 retry_count_al;            /* 36 */
-       u32 timeout_al;                /* 37 */
-       u32 max_static_rate_al;        /* 38 */
-       u32 dlid_al;                   /* 39 */
-       u32 rnr_retry_count_al;        /* 40 */
-       u32 source_path_bits_al;       /* 41 */
-       u32 traffic_class_al;          /* 42 */
-       u32 hop_limit_al;              /* 43 */
-       u32 source_gid_idx_al;         /* 44 */
-       u32 flow_label_al;             /* 45 */
-       u32 reserved_46;               /* 46 */
-       u32 reserved_47;               /* 47 */
-       union {                        /* 48 */
-               u64 dw[2];
-               u8 byte[16];
-       } dest_gid_al;
-       u32 max_nr_outst_send_wr;      /* 52 */
-       u32 max_nr_outst_recv_wr;      /* 53 */
-       u32 disable_ete_credit_check;  /* 54 */
-       u32 qp_number;                 /* 55 */
-       u64 send_queue_handle;         /* 56 */
-       u64 recv_queue_handle;         /* 58 */
-       u32 actual_nr_sges_in_sq_wqe;  /* 60 */
-       u32 actual_nr_sges_in_rq_wqe;  /* 61 */
-       u32 qp_enable;                 /* 62 */
-       u32 curr_srq_limit;            /* 63 */
-       u64 qp_aff_asyn_ev_log_reg;    /* 64 */
-       u64 shared_rq_hndl;            /* 66 */
-       u64 trigg_doorbell_qp_hndl;    /* 68 */
-       u32 reserved_70_127[58];       /* 70 */
-};
-
-#define MQPCB_MASK_QKEY                         EHCA_BMASK_IBM( 0,  0)
-#define MQPCB_MASK_SEND_PSN                     EHCA_BMASK_IBM( 2,  2)
-#define MQPCB_MASK_RECEIVE_PSN                  EHCA_BMASK_IBM( 3,  3)
-#define MQPCB_MASK_PRIM_PHYS_PORT               EHCA_BMASK_IBM( 4,  4)
-#define MQPCB_PRIM_PHYS_PORT                    EHCA_BMASK_IBM(24, 31)
-#define MQPCB_MASK_ALT_PHYS_PORT                EHCA_BMASK_IBM( 5,  5)
-#define MQPCB_MASK_PRIM_P_KEY_IDX               EHCA_BMASK_IBM( 6,  6)
-#define MQPCB_PRIM_P_KEY_IDX                    EHCA_BMASK_IBM(24, 31)
-#define MQPCB_MASK_ALT_P_KEY_IDX                EHCA_BMASK_IBM( 7,  7)
-#define MQPCB_MASK_RDMA_ATOMIC_CTRL             EHCA_BMASK_IBM( 8,  8)
-#define MQPCB_MASK_QP_STATE                     EHCA_BMASK_IBM( 9,  9)
-#define MQPCB_MASK_RDMA_NR_ATOMIC_RESP_RES      EHCA_BMASK_IBM(11, 11)
-#define MQPCB_MASK_PATH_MIGRATION_STATE         EHCA_BMASK_IBM(12, 12)
-#define MQPCB_MASK_RDMA_ATOMIC_OUTST_DEST_QP    EHCA_BMASK_IBM(13, 13)
-#define MQPCB_MASK_DEST_QP_NR                   EHCA_BMASK_IBM(14, 14)
-#define MQPCB_MASK_MIN_RNR_NAK_TIMER_FIELD      EHCA_BMASK_IBM(15, 15)
-#define MQPCB_MASK_SERVICE_LEVEL                EHCA_BMASK_IBM(16, 16)
-#define MQPCB_MASK_SEND_GRH_FLAG                EHCA_BMASK_IBM(17, 17)
-#define MQPCB_MASK_RETRY_COUNT                  EHCA_BMASK_IBM(18, 18)
-#define MQPCB_MASK_TIMEOUT                      EHCA_BMASK_IBM(19, 19)
-#define MQPCB_MASK_PATH_MTU                     EHCA_BMASK_IBM(20, 20)
-#define MQPCB_MASK_MAX_STATIC_RATE              EHCA_BMASK_IBM(21, 21)
-#define MQPCB_MASK_DLID                         EHCA_BMASK_IBM(22, 22)
-#define MQPCB_MASK_RNR_RETRY_COUNT              EHCA_BMASK_IBM(23, 23)
-#define MQPCB_MASK_SOURCE_PATH_BITS             EHCA_BMASK_IBM(24, 24)
-#define MQPCB_MASK_TRAFFIC_CLASS                EHCA_BMASK_IBM(25, 25)
-#define MQPCB_MASK_HOP_LIMIT                    EHCA_BMASK_IBM(26, 26)
-#define MQPCB_MASK_SOURCE_GID_IDX               EHCA_BMASK_IBM(27, 27)
-#define MQPCB_MASK_FLOW_LABEL                   EHCA_BMASK_IBM(28, 28)
-#define MQPCB_MASK_DEST_GID                     EHCA_BMASK_IBM(30, 30)
-#define MQPCB_MASK_SERVICE_LEVEL_AL             EHCA_BMASK_IBM(31, 31)
-#define MQPCB_MASK_SEND_GRH_FLAG_AL             EHCA_BMASK_IBM(32, 32)
-#define MQPCB_MASK_RETRY_COUNT_AL               EHCA_BMASK_IBM(33, 33)
-#define MQPCB_MASK_TIMEOUT_AL                   EHCA_BMASK_IBM(34, 34)
-#define MQPCB_MASK_MAX_STATIC_RATE_AL           EHCA_BMASK_IBM(35, 35)
-#define MQPCB_MASK_DLID_AL                      EHCA_BMASK_IBM(36, 36)
-#define MQPCB_MASK_RNR_RETRY_COUNT_AL           EHCA_BMASK_IBM(37, 37)
-#define MQPCB_MASK_SOURCE_PATH_BITS_AL          EHCA_BMASK_IBM(38, 38)
-#define MQPCB_MASK_TRAFFIC_CLASS_AL             EHCA_BMASK_IBM(39, 39)
-#define MQPCB_MASK_HOP_LIMIT_AL                 EHCA_BMASK_IBM(40, 40)
-#define MQPCB_MASK_SOURCE_GID_IDX_AL            EHCA_BMASK_IBM(41, 41)
-#define MQPCB_MASK_FLOW_LABEL_AL                EHCA_BMASK_IBM(42, 42)
-#define MQPCB_MASK_DEST_GID_AL                  EHCA_BMASK_IBM(44, 44)
-#define MQPCB_MASK_MAX_NR_OUTST_SEND_WR         EHCA_BMASK_IBM(45, 45)
-#define MQPCB_MASK_MAX_NR_OUTST_RECV_WR         EHCA_BMASK_IBM(46, 46)
-#define MQPCB_MASK_DISABLE_ETE_CREDIT_CHECK     EHCA_BMASK_IBM(47, 47)
-#define MQPCB_MASK_QP_ENABLE                    EHCA_BMASK_IBM(48, 48)
-#define MQPCB_MASK_CURR_SRQ_LIMIT               EHCA_BMASK_IBM(49, 49)
-#define MQPCB_MASK_QP_AFF_ASYN_EV_LOG_REG       EHCA_BMASK_IBM(50, 50)
-#define MQPCB_MASK_SHARED_RQ_HNDL               EHCA_BMASK_IBM(51, 51)
-
-#endif /* __EHCA_CLASSES_PSERIES_H__ */
diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c b/drivers/infiniband/hw/ehca/ehca_cq.c
deleted file mode 100644 (file)
index 9b68b17..0000000
+++ /dev/null
@@ -1,397 +0,0 @@
-/*
- *  IBM eServer eHCA Infiniband device driver for Linux on POWER
- *
- *  Completion queue handling
- *
- *  Authors: Waleri Fomin <fomin@de.ibm.com>
- *           Khadija Souissi <souissi@de.ibm.com>
- *           Reinhard Ernst <rernst@de.ibm.com>
- *           Heiko J Schick <schickhj@de.ibm.com>
- *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
- *
- *
- *  Copyright (c) 2005 IBM Corporation
- *
- *  All rights reserved.
- *
- *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
- *  BSD.
- *
- * OpenIB BSD License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <linux/slab.h>
-
-#include "ehca_iverbs.h"
-#include "ehca_classes.h"
-#include "ehca_irq.h"
-#include "hcp_if.h"
-
-static struct kmem_cache *cq_cache;
-
-int ehca_cq_assign_qp(struct ehca_cq *cq, struct ehca_qp *qp)
-{
-       unsigned int qp_num = qp->real_qp_num;
-       unsigned int key = qp_num & (QP_HASHTAB_LEN-1);
-       unsigned long flags;
-
-       spin_lock_irqsave(&cq->spinlock, flags);
-       hlist_add_head(&qp->list_entries, &cq->qp_hashtab[key]);
-       spin_unlock_irqrestore(&cq->spinlock, flags);
-
-       ehca_dbg(cq->ib_cq.device, "cq_num=%x real_qp_num=%x",
-                cq->cq_number, qp_num);
-
-       return 0;
-}
-
-int ehca_cq_unassign_qp(struct ehca_cq *cq, unsigned int real_qp_num)
-{
-       int ret = -EINVAL;
-       unsigned int key = real_qp_num & (QP_HASHTAB_LEN-1);
-       struct hlist_node *iter;
-       struct ehca_qp *qp;
-       unsigned long flags;
-
-       spin_lock_irqsave(&cq->spinlock, flags);
-       hlist_for_each(iter, &cq->qp_hashtab[key]) {
-               qp = hlist_entry(iter, struct ehca_qp, list_entries);
-               if (qp->real_qp_num == real_qp_num) {
-                       hlist_del(iter);
-                       ehca_dbg(cq->ib_cq.device,
-                                "removed qp from cq .cq_num=%x real_qp_num=%x",
-                                cq->cq_number, real_qp_num);
-                       ret = 0;
-                       break;
-               }
-       }
-       spin_unlock_irqrestore(&cq->spinlock, flags);
-       if (ret)
-               ehca_err(cq->ib_cq.device,
-                        "qp not found cq_num=%x real_qp_num=%x",
-                        cq->cq_number, real_qp_num);
-
-       return ret;
-}
-
-struct ehca_qp *ehca_cq_get_qp(struct ehca_cq *cq, int real_qp_num)
-{
-       struct ehca_qp *ret = NULL;
-       unsigned int key = real_qp_num & (QP_HASHTAB_LEN-1);
-       struct hlist_node *iter;
-       struct ehca_qp *qp;
-       hlist_for_each(iter, &cq->qp_hashtab[key]) {
-               qp = hlist_entry(iter, struct ehca_qp, list_entries);
-               if (qp->real_qp_num == real_qp_num) {
-                       ret = qp;
-                       break;
-               }
-       }
-       return ret;
-}
-
-struct ib_cq *ehca_create_cq(struct ib_device *device,
-                            const struct ib_cq_init_attr *attr,
-                            struct ib_ucontext *context,
-                            struct ib_udata *udata)
-{
-       int cqe = attr->cqe;
-       static const u32 additional_cqe = 20;
-       struct ib_cq *cq;
-       struct ehca_cq *my_cq;
-       struct ehca_shca *shca =
-               container_of(device, struct ehca_shca, ib_device);
-       struct ipz_adapter_handle adapter_handle;
-       struct ehca_alloc_cq_parms param; /* h_call's out parameters */
-       struct h_galpa gal;
-       void *vpage;
-       u32 counter;
-       u64 rpage, cqx_fec, h_ret;
-       int ipz_rc, i;
-       unsigned long flags;
-
-       if (attr->flags)
-               return ERR_PTR(-EINVAL);
-
-       if (cqe >= 0xFFFFFFFF - 64 - additional_cqe)
-               return ERR_PTR(-EINVAL);
-
-       if (!atomic_add_unless(&shca->num_cqs, 1, shca->max_num_cqs)) {
-               ehca_err(device, "Unable to create CQ, max number of %i "
-                       "CQs reached.", shca->max_num_cqs);
-               ehca_err(device, "To increase the maximum number of CQs "
-                       "use the number_of_cqs module parameter.\n");
-               return ERR_PTR(-ENOSPC);
-       }
-
-       my_cq = kmem_cache_zalloc(cq_cache, GFP_KERNEL);
-       if (!my_cq) {
-               ehca_err(device, "Out of memory for ehca_cq struct device=%p",
-                        device);
-               atomic_dec(&shca->num_cqs);
-               return ERR_PTR(-ENOMEM);
-       }
-
-       memset(&param, 0, sizeof(struct ehca_alloc_cq_parms));
-
-       spin_lock_init(&my_cq->spinlock);
-       spin_lock_init(&my_cq->cb_lock);
-       spin_lock_init(&my_cq->task_lock);
-       atomic_set(&my_cq->nr_events, 0);
-       init_waitqueue_head(&my_cq->wait_completion);
-
-       cq = &my_cq->ib_cq;
-
-       adapter_handle = shca->ipz_hca_handle;
-       param.eq_handle = shca->eq.ipz_eq_handle;
-
-       idr_preload(GFP_KERNEL);
-       write_lock_irqsave(&ehca_cq_idr_lock, flags);
-       my_cq->token = idr_alloc(&ehca_cq_idr, my_cq, 0, 0x2000000, GFP_NOWAIT);
-       write_unlock_irqrestore(&ehca_cq_idr_lock, flags);
-       idr_preload_end();
-
-       if (my_cq->token < 0) {
-               cq = ERR_PTR(-ENOMEM);
-               ehca_err(device, "Can't allocate new idr entry. device=%p",
-                        device);
-               goto create_cq_exit1;
-       }
-
-       /*
-        * CQs maximum depth is 4GB-64, but we need additional 20 as buffer
-        * for receiving errors CQEs.
-        */
-       param.nr_cqe = cqe + additional_cqe;
-       h_ret = hipz_h_alloc_resource_cq(adapter_handle, my_cq, &param);
-
-       if (h_ret != H_SUCCESS) {
-               ehca_err(device, "hipz_h_alloc_resource_cq() failed "
-                        "h_ret=%lli device=%p", h_ret, device);
-               cq = ERR_PTR(ehca2ib_return_code(h_ret));
-               goto create_cq_exit2;
-       }
-
-       ipz_rc = ipz_queue_ctor(NULL, &my_cq->ipz_queue, param.act_pages,
-                               EHCA_PAGESIZE, sizeof(struct ehca_cqe), 0, 0);
-       if (!ipz_rc) {
-               ehca_err(device, "ipz_queue_ctor() failed ipz_rc=%i device=%p",
-                        ipz_rc, device);
-               cq = ERR_PTR(-EINVAL);
-               goto create_cq_exit3;
-       }
-
-       for (counter = 0; counter < param.act_pages; counter++) {
-               vpage = ipz_qpageit_get_inc(&my_cq->ipz_queue);
-               if (!vpage) {
-                       ehca_err(device, "ipz_qpageit_get_inc() "
-                                "returns NULL device=%p", device);
-                       cq = ERR_PTR(-EAGAIN);
-                       goto create_cq_exit4;
-               }
-               rpage = __pa(vpage);
-
-               h_ret = hipz_h_register_rpage_cq(adapter_handle,
-                                                my_cq->ipz_cq_handle,
-                                                &my_cq->pf,
-                                                0,
-                                                0,
-                                                rpage,
-                                                1,
-                                                my_cq->galpas.
-                                                kernel);
-
-               if (h_ret < H_SUCCESS) {
-                       ehca_err(device, "hipz_h_register_rpage_cq() failed "
-                                "ehca_cq=%p cq_num=%x h_ret=%lli counter=%i "
-                                "act_pages=%i", my_cq, my_cq->cq_number,
-                                h_ret, counter, param.act_pages);
-                       cq = ERR_PTR(-EINVAL);
-                       goto create_cq_exit4;
-               }
-
-               if (counter == (param.act_pages - 1)) {
-                       vpage = ipz_qpageit_get_inc(&my_cq->ipz_queue);
-                       if ((h_ret != H_SUCCESS) || vpage) {
-                               ehca_err(device, "Registration of pages not "
-                                        "complete ehca_cq=%p cq_num=%x "
-                                        "h_ret=%lli", my_cq, my_cq->cq_number,
-                                        h_ret);
-                               cq = ERR_PTR(-EAGAIN);
-                               goto create_cq_exit4;
-                       }
-               } else {
-                       if (h_ret != H_PAGE_REGISTERED) {
-                               ehca_err(device, "Registration of page failed "
-                                        "ehca_cq=%p cq_num=%x h_ret=%lli "
-                                        "counter=%i act_pages=%i",
-                                        my_cq, my_cq->cq_number,
-                                        h_ret, counter, param.act_pages);
-                               cq = ERR_PTR(-ENOMEM);
-                               goto create_cq_exit4;
-                       }
-               }
-       }
-
-       ipz_qeit_reset(&my_cq->ipz_queue);
-
-       gal = my_cq->galpas.kernel;
-       cqx_fec = hipz_galpa_load(gal, CQTEMM_OFFSET(cqx_fec));
-       ehca_dbg(device, "ehca_cq=%p cq_num=%x CQX_FEC=%llx",
-                my_cq, my_cq->cq_number, cqx_fec);
-
-       my_cq->ib_cq.cqe = my_cq->nr_of_entries =
-               param.act_nr_of_entries - additional_cqe;
-       my_cq->cq_number = (my_cq->ipz_cq_handle.handle) & 0xffff;
-
-       for (i = 0; i < QP_HASHTAB_LEN; i++)
-               INIT_HLIST_HEAD(&my_cq->qp_hashtab[i]);
-
-       INIT_LIST_HEAD(&my_cq->sqp_err_list);
-       INIT_LIST_HEAD(&my_cq->rqp_err_list);
-
-       if (context) {
-               struct ipz_queue *ipz_queue = &my_cq->ipz_queue;
-               struct ehca_create_cq_resp resp;
-               memset(&resp, 0, sizeof(resp));
-               resp.cq_number = my_cq->cq_number;
-               resp.token = my_cq->token;
-               resp.ipz_queue.qe_size = ipz_queue->qe_size;
-               resp.ipz_queue.act_nr_of_sg = ipz_queue->act_nr_of_sg;
-               resp.ipz_queue.queue_length = ipz_queue->queue_length;
-               resp.ipz_queue.pagesize = ipz_queue->pagesize;
-               resp.ipz_queue.toggle_state = ipz_queue->toggle_state;
-               resp.fw_handle_ofs = (u32)
-                       (my_cq->galpas.user.fw_handle & (PAGE_SIZE - 1));
-               if (ib_copy_to_udata(udata, &resp, sizeof(resp))) {
-                       ehca_err(device, "Copy to udata failed.");
-                       cq = ERR_PTR(-EFAULT);
-                       goto create_cq_exit4;
-               }
-       }
-
-       return cq;
-
-create_cq_exit4:
-       ipz_queue_dtor(NULL, &my_cq->ipz_queue);
-
-create_cq_exit3:
-       h_ret = hipz_h_destroy_cq(adapter_handle, my_cq, 1);
-       if (h_ret != H_SUCCESS)
-               ehca_err(device, "hipz_h_destroy_cq() failed ehca_cq=%p "
-                        "cq_num=%x h_ret=%lli", my_cq, my_cq->cq_number, h_ret);
-
-create_cq_exit2:
-       write_lock_irqsave(&ehca_cq_idr_lock, flags);
-       idr_remove(&ehca_cq_idr, my_cq->token);
-       write_unlock_irqrestore(&ehca_cq_idr_lock, flags);
-
-create_cq_exit1:
-       kmem_cache_free(cq_cache, my_cq);
-
-       atomic_dec(&shca->num_cqs);
-       return cq;
-}
-
-int ehca_destroy_cq(struct ib_cq *cq)
-{
-       u64 h_ret;
-       struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq);
-       int cq_num = my_cq->cq_number;
-       struct ib_device *device = cq->device;
-       struct ehca_shca *shca = container_of(device, struct ehca_shca,
-                                             ib_device);
-       struct ipz_adapter_handle adapter_handle = shca->ipz_hca_handle;
-       unsigned long flags;
-
-       if (cq->uobject) {
-               if (my_cq->mm_count_galpa || my_cq->mm_count_queue) {
-                       ehca_err(device, "Resources still referenced in "
-                                "user space cq_num=%x", my_cq->cq_number);
-                       return -EINVAL;
-               }
-       }
-
-       /*
-        * remove the CQ from the idr first to make sure
-        * no more interrupt tasklets will touch this CQ
-        */
-       write_lock_irqsave(&ehca_cq_idr_lock, flags);
-       idr_remove(&ehca_cq_idr, my_cq->token);
-       write_unlock_irqrestore(&ehca_cq_idr_lock, flags);
-
-       /* now wait until all pending events have completed */
-       wait_event(my_cq->wait_completion, !atomic_read(&my_cq->nr_events));
-
-       /* nobody's using our CQ any longer -- we can destroy it */
-       h_ret = hipz_h_destroy_cq(adapter_handle, my_cq, 0);
-       if (h_ret == H_R_STATE) {
-               /* cq in err: read err data and destroy it forcibly */
-               ehca_dbg(device, "ehca_cq=%p cq_num=%x resource=%llx in err "
-                        "state. Try to delete it forcibly.",
-                        my_cq, cq_num, my_cq->ipz_cq_handle.handle);
-               ehca_error_data(shca, my_cq, my_cq->ipz_cq_handle.handle);
-               h_ret = hipz_h_destroy_cq(adapter_handle, my_cq, 1);
-               if (h_ret == H_SUCCESS)
-                       ehca_dbg(device, "cq_num=%x deleted successfully.",
-                                cq_num);
-       }
-       if (h_ret != H_SUCCESS) {
-               ehca_err(device, "hipz_h_destroy_cq() failed h_ret=%lli "
-                        "ehca_cq=%p cq_num=%x", h_ret, my_cq, cq_num);
-               return ehca2ib_return_code(h_ret);
-       }
-       ipz_queue_dtor(NULL, &my_cq->ipz_queue);
-       kmem_cache_free(cq_cache, my_cq);
-
-       atomic_dec(&shca->num_cqs);
-       return 0;
-}
-
-int ehca_resize_cq(struct ib_cq *cq, int cqe, struct ib_udata *udata)
-{
-       /* TODO: proper resize needs to be done */
-       ehca_err(cq->device, "not implemented yet");
-
-       return -EFAULT;
-}
-
-int ehca_init_cq_cache(void)
-{
-       cq_cache = kmem_cache_create("ehca_cache_cq",
-                                    sizeof(struct ehca_cq), 0,
-                                    SLAB_HWCACHE_ALIGN,
-                                    NULL);
-       if (!cq_cache)
-               return -ENOMEM;
-       return 0;
-}
-
-void ehca_cleanup_cq_cache(void)
-{
-       if (cq_cache)
-               kmem_cache_destroy(cq_cache);
-}
diff --git a/drivers/infiniband/hw/ehca/ehca_eq.c b/drivers/infiniband/hw/ehca/ehca_eq.c
deleted file mode 100644 (file)
index 90da674..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- *  IBM eServer eHCA Infiniband device driver for Linux on POWER
- *
- *  Event queue handling
- *
- *  Authors: Waleri Fomin <fomin@de.ibm.com>
- *           Khadija Souissi <souissi@de.ibm.com>
- *           Reinhard Ernst <rernst@de.ibm.com>
- *           Heiko J Schick <schickhj@de.ibm.com>
- *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
- *
- *
- *  Copyright (c) 2005 IBM Corporation
- *
- *  All rights reserved.
- *
- *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
- *  BSD.
- *
- * OpenIB BSD License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "ehca_classes.h"
-#include "ehca_irq.h"
-#include "ehca_iverbs.h"
-#include "ehca_qes.h"
-#include "hcp_if.h"
-#include "ipz_pt_fn.h"
-
-int ehca_create_eq(struct ehca_shca *shca,
-                  struct ehca_eq *eq,
-                  const enum ehca_eq_type type, const u32 length)
-{
-       int ret;
-       u64 h_ret;
-       u32 nr_pages;
-       u32 i;
-       void *vpage;
-       struct ib_device *ib_dev = &shca->ib_device;
-
-       spin_lock_init(&eq->spinlock);
-       spin_lock_init(&eq->irq_spinlock);
-       eq->is_initialized = 0;
-
-       if (type != EHCA_EQ && type != EHCA_NEQ) {
-               ehca_err(ib_dev, "Invalid EQ type %x. eq=%p", type, eq);
-               return -EINVAL;
-       }
-       if (!length) {
-               ehca_err(ib_dev, "EQ length must not be zero. eq=%p", eq);
-               return -EINVAL;
-       }
-
-       h_ret = hipz_h_alloc_resource_eq(shca->ipz_hca_handle,
-                                        &eq->pf,
-                                        type,
-                                        length,
-                                        &eq->ipz_eq_handle,
-                                        &eq->length,
-                                        &nr_pages, &eq->ist);
-
-       if (h_ret != H_SUCCESS) {
-               ehca_err(ib_dev, "Can't allocate EQ/NEQ. eq=%p", eq);
-               return -EINVAL;
-       }
-
-       ret = ipz_queue_ctor(NULL, &eq->ipz_queue, nr_pages,
-                            EHCA_PAGESIZE, sizeof(struct ehca_eqe), 0, 0);
-       if (!ret) {
-               ehca_err(ib_dev, "Can't allocate EQ pages eq=%p", eq);
-               goto create_eq_exit1;
-       }
-
-       for (i = 0; i < nr_pages; i++) {
-               u64 rpage;
-
-               vpage = ipz_qpageit_get_inc(&eq->ipz_queue);
-               if (!vpage)
-                       goto create_eq_exit2;
-
-               rpage = __pa(vpage);
-               h_ret = hipz_h_register_rpage_eq(shca->ipz_hca_handle,
-                                                eq->ipz_eq_handle,
-                                                &eq->pf,
-                                                0, 0, rpage, 1);
-
-               if (i == (nr_pages - 1)) {
-                       /* last page */
-                       vpage = ipz_qpageit_get_inc(&eq->ipz_queue);
-                       if (h_ret != H_SUCCESS || vpage)
-                               goto create_eq_exit2;
-               } else {
-                       if (h_ret != H_PAGE_REGISTERED)
-                               goto create_eq_exit2;
-               }
-       }
-
-       ipz_qeit_reset(&eq->ipz_queue);
-
-       /* register interrupt handlers and initialize work queues */
-       if (type == EHCA_EQ) {
-               tasklet_init(&eq->interrupt_task, ehca_tasklet_eq, (long)shca);
-
-               ret = ibmebus_request_irq(eq->ist, ehca_interrupt_eq,
-                                         0, "ehca_eq",
-                                         (void *)shca);
-               if (ret < 0)
-                       ehca_err(ib_dev, "Can't map interrupt handler.");
-       } else if (type == EHCA_NEQ) {
-               tasklet_init(&eq->interrupt_task, ehca_tasklet_neq, (long)shca);
-
-               ret = ibmebus_request_irq(eq->ist, ehca_interrupt_neq,
-                                         0, "ehca_neq",
-                                         (void *)shca);
-               if (ret < 0)
-                       ehca_err(ib_dev, "Can't map interrupt handler.");
-       }
-
-       eq->is_initialized = 1;
-
-       return 0;
-
-create_eq_exit2:
-       ipz_queue_dtor(NULL, &eq->ipz_queue);
-
-create_eq_exit1:
-       hipz_h_destroy_eq(shca->ipz_hca_handle, eq);
-
-       return -EINVAL;
-}
-
-void *ehca_poll_eq(struct ehca_shca *shca, struct ehca_eq *eq)
-{
-       unsigned long flags;
-       void *eqe;
-
-       spin_lock_irqsave(&eq->spinlock, flags);
-       eqe = ipz_eqit_eq_get_inc_valid(&eq->ipz_queue);
-       spin_unlock_irqrestore(&eq->spinlock, flags);
-
-       return eqe;
-}
-
-int ehca_destroy_eq(struct ehca_shca *shca, struct ehca_eq *eq)
-{
-       unsigned long flags;
-       u64 h_ret;
-
-       ibmebus_free_irq(eq->ist, (void *)shca);
-
-       spin_lock_irqsave(&shca_list_lock, flags);
-       eq->is_initialized = 0;
-       spin_unlock_irqrestore(&shca_list_lock, flags);
-
-       tasklet_kill(&eq->interrupt_task);
-
-       h_ret = hipz_h_destroy_eq(shca->ipz_hca_handle, eq);
-
-       if (h_ret != H_SUCCESS) {
-               ehca_err(&shca->ib_device, "Can't free EQ resources.");
-               return -EINVAL;
-       }
-       ipz_queue_dtor(NULL, &eq->ipz_queue);
-
-       return 0;
-}
diff --git a/drivers/infiniband/hw/ehca/ehca_hca.c b/drivers/infiniband/hw/ehca/ehca_hca.c
deleted file mode 100644 (file)
index e8b1bb6..0000000
+++ /dev/null
@@ -1,414 +0,0 @@
-/*
- *  IBM eServer eHCA Infiniband device driver for Linux on POWER
- *
- *  HCA query functions
- *
- *  Authors: Heiko J Schick <schickhj@de.ibm.com>
- *           Christoph Raisch <raisch@de.ibm.com>
- *
- *  Copyright (c) 2005 IBM Corporation
- *
- *  All rights reserved.
- *
- *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
- *  BSD.
- *
- * OpenIB BSD License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <linux/gfp.h>
-
-#include "ehca_tools.h"
-#include "ehca_iverbs.h"
-#include "hcp_if.h"
-
-static unsigned int limit_uint(unsigned int value)
-{
-       return min_t(unsigned int, value, INT_MAX);
-}
-
-int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props,
-                     struct ib_udata *uhw)
-{
-       int i, ret = 0;
-       struct ehca_shca *shca = container_of(ibdev, struct ehca_shca,
-                                             ib_device);
-       struct hipz_query_hca *rblock;
-
-       static const u32 cap_mapping[] = {
-               IB_DEVICE_RESIZE_MAX_WR,      HCA_CAP_WQE_RESIZE,
-               IB_DEVICE_BAD_PKEY_CNTR,      HCA_CAP_BAD_P_KEY_CTR,
-               IB_DEVICE_BAD_QKEY_CNTR,      HCA_CAP_Q_KEY_VIOL_CTR,
-               IB_DEVICE_RAW_MULTI,          HCA_CAP_RAW_PACKET_MCAST,
-               IB_DEVICE_AUTO_PATH_MIG,      HCA_CAP_AUTO_PATH_MIG,
-               IB_DEVICE_CHANGE_PHY_PORT,    HCA_CAP_SQD_RTS_PORT_CHANGE,
-               IB_DEVICE_UD_AV_PORT_ENFORCE, HCA_CAP_AH_PORT_NR_CHECK,
-               IB_DEVICE_CURR_QP_STATE_MOD,  HCA_CAP_CUR_QP_STATE_MOD,
-               IB_DEVICE_SHUTDOWN_PORT,      HCA_CAP_SHUTDOWN_PORT,
-               IB_DEVICE_INIT_TYPE,          HCA_CAP_INIT_TYPE,
-               IB_DEVICE_PORT_ACTIVE_EVENT,  HCA_CAP_PORT_ACTIVE_EVENT,
-       };
-
-       if (uhw->inlen || uhw->outlen)
-               return -EINVAL;
-
-       rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
-       if (!rblock) {
-               ehca_err(&shca->ib_device, "Can't allocate rblock memory.");
-               return -ENOMEM;
-       }
-
-       if (hipz_h_query_hca(shca->ipz_hca_handle, rblock) != H_SUCCESS) {
-               ehca_err(&shca->ib_device, "Can't query device properties");
-               ret = -EINVAL;
-               goto query_device1;
-       }
-
-       memset(props, 0, sizeof(struct ib_device_attr));
-       props->page_size_cap   = shca->hca_cap_mr_pgsize;
-       props->fw_ver          = rblock->hw_ver;
-       props->max_mr_size     = rblock->max_mr_size;
-       props->vendor_id       = rblock->vendor_id >> 8;
-       props->vendor_part_id  = rblock->vendor_part_id >> 16;
-       props->hw_ver          = rblock->hw_ver;
-       props->max_qp          = limit_uint(rblock->max_qp);
-       props->max_qp_wr       = limit_uint(rblock->max_wqes_wq);
-       props->max_sge         = limit_uint(rblock->max_sge);
-       props->max_sge_rd      = limit_uint(rblock->max_sge_rd);
-       props->max_cq          = limit_uint(rblock->max_cq);
-       props->max_cqe         = limit_uint(rblock->max_cqe);
-       props->max_mr          = limit_uint(rblock->max_mr);
-       props->max_mw          = limit_uint(rblock->max_mw);
-       props->max_pd          = limit_uint(rblock->max_pd);
-       props->max_ah          = limit_uint(rblock->max_ah);
-       props->max_ee          = limit_uint(rblock->max_rd_ee_context);
-       props->max_rdd         = limit_uint(rblock->max_rd_domain);
-       props->max_fmr         = limit_uint(rblock->max_mr);
-       props->max_qp_rd_atom  = limit_uint(rblock->max_rr_qp);
-       props->max_ee_rd_atom  = limit_uint(rblock->max_rr_ee_context);
-       props->max_res_rd_atom = limit_uint(rblock->max_rr_hca);
-       props->max_qp_init_rd_atom = limit_uint(rblock->max_act_wqs_qp);
-       props->max_ee_init_rd_atom = limit_uint(rblock->max_act_wqs_ee_context);
-
-       if (EHCA_BMASK_GET(HCA_CAP_SRQ, shca->hca_cap)) {
-               props->max_srq         = limit_uint(props->max_qp);
-               props->max_srq_wr      = limit_uint(props->max_qp_wr);
-               props->max_srq_sge     = 3;
-       }
-
-       props->max_pkeys           = 16;
-       /* Some FW versions say 0 here; insert sensible value in that case */
-       props->local_ca_ack_delay  = rblock->local_ca_ack_delay ?
-               min_t(u8, rblock->local_ca_ack_delay, 255) : 12;
-       props->max_raw_ipv6_qp     = limit_uint(rblock->max_raw_ipv6_qp);
-       props->max_raw_ethy_qp     = limit_uint(rblock->max_raw_ethy_qp);
-       props->max_mcast_grp       = limit_uint(rblock->max_mcast_grp);
-       props->max_mcast_qp_attach = limit_uint(rblock->max_mcast_qp_attach);
-       props->max_total_mcast_qp_attach
-               = limit_uint(rblock->max_total_mcast_qp_attach);
-
-       /* translate device capabilities */
-       props->device_cap_flags = IB_DEVICE_SYS_IMAGE_GUID |
-               IB_DEVICE_RC_RNR_NAK_GEN | IB_DEVICE_N_NOTIFY_CQ;
-       for (i = 0; i < ARRAY_SIZE(cap_mapping); i += 2)
-               if (rblock->hca_cap_indicators & cap_mapping[i + 1])
-                       props->device_cap_flags |= cap_mapping[i];
-
-query_device1:
-       ehca_free_fw_ctrlblock(rblock);
-
-       return ret;
-}
-
-static enum ib_mtu map_mtu(struct ehca_shca *shca, u32 fw_mtu)
-{
-       switch (fw_mtu) {
-       case 0x1:
-               return IB_MTU_256;
-       case 0x2:
-               return IB_MTU_512;
-       case 0x3:
-               return IB_MTU_1024;
-       case 0x4:
-               return IB_MTU_2048;
-       case 0x5:
-               return IB_MTU_4096;
-       default:
-               ehca_err(&shca->ib_device, "Unknown MTU size: %x.",
-                        fw_mtu);
-               return 0;
-       }
-}
-
-static u8 map_number_of_vls(struct ehca_shca *shca, u32 vl_cap)
-{
-       switch (vl_cap) {
-       case 0x1:
-               return 1;
-       case 0x2:
-               return 2;
-       case 0x3:
-               return 4;
-       case 0x4:
-               return 8;
-       case 0x5:
-               return 15;
-       default:
-               ehca_err(&shca->ib_device, "invalid Vl Capability: %x.",
-                        vl_cap);
-               return 0;
-       }
-}
-
-int ehca_query_port(struct ib_device *ibdev,
-                   u8 port, struct ib_port_attr *props)
-{
-       int ret = 0;
-       u64 h_ret;
-       struct ehca_shca *shca = container_of(ibdev, struct ehca_shca,
-                                             ib_device);
-       struct hipz_query_port *rblock;
-
-       rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
-       if (!rblock) {
-               ehca_err(&shca->ib_device, "Can't allocate rblock memory.");
-               return -ENOMEM;
-       }
-
-       h_ret = hipz_h_query_port(shca->ipz_hca_handle, port, rblock);
-       if (h_ret != H_SUCCESS) {
-               ehca_err(&shca->ib_device, "Can't query port properties");
-               ret = -EINVAL;
-               goto query_port1;
-       }
-
-       memset(props, 0, sizeof(struct ib_port_attr));
-
-       props->active_mtu = props->max_mtu = map_mtu(shca, rblock->max_mtu);
-       props->port_cap_flags  = rblock->capability_mask;
-       props->gid_tbl_len     = rblock->gid_tbl_len;
-       if (rblock->max_msg_sz)
-               props->max_msg_sz      = rblock->max_msg_sz;
-       else
-               props->max_msg_sz      = 0x1 << 31;
-       props->bad_pkey_cntr   = rblock->bad_pkey_cntr;
-       props->qkey_viol_cntr  = rblock->qkey_viol_cntr;
-       props->pkey_tbl_len    = rblock->pkey_tbl_len;
-       props->lid             = rblock->lid;
-       props->sm_lid          = rblock->sm_lid;
-       props->lmc             = rblock->lmc;
-       props->sm_sl           = rblock->sm_sl;
-       props->subnet_timeout  = rblock->subnet_timeout;
-       props->init_type_reply = rblock->init_type_reply;
-       props->max_vl_num      = map_number_of_vls(shca, rblock->vl_cap);
-
-       if (rblock->state && rblock->phys_width) {
-               props->phys_state      = rblock->phys_pstate;
-               props->state           = rblock->phys_state;
-               props->active_width    = rblock->phys_width;
-               props->active_speed    = rblock->phys_speed;
-       } else {
-               /* old firmware releases don't report physical
-                * port info, so use default values
-                */
-               props->phys_state      = 5;
-               props->state           = rblock->state;
-               props->active_width    = IB_WIDTH_12X;
-               props->active_speed    = IB_SPEED_SDR;
-       }
-
-query_port1:
-       ehca_free_fw_ctrlblock(rblock);
-
-       return ret;
-}
-
-int ehca_query_sma_attr(struct ehca_shca *shca,
-                       u8 port, struct ehca_sma_attr *attr)
-{
-       int ret = 0;
-       u64 h_ret;
-       struct hipz_query_port *rblock;
-
-       rblock = ehca_alloc_fw_ctrlblock(GFP_ATOMIC);
-       if (!rblock) {
-               ehca_err(&shca->ib_device, "Can't allocate rblock memory.");
-               return -ENOMEM;
-       }
-
-       h_ret = hipz_h_query_port(shca->ipz_hca_handle, port, rblock);
-       if (h_ret != H_SUCCESS) {
-               ehca_err(&shca->ib_device, "Can't query port properties");
-               ret = -EINVAL;
-               goto query_sma_attr1;
-       }
-
-       memset(attr, 0, sizeof(struct ehca_sma_attr));
-
-       attr->lid    = rblock->lid;
-       attr->lmc    = rblock->lmc;
-       attr->sm_sl  = rblock->sm_sl;
-       attr->sm_lid = rblock->sm_lid;
-
-       attr->pkey_tbl_len = rblock->pkey_tbl_len;
-       memcpy(attr->pkeys, rblock->pkey_entries, sizeof(attr->pkeys));
-
-query_sma_attr1:
-       ehca_free_fw_ctrlblock(rblock);
-
-       return ret;
-}
-
-int ehca_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 *pkey)
-{
-       int ret = 0;
-       u64 h_ret;
-       struct ehca_shca *shca;
-       struct hipz_query_port *rblock;
-
-       shca = container_of(ibdev, struct ehca_shca, ib_device);
-       if (index > 16) {
-               ehca_err(&shca->ib_device, "Invalid index: %x.", index);
-               return -EINVAL;
-       }
-
-       rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
-       if (!rblock) {
-               ehca_err(&shca->ib_device,  "Can't allocate rblock memory.");
-               return -ENOMEM;
-       }
-
-       h_ret = hipz_h_query_port(shca->ipz_hca_handle, port, rblock);
-       if (h_ret != H_SUCCESS) {
-               ehca_err(&shca->ib_device, "Can't query port properties");
-               ret = -EINVAL;
-               goto query_pkey1;
-       }
-
-       memcpy(pkey, &rblock->pkey_entries + index, sizeof(u16));
-
-query_pkey1:
-       ehca_free_fw_ctrlblock(rblock);
-
-       return ret;
-}
-
-int ehca_query_gid(struct ib_device *ibdev, u8 port,
-                  int index, union ib_gid *gid)
-{
-       int ret = 0;
-       u64 h_ret;
-       struct ehca_shca *shca = container_of(ibdev, struct ehca_shca,
-                                             ib_device);
-       struct hipz_query_port *rblock;
-
-       if (index < 0 || index > 255) {
-               ehca_err(&shca->ib_device, "Invalid index: %x.", index);
-               return -EINVAL;
-       }
-
-       rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
-       if (!rblock) {
-               ehca_err(&shca->ib_device, "Can't allocate rblock memory.");
-               return -ENOMEM;
-       }
-
-       h_ret = hipz_h_query_port(shca->ipz_hca_handle, port, rblock);
-       if (h_ret != H_SUCCESS) {
-               ehca_err(&shca->ib_device, "Can't query port properties");
-               ret = -EINVAL;
-               goto query_gid1;
-       }
-
-       memcpy(&gid->raw[0], &rblock->gid_prefix, sizeof(u64));
-       memcpy(&gid->raw[8], &rblock->guid_entries[index], sizeof(u64));
-
-query_gid1:
-       ehca_free_fw_ctrlblock(rblock);
-
-       return ret;
-}
-
-static const u32 allowed_port_caps = (
-       IB_PORT_SM | IB_PORT_LED_INFO_SUP | IB_PORT_CM_SUP |
-       IB_PORT_SNMP_TUNNEL_SUP | IB_PORT_DEVICE_MGMT_SUP |
-       IB_PORT_VENDOR_CLASS_SUP);
-
-int ehca_modify_port(struct ib_device *ibdev,
-                    u8 port, int port_modify_mask,
-                    struct ib_port_modify *props)
-{
-       int ret = 0;
-       struct ehca_shca *shca;
-       struct hipz_query_port *rblock;
-       u32 cap;
-       u64 hret;
-
-       shca = container_of(ibdev, struct ehca_shca, ib_device);
-       if ((props->set_port_cap_mask | props->clr_port_cap_mask)
-           & ~allowed_port_caps) {
-               ehca_err(&shca->ib_device, "Non-changeable bits set in masks  "
-                        "set=%x  clr=%x  allowed=%x", props->set_port_cap_mask,
-                        props->clr_port_cap_mask, allowed_port_caps);
-               return -EINVAL;
-       }
-
-       if (mutex_lock_interruptible(&shca->modify_mutex))
-               return -ERESTARTSYS;
-
-       rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
-       if (!rblock) {
-               ehca_err(&shca->ib_device,  "Can't allocate rblock memory.");
-               ret = -ENOMEM;
-               goto modify_port1;
-       }
-
-       hret = hipz_h_query_port(shca->ipz_hca_handle, port, rblock);
-       if (hret != H_SUCCESS) {
-               ehca_err(&shca->ib_device, "Can't query port properties");
-               ret = -EINVAL;
-               goto modify_port2;
-       }
-
-       cap = (rblock->capability_mask | props->set_port_cap_mask)
-               & ~props->clr_port_cap_mask;
-
-       hret = hipz_h_modify_port(shca->ipz_hca_handle, port,
-                                 cap, props->init_type, port_modify_mask);
-       if (hret != H_SUCCESS) {
-               ehca_err(&shca->ib_device, "Modify port failed  h_ret=%lli",
-                        hret);
-               ret = -EINVAL;
-       }
-
-modify_port2:
-       ehca_free_fw_ctrlblock(rblock);
-
-modify_port1:
-       mutex_unlock(&shca->modify_mutex);
-
-       return ret;
-}
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c
deleted file mode 100644 (file)
index 8615d7c..0000000
+++ /dev/null
@@ -1,870 +0,0 @@
-/*
- *  IBM eServer eHCA Infiniband device driver for Linux on POWER
- *
- *  Functions for EQs, NEQs and interrupts
- *
- *  Authors: Heiko J Schick <schickhj@de.ibm.com>
- *           Khadija Souissi <souissi@de.ibm.com>
- *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
- *           Joachim Fenkes <fenkes@de.ibm.com>
- *
- *  Copyright (c) 2005 IBM Corporation
- *
- *  All rights reserved.
- *
- *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
- *  BSD.
- *
- * OpenIB BSD License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <linux/slab.h>
-#include <linux/smpboot.h>
-
-#include "ehca_classes.h"
-#include "ehca_irq.h"
-#include "ehca_iverbs.h"
-#include "ehca_tools.h"
-#include "hcp_if.h"
-#include "hipz_fns.h"
-#include "ipz_pt_fn.h"
-
-#define EQE_COMPLETION_EVENT   EHCA_BMASK_IBM( 1,  1)
-#define EQE_CQ_QP_NUMBER       EHCA_BMASK_IBM( 8, 31)
-#define EQE_EE_IDENTIFIER      EHCA_BMASK_IBM( 2,  7)
-#define EQE_CQ_NUMBER          EHCA_BMASK_IBM( 8, 31)
-#define EQE_QP_NUMBER          EHCA_BMASK_IBM( 8, 31)
-#define EQE_QP_TOKEN           EHCA_BMASK_IBM(32, 63)
-#define EQE_CQ_TOKEN           EHCA_BMASK_IBM(32, 63)
-
-#define NEQE_COMPLETION_EVENT  EHCA_BMASK_IBM( 1,  1)
-#define NEQE_EVENT_CODE        EHCA_BMASK_IBM( 2,  7)
-#define NEQE_PORT_NUMBER       EHCA_BMASK_IBM( 8, 15)
-#define NEQE_PORT_AVAILABILITY EHCA_BMASK_IBM(16, 16)
-#define NEQE_DISRUPTIVE        EHCA_BMASK_IBM(16, 16)
-#define NEQE_SPECIFIC_EVENT    EHCA_BMASK_IBM(16, 23)
-
-#define ERROR_DATA_LENGTH      EHCA_BMASK_IBM(52, 63)
-#define ERROR_DATA_TYPE        EHCA_BMASK_IBM( 0,  7)
-
-static void queue_comp_task(struct ehca_cq *__cq);
-
-static struct ehca_comp_pool *pool;
-
-static inline void comp_event_callback(struct ehca_cq *cq)
-{
-       if (!cq->ib_cq.comp_handler)
-               return;
-
-       spin_lock(&cq->cb_lock);
-       cq->ib_cq.comp_handler(&cq->ib_cq, cq->ib_cq.cq_context);
-       spin_unlock(&cq->cb_lock);
-
-       return;
-}
-
-static void print_error_data(struct ehca_shca *shca, void *data,
-                            u64 *rblock, int length)
-{
-       u64 type = EHCA_BMASK_GET(ERROR_DATA_TYPE, rblock[2]);
-       u64 resource = rblock[1];
-
-       switch (type) {
-       case 0x1: /* Queue Pair */
-       {
-               struct ehca_qp *qp = (struct ehca_qp *)data;
-
-               /* only print error data if AER is set */
-               if (rblock[6] == 0)
-                       return;
-
-               ehca_err(&shca->ib_device,
-                        "QP 0x%x (resource=%llx) has errors.",
-                        qp->ib_qp.qp_num, resource);
-               break;
-       }
-       case 0x4: /* Completion Queue */
-       {
-               struct ehca_cq *cq = (struct ehca_cq *)data;
-
-               ehca_err(&shca->ib_device,
-                        "CQ 0x%x (resource=%llx) has errors.",
-                        cq->cq_number, resource);
-               break;
-       }
-       default:
-               ehca_err(&shca->ib_device,
-                        "Unknown error type: %llx on %s.",
-                        type, shca->ib_device.name);
-               break;
-       }
-
-       ehca_err(&shca->ib_device, "Error data is available: %llx.", resource);
-       ehca_err(&shca->ib_device, "EHCA ----- error data begin "
-                "---------------------------------------------------");
-       ehca_dmp(rblock, length, "resource=%llx", resource);
-       ehca_err(&shca->ib_device, "EHCA ----- error data end "
-                "----------------------------------------------------");
-
-       return;
-}
-
-int ehca_error_data(struct ehca_shca *shca, void *data,
-                   u64 resource)
-{
-
-       unsigned long ret;
-       u64 *rblock;
-       unsigned long block_count;
-
-       rblock = ehca_alloc_fw_ctrlblock(GFP_ATOMIC);
-       if (!rblock) {
-               ehca_err(&shca->ib_device, "Cannot allocate rblock memory.");
-               ret = -ENOMEM;
-               goto error_data1;
-       }
-
-       /* rblock must be 4K aligned and should be 4K large */
-       ret = hipz_h_error_data(shca->ipz_hca_handle,
-                               resource,
-                               rblock,
-                               &block_count);
-
-       if (ret == H_R_STATE)
-               ehca_err(&shca->ib_device,
-                        "No error data is available: %llx.", resource);
-       else if (ret == H_SUCCESS) {
-               int length;
-
-               length = EHCA_BMASK_GET(ERROR_DATA_LENGTH, rblock[0]);
-
-               if (length > EHCA_PAGESIZE)
-                       length = EHCA_PAGESIZE;
-
-               print_error_data(shca, data, rblock, length);
-       } else
-               ehca_err(&shca->ib_device,
-                        "Error data could not be fetched: %llx", resource);
-
-       ehca_free_fw_ctrlblock(rblock);
-
-error_data1:
-       return ret;
-
-}
-
-static void dispatch_qp_event(struct ehca_shca *shca, struct ehca_qp *qp,
-                             enum ib_event_type event_type)
-{
-       struct ib_event event;
-
-       /* PATH_MIG without the QP ever having been armed is false alarm */
-       if (event_type == IB_EVENT_PATH_MIG && !qp->mig_armed)
-               return;
-
-       event.device = &shca->ib_device;
-       event.event = event_type;
-
-       if (qp->ext_type == EQPT_SRQ) {
-               if (!qp->ib_srq.event_handler)
-                       return;
-
-               event.element.srq = &qp->ib_srq;
-               qp->ib_srq.event_handler(&event, qp->ib_srq.srq_context);
-       } else {
-               if (!qp->ib_qp.event_handler)
-                       return;
-
-               event.element.qp = &qp->ib_qp;
-               qp->ib_qp.event_handler(&event, qp->ib_qp.qp_context);
-       }
-}
-
-static void qp_event_callback(struct ehca_shca *shca, u64 eqe,
-                             enum ib_event_type event_type, int fatal)
-{
-       struct ehca_qp *qp;
-       u32 token = EHCA_BMASK_GET(EQE_QP_TOKEN, eqe);
-
-       read_lock(&ehca_qp_idr_lock);
-       qp = idr_find(&ehca_qp_idr, token);
-       if (qp)
-               atomic_inc(&qp->nr_events);
-       read_unlock(&ehca_qp_idr_lock);
-
-       if (!qp)
-               return;
-
-       if (fatal)
-               ehca_error_data(shca, qp, qp->ipz_qp_handle.handle);
-
-       dispatch_qp_event(shca, qp, fatal && qp->ext_type == EQPT_SRQ ?
-                         IB_EVENT_SRQ_ERR : event_type);
-
-       /*
-        * eHCA only processes one WQE at a time for SRQ base QPs,
-        * so the last WQE has been processed as soon as the QP enters
-        * error state.
-        */
-       if (fatal && qp->ext_type == EQPT_SRQBASE)
-               dispatch_qp_event(shca, qp, IB_EVENT_QP_LAST_WQE_REACHED);
-
-       if (atomic_dec_and_test(&qp->nr_events))
-               wake_up(&qp->wait_completion);
-       return;
-}
-
-static void cq_event_callback(struct ehca_shca *shca,
-                             u64 eqe)
-{
-       struct ehca_cq *cq;
-       u32 token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe);
-
-       read_lock(&ehca_cq_idr_lock);
-       cq = idr_find(&ehca_cq_idr, token);
-       if (cq)
-               atomic_inc(&cq->nr_events);
-       read_unlock(&ehca_cq_idr_lock);
-
-       if (!cq)
-               return;
-
-       ehca_error_data(shca, cq, cq->ipz_cq_handle.handle);
-
-       if (atomic_dec_and_test(&cq->nr_events))
-               wake_up(&cq->wait_completion);
-
-       return;
-}
-
-static void parse_identifier(struct ehca_shca *shca, u64 eqe)
-{
-       u8 identifier = EHCA_BMASK_GET(EQE_EE_IDENTIFIER, eqe);
-
-       switch (identifier) {
-       case 0x02: /* path migrated */
-               qp_event_callback(shca, eqe, IB_EVENT_PATH_MIG, 0);
-               break;
-       case 0x03: /* communication established */
-               qp_event_callback(shca, eqe, IB_EVENT_COMM_EST, 0);
-               break;
-       case 0x04: /* send queue drained */
-               qp_event_callback(shca, eqe, IB_EVENT_SQ_DRAINED, 0);
-               break;
-       case 0x05: /* QP error */
-       case 0x06: /* QP error */
-               qp_event_callback(shca, eqe, IB_EVENT_QP_FATAL, 1);
-               break;
-       case 0x07: /* CQ error */
-       case 0x08: /* CQ error */
-               cq_event_callback(shca, eqe);
-               break;
-       case 0x09: /* MRMWPTE error */
-               ehca_err(&shca->ib_device, "MRMWPTE error.");
-               break;
-       case 0x0A: /* port event */
-               ehca_err(&shca->ib_device, "Port event.");
-               break;
-       case 0x0B: /* MR access error */
-               ehca_err(&shca->ib_device, "MR access error.");
-               break;
-       case 0x0C: /* EQ error */
-               ehca_err(&shca->ib_device, "EQ error.");
-               break;
-       case 0x0D: /* P/Q_Key mismatch */
-               ehca_err(&shca->ib_device, "P/Q_Key mismatch.");
-               break;
-       case 0x10: /* sampling complete */
-               ehca_err(&shca->ib_device, "Sampling complete.");
-               break;
-       case 0x11: /* unaffiliated access error */
-               ehca_err(&shca->ib_device, "Unaffiliated access error.");
-               break;
-       case 0x12: /* path migrating */
-               ehca_err(&shca->ib_device, "Path migrating.");
-               break;
-       case 0x13: /* interface trace stopped */
-               ehca_err(&shca->ib_device, "Interface trace stopped.");
-               break;
-       case 0x14: /* first error capture info available */
-               ehca_info(&shca->ib_device, "First error capture available");
-               break;
-       case 0x15: /* SRQ limit reached */
-               qp_event_callback(shca, eqe, IB_EVENT_SRQ_LIMIT_REACHED, 0);
-               break;
-       default:
-               ehca_err(&shca->ib_device, "Unknown identifier: %x on %s.",
-                        identifier, shca->ib_device.name);
-               break;
-       }
-
-       return;
-}
-
-static void dispatch_port_event(struct ehca_shca *shca, int port_num,
-                               enum ib_event_type type, const char *msg)
-{
-       struct ib_event event;
-
-       ehca_info(&shca->ib_device, "port %d %s.", port_num, msg);
-       event.device = &shca->ib_device;
-       event.event = type;
-       event.element.port_num = port_num;
-       ib_dispatch_event(&event);
-}
-
-static void notify_port_conf_change(struct ehca_shca *shca, int port_num)
-{
-       struct ehca_sma_attr  new_attr;
-       struct ehca_sma_attr *old_attr = &shca->sport[port_num - 1].saved_attr;
-
-       ehca_query_sma_attr(shca, port_num, &new_attr);
-
-       if (new_attr.sm_sl  != old_attr->sm_sl ||
-           new_attr.sm_lid != old_attr->sm_lid)
-               dispatch_port_event(shca, port_num, IB_EVENT_SM_CHANGE,
-                                   "SM changed");
-
-       if (new_attr.lid != old_attr->lid ||
-           new_attr.lmc != old_attr->lmc)
-               dispatch_port_event(shca, port_num, IB_EVENT_LID_CHANGE,
-                                   "LID changed");
-
-       if (new_attr.pkey_tbl_len != old_attr->pkey_tbl_len ||
-           memcmp(new_attr.pkeys, old_attr->pkeys,
-                  sizeof(u16) * new_attr.pkey_tbl_len))
-               dispatch_port_event(shca, port_num, IB_EVENT_PKEY_CHANGE,
-                                   "P_Key changed");
-
-       *old_attr = new_attr;
-}
-
-/* replay modify_qp for sqps -- return 0 if all is well, 1 if AQP1 destroyed */
-static int replay_modify_qp(struct ehca_sport *sport)
-{
-       int aqp1_destroyed;
-       unsigned long flags;
-
-       spin_lock_irqsave(&sport->mod_sqp_lock, flags);
-
-       aqp1_destroyed = !sport->ibqp_sqp[IB_QPT_GSI];
-
-       if (sport->ibqp_sqp[IB_QPT_SMI])
-               ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_SMI]);
-       if (!aqp1_destroyed)
-               ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_GSI]);
-
-       spin_unlock_irqrestore(&sport->mod_sqp_lock, flags);
-
-       return aqp1_destroyed;
-}
-
-static void parse_ec(struct ehca_shca *shca, u64 eqe)
-{
-       u8 ec   = EHCA_BMASK_GET(NEQE_EVENT_CODE, eqe);
-       u8 port = EHCA_BMASK_GET(NEQE_PORT_NUMBER, eqe);
-       u8 spec_event;
-       struct ehca_sport *sport = &shca->sport[port - 1];
-
-       switch (ec) {
-       case 0x30: /* port availability change */
-               if (EHCA_BMASK_GET(NEQE_PORT_AVAILABILITY, eqe)) {
-                       /* only replay modify_qp calls in autodetect mode;
-                        * if AQP1 was destroyed, the port is already down
-                        * again and we can drop the event.
-                        */
-                       if (ehca_nr_ports < 0)
-                               if (replay_modify_qp(sport))
-                                       break;
-
-                       sport->port_state = IB_PORT_ACTIVE;
-                       dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE,
-                                           "is active");
-                       ehca_query_sma_attr(shca, port, &sport->saved_attr);
-               } else {
-                       sport->port_state = IB_PORT_DOWN;
-                       dispatch_port_event(shca, port, IB_EVENT_PORT_ERR,
-                                           "is inactive");
-               }
-               break;
-       case 0x31:
-               /* port configuration change
-                * disruptive change is caused by
-                * LID, PKEY or SM change
-                */
-               if (EHCA_BMASK_GET(NEQE_DISRUPTIVE, eqe)) {
-                       ehca_warn(&shca->ib_device, "disruptive port "
-                                 "%d configuration change", port);
-
-                       sport->port_state = IB_PORT_DOWN;
-                       dispatch_port_event(shca, port, IB_EVENT_PORT_ERR,
-                                           "is inactive");
-
-                       sport->port_state = IB_PORT_ACTIVE;
-                       dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE,
-                                           "is active");
-                       ehca_query_sma_attr(shca, port,
-                                           &sport->saved_attr);
-               } else
-                       notify_port_conf_change(shca, port);
-               break;
-       case 0x32: /* adapter malfunction */
-               ehca_err(&shca->ib_device, "Adapter malfunction.");
-               break;
-       case 0x33:  /* trace stopped */
-               ehca_err(&shca->ib_device, "Traced stopped.");
-               break;
-       case 0x34: /* util async event */
-               spec_event = EHCA_BMASK_GET(NEQE_SPECIFIC_EVENT, eqe);
-               if (spec_event == 0x80) /* client reregister required */
-                       dispatch_port_event(shca, port,
-                                           IB_EVENT_CLIENT_REREGISTER,
-                                           "client reregister req.");
-               else
-                       ehca_warn(&shca->ib_device, "Unknown util async "
-                                 "event %x on port %x", spec_event, port);
-               break;
-       default:
-               ehca_err(&shca->ib_device, "Unknown event code: %x on %s.",
-                        ec, shca->ib_device.name);
-               break;
-       }
-
-       return;
-}
-
-static inline void reset_eq_pending(struct ehca_cq *cq)
-{
-       u64 CQx_EP;
-       struct h_galpa gal = cq->galpas.kernel;
-
-       hipz_galpa_store_cq(gal, cqx_ep, 0x0);
-       CQx_EP = hipz_galpa_load(gal, CQTEMM_OFFSET(cqx_ep));
-
-       return;
-}
-
-irqreturn_t ehca_interrupt_neq(int irq, void *dev_id)
-{
-       struct ehca_shca *shca = (struct ehca_shca*)dev_id;
-
-       tasklet_hi_schedule(&shca->neq.interrupt_task);
-
-       return IRQ_HANDLED;
-}
-
-void ehca_tasklet_neq(unsigned long data)
-{
-       struct ehca_shca *shca = (struct ehca_shca*)data;
-       struct ehca_eqe *eqe;
-       u64 ret;
-
-       eqe = ehca_poll_eq(shca, &shca->neq);
-
-       while (eqe) {
-               if (!EHCA_BMASK_GET(NEQE_COMPLETION_EVENT, eqe->entry))
-                       parse_ec(shca, eqe->entry);
-
-               eqe = ehca_poll_eq(shca, &shca->neq);
-       }
-
-       ret = hipz_h_reset_event(shca->ipz_hca_handle,
-                                shca->neq.ipz_eq_handle, 0xFFFFFFFFFFFFFFFFL);
-
-       if (ret != H_SUCCESS)
-               ehca_err(&shca->ib_device, "Can't clear notification events.");
-
-       return;
-}
-
-irqreturn_t ehca_interrupt_eq(int irq, void *dev_id)
-{
-       struct ehca_shca *shca = (struct ehca_shca*)dev_id;
-
-       tasklet_hi_schedule(&shca->eq.interrupt_task);
-
-       return IRQ_HANDLED;
-}
-
-
-static inline void process_eqe(struct ehca_shca *shca, struct ehca_eqe *eqe)
-{
-       u64 eqe_value;
-       u32 token;
-       struct ehca_cq *cq;
-
-       eqe_value = eqe->entry;
-       ehca_dbg(&shca->ib_device, "eqe_value=%llx", eqe_value);
-       if (EHCA_BMASK_GET(EQE_COMPLETION_EVENT, eqe_value)) {
-               ehca_dbg(&shca->ib_device, "Got completion event");
-               token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe_value);
-               read_lock(&ehca_cq_idr_lock);
-               cq = idr_find(&ehca_cq_idr, token);
-               if (cq)
-                       atomic_inc(&cq->nr_events);
-               read_unlock(&ehca_cq_idr_lock);
-               if (cq == NULL) {
-                       ehca_err(&shca->ib_device,
-                                "Invalid eqe for non-existing cq token=%x",
-                                token);
-                       return;
-               }
-               reset_eq_pending(cq);
-               if (ehca_scaling_code)
-                       queue_comp_task(cq);
-               else {
-                       comp_event_callback(cq);
-                       if (atomic_dec_and_test(&cq->nr_events))
-                               wake_up(&cq->wait_completion);
-               }
-       } else {
-               ehca_dbg(&shca->ib_device, "Got non completion event");
-               parse_identifier(shca, eqe_value);
-       }
-}
-
-void ehca_process_eq(struct ehca_shca *shca, int is_irq)
-{
-       struct ehca_eq *eq = &shca->eq;
-       struct ehca_eqe_cache_entry *eqe_cache = eq->eqe_cache;
-       u64 eqe_value, ret;
-       int eqe_cnt, i;
-       int eq_empty = 0;
-
-       spin_lock(&eq->irq_spinlock);
-       if (is_irq) {
-               const int max_query_cnt = 100;
-               int query_cnt = 0;
-               int int_state = 1;
-               do {
-                       int_state = hipz_h_query_int_state(
-                               shca->ipz_hca_handle, eq->ist);
-                       query_cnt++;
-                       iosync();
-               } while (int_state && query_cnt < max_query_cnt);
-               if (unlikely((query_cnt == max_query_cnt)))
-                       ehca_dbg(&shca->ib_device, "int_state=%x query_cnt=%x",
-                                int_state, query_cnt);
-       }
-
-       /* read out all eqes */
-       eqe_cnt = 0;
-       do {
-               u32 token;
-               eqe_cache[eqe_cnt].eqe = ehca_poll_eq(shca, eq);
-               if (!eqe_cache[eqe_cnt].eqe)
-                       break;
-               eqe_value = eqe_cache[eqe_cnt].eqe->entry;
-               if (EHCA_BMASK_GET(EQE_COMPLETION_EVENT, eqe_value)) {
-                       token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe_value);
-                       read_lock(&ehca_cq_idr_lock);
-                       eqe_cache[eqe_cnt].cq = idr_find(&ehca_cq_idr, token);
-                       if (eqe_cache[eqe_cnt].cq)
-                               atomic_inc(&eqe_cache[eqe_cnt].cq->nr_events);
-                       read_unlock(&ehca_cq_idr_lock);
-                       if (!eqe_cache[eqe_cnt].cq) {
-                               ehca_err(&shca->ib_device,
-                                        "Invalid eqe for non-existing cq "
-                                        "token=%x", token);
-                               continue;
-                       }
-               } else
-                       eqe_cache[eqe_cnt].cq = NULL;
-               eqe_cnt++;
-       } while (eqe_cnt < EHCA_EQE_CACHE_SIZE);
-       if (!eqe_cnt) {
-               if (is_irq)
-                       ehca_dbg(&shca->ib_device,
-                                "No eqe found for irq event");
-               goto unlock_irq_spinlock;
-       } else if (!is_irq) {
-               ret = hipz_h_eoi(eq->ist);
-               if (ret != H_SUCCESS)
-                       ehca_err(&shca->ib_device,
-                                "bad return code EOI -rc = %lld\n", ret);
-               ehca_dbg(&shca->ib_device, "deadman found %x eqe", eqe_cnt);
-       }
-       if (unlikely(eqe_cnt == EHCA_EQE_CACHE_SIZE))
-               ehca_dbg(&shca->ib_device, "too many eqes for one irq event");
-       /* enable irq for new packets */
-       for (i = 0; i < eqe_cnt; i++) {
-               if (eq->eqe_cache[i].cq)
-                       reset_eq_pending(eq->eqe_cache[i].cq);
-       }
-       /* check eq */
-       spin_lock(&eq->spinlock);
-       eq_empty = (!ipz_eqit_eq_peek_valid(&shca->eq.ipz_queue));
-       spin_unlock(&eq->spinlock);
-       /* call completion handler for cached eqes */
-       for (i = 0; i < eqe_cnt; i++)
-               if (eq->eqe_cache[i].cq) {
-                       if (ehca_scaling_code)
-                               queue_comp_task(eq->eqe_cache[i].cq);
-                       else {
-                               struct ehca_cq *cq = eq->eqe_cache[i].cq;
-                               comp_event_callback(cq);
-                               if (atomic_dec_and_test(&cq->nr_events))
-                                       wake_up(&cq->wait_completion);
-                       }
-               } else {
-                       ehca_dbg(&shca->ib_device, "Got non completion event");
-                       parse_identifier(shca, eq->eqe_cache[i].eqe->entry);
-               }
-       /* poll eq if not empty */
-       if (eq_empty)
-               goto unlock_irq_spinlock;
-       do {
-               struct ehca_eqe *eqe;
-               eqe = ehca_poll_eq(shca, &shca->eq);
-               if (!eqe)
-                       break;
-               process_eqe(shca, eqe);
-       } while (1);
-
-unlock_irq_spinlock:
-       spin_unlock(&eq->irq_spinlock);
-}
-
-void ehca_tasklet_eq(unsigned long data)
-{
-       ehca_process_eq((struct ehca_shca*)data, 1);
-}
-
-static int find_next_online_cpu(struct ehca_comp_pool *pool)
-{
-       int cpu;
-       unsigned long flags;
-
-       WARN_ON_ONCE(!in_interrupt());
-       if (ehca_debug_level >= 3)
-               ehca_dmp(cpu_online_mask, cpumask_size(), "");
-
-       spin_lock_irqsave(&pool->last_cpu_lock, flags);
-       do {
-               cpu = cpumask_next(pool->last_cpu, cpu_online_mask);
-               if (cpu >= nr_cpu_ids)
-                       cpu = cpumask_first(cpu_online_mask);
-               pool->last_cpu = cpu;
-       } while (!per_cpu_ptr(pool->cpu_comp_tasks, cpu)->active);
-       spin_unlock_irqrestore(&pool->last_cpu_lock, flags);
-
-       return cpu;
-}
-
-static void __queue_comp_task(struct ehca_cq *__cq,
-                             struct ehca_cpu_comp_task *cct,
-                             struct task_struct *thread)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&cct->task_lock, flags);
-       spin_lock(&__cq->task_lock);
-
-       if (__cq->nr_callbacks == 0) {
-               __cq->nr_callbacks++;
-               list_add_tail(&__cq->entry, &cct->cq_list);
-               cct->cq_jobs++;
-               wake_up_process(thread);
-       } else
-               __cq->nr_callbacks++;
-
-       spin_unlock(&__cq->task_lock);
-       spin_unlock_irqrestore(&cct->task_lock, flags);
-}
-
-static void queue_comp_task(struct ehca_cq *__cq)
-{
-       int cpu_id;
-       struct ehca_cpu_comp_task *cct;
-       struct task_struct *thread;
-       int cq_jobs;
-       unsigned long flags;
-
-       cpu_id = find_next_online_cpu(pool);
-       BUG_ON(!cpu_online(cpu_id));
-
-       cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu_id);
-       thread = *per_cpu_ptr(pool->cpu_comp_threads, cpu_id);
-       BUG_ON(!cct || !thread);
-
-       spin_lock_irqsave(&cct->task_lock, flags);
-       cq_jobs = cct->cq_jobs;
-       spin_unlock_irqrestore(&cct->task_lock, flags);
-       if (cq_jobs > 0) {
-               cpu_id = find_next_online_cpu(pool);
-               cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu_id);
-               thread = *per_cpu_ptr(pool->cpu_comp_threads, cpu_id);
-               BUG_ON(!cct || !thread);
-       }
-       __queue_comp_task(__cq, cct, thread);
-}
-
-static void run_comp_task(struct ehca_cpu_comp_task *cct)
-{
-       struct ehca_cq *cq;
-
-       while (!list_empty(&cct->cq_list)) {
-               cq = list_entry(cct->cq_list.next, struct ehca_cq, entry);
-               spin_unlock_irq(&cct->task_lock);
-
-               comp_event_callback(cq);
-               if (atomic_dec_and_test(&cq->nr_events))
-                       wake_up(&cq->wait_completion);
-
-               spin_lock_irq(&cct->task_lock);
-               spin_lock(&cq->task_lock);
-               cq->nr_callbacks--;
-               if (!cq->nr_callbacks) {
-                       list_del_init(cct->cq_list.next);
-                       cct->cq_jobs--;
-               }
-               spin_unlock(&cq->task_lock);
-       }
-}
-
-static void comp_task_park(unsigned int cpu)
-{
-       struct ehca_cpu_comp_task *cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu);
-       struct ehca_cpu_comp_task *target;
-       struct task_struct *thread;
-       struct ehca_cq *cq, *tmp;
-       LIST_HEAD(list);
-
-       spin_lock_irq(&cct->task_lock);
-       cct->cq_jobs = 0;
-       cct->active = 0;
-       list_splice_init(&cct->cq_list, &list);
-       spin_unlock_irq(&cct->task_lock);
-
-       cpu = find_next_online_cpu(pool);
-       target = per_cpu_ptr(pool->cpu_comp_tasks, cpu);
-       thread = *per_cpu_ptr(pool->cpu_comp_threads, cpu);
-       spin_lock_irq(&target->task_lock);
-       list_for_each_entry_safe(cq, tmp, &list, entry) {
-               list_del(&cq->entry);
-               __queue_comp_task(cq, target, thread);
-       }
-       spin_unlock_irq(&target->task_lock);
-}
-
-static void comp_task_stop(unsigned int cpu, bool online)
-{
-       struct ehca_cpu_comp_task *cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu);
-
-       spin_lock_irq(&cct->task_lock);
-       cct->cq_jobs = 0;
-       cct->active = 0;
-       WARN_ON(!list_empty(&cct->cq_list));
-       spin_unlock_irq(&cct->task_lock);
-}
-
-static int comp_task_should_run(unsigned int cpu)
-{
-       struct ehca_cpu_comp_task *cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu);
-
-       return cct->cq_jobs;
-}
-
-static void comp_task(unsigned int cpu)
-{
-       struct ehca_cpu_comp_task *cct = this_cpu_ptr(pool->cpu_comp_tasks);
-       int cql_empty;
-
-       spin_lock_irq(&cct->task_lock);
-       cql_empty = list_empty(&cct->cq_list);
-       if (!cql_empty) {
-               __set_current_state(TASK_RUNNING);
-               run_comp_task(cct);
-       }
-       spin_unlock_irq(&cct->task_lock);
-}
-
-static struct smp_hotplug_thread comp_pool_threads = {
-       .thread_should_run      = comp_task_should_run,
-       .thread_fn              = comp_task,
-       .thread_comm            = "ehca_comp/%u",
-       .cleanup                = comp_task_stop,
-       .park                   = comp_task_park,
-};
-
-int ehca_create_comp_pool(void)
-{
-       int cpu, ret = -ENOMEM;
-
-       if (!ehca_scaling_code)
-               return 0;
-
-       pool = kzalloc(sizeof(struct ehca_comp_pool), GFP_KERNEL);
-       if (pool == NULL)
-               return -ENOMEM;
-
-       spin_lock_init(&pool->last_cpu_lock);
-       pool->last_cpu = cpumask_any(cpu_online_mask);
-
-       pool->cpu_comp_tasks = alloc_percpu(struct ehca_cpu_comp_task);
-       if (!pool->cpu_comp_tasks)
-               goto out_pool;
-
-       pool->cpu_comp_threads = alloc_percpu(struct task_struct *);
-       if (!pool->cpu_comp_threads)
-               goto out_tasks;
-
-       for_each_present_cpu(cpu) {
-               struct ehca_cpu_comp_task *cct;
-
-               cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu);
-               spin_lock_init(&cct->task_lock);
-               INIT_LIST_HEAD(&cct->cq_list);
-       }
-
-       comp_pool_threads.store = pool->cpu_comp_threads;
-       ret = smpboot_register_percpu_thread(&comp_pool_threads);
-       if (ret)
-               goto out_threads;
-
-       pr_info("eHCA scaling code enabled\n");
-       return ret;
-
-out_threads:
-       free_percpu(pool->cpu_comp_threads);
-out_tasks:
-       free_percpu(pool->cpu_comp_tasks);
-out_pool:
-       kfree(pool);
-       return ret;
-}
-
-void ehca_destroy_comp_pool(void)
-{
-       if (!ehca_scaling_code)
-               return;
-
-       smpboot_unregister_percpu_thread(&comp_pool_threads);
-
-       free_percpu(pool->cpu_comp_threads);
-       free_percpu(pool->cpu_comp_tasks);
-       kfree(pool);
-}
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.h b/drivers/infiniband/hw/ehca/ehca_irq.h
deleted file mode 100644 (file)
index 5370199..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- *  IBM eServer eHCA Infiniband device driver for Linux on POWER
- *
- *  Function definitions and structs for EQs, NEQs and interrupts
- *
- *  Authors: Heiko J Schick <schickhj@de.ibm.com>
- *           Khadija Souissi <souissi@de.ibm.com>
- *
- *  Copyright (c) 2005 IBM Corporation
- *
- *  All rights reserved.
- *
- *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
- *  BSD.
- *
- * OpenIB BSD License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __EHCA_IRQ_H
-#define __EHCA_IRQ_H
-
-
-struct ehca_shca;
-
-#include <linux/interrupt.h>
-#include <linux/types.h>
-
-int ehca_error_data(struct ehca_shca *shca, void *data, u64 resource);
-
-irqreturn_t ehca_interrupt_neq(int irq, void *dev_id);
-void ehca_tasklet_neq(unsigned long data);
-
-irqreturn_t ehca_interrupt_eq(int irq, void *dev_id);
-void ehca_tasklet_eq(unsigned long data);
-void ehca_process_eq(struct ehca_shca *shca, int is_irq);
-
-struct ehca_cpu_comp_task {
-       struct list_head cq_list;
-       spinlock_t task_lock;
-       int cq_jobs;
-       int active;
-};
-
-struct ehca_comp_pool {
-       struct ehca_cpu_comp_task __percpu *cpu_comp_tasks;
-       struct task_struct * __percpu *cpu_comp_threads;
-       int last_cpu;
-       spinlock_t last_cpu_lock;
-};
-
-int ehca_create_comp_pool(void);
-void ehca_destroy_comp_pool(void);
-
-#endif
diff --git a/drivers/infiniband/hw/ehca/ehca_iverbs.h b/drivers/infiniband/hw/ehca/ehca_iverbs.h
deleted file mode 100644 (file)
index 80e6a3d..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- *  IBM eServer eHCA Infiniband device driver for Linux on POWER
- *
- *  Function definitions for internal functions
- *
- *  Authors: Heiko J Schick <schickhj@de.ibm.com>
- *           Dietmar Decker <ddecker@de.ibm.com>
- *
- *  Copyright (c) 2005 IBM Corporation
- *
- *  All rights reserved.
- *
- *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
- *  BSD.
- *
- * OpenIB BSD License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __EHCA_IVERBS_H__
-#define __EHCA_IVERBS_H__
-
-#include "ehca_classes.h"
-
-int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props,
-                     struct ib_udata *uhw);
-
-int ehca_query_port(struct ib_device *ibdev, u8 port,
-                   struct ib_port_attr *props);
-
-enum rdma_protocol_type
-ehca_query_protocol(struct ib_device *device, u8 port_num);
-
-int ehca_query_sma_attr(struct ehca_shca *shca, u8 port,
-                       struct ehca_sma_attr *attr);
-
-int ehca_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 * pkey);
-
-int ehca_query_gid(struct ib_device *ibdev, u8 port, int index,
-                  union ib_gid *gid);
-
-int ehca_modify_port(struct ib_device *ibdev, u8 port, int port_modify_mask,
-                    struct ib_port_modify *props);
-
-struct ib_pd *ehca_alloc_pd(struct ib_device *device,
-                           struct ib_ucontext *context,
-                           struct ib_udata *udata);
-
-int ehca_dealloc_pd(struct ib_pd *pd);
-
-struct ib_ah *ehca_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr);
-
-int ehca_modify_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr);
-
-int ehca_query_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr);
-
-int ehca_destroy_ah(struct ib_ah *ah);
-
-struct ib_mr *ehca_get_dma_mr(struct ib_pd *pd, int mr_access_flags);
-
-struct ib_mr *ehca_reg_phys_mr(struct ib_pd *pd,
-                              struct ib_phys_buf *phys_buf_array,
-                              int num_phys_buf,
-                              int mr_access_flags, u64 *iova_start);
-
-struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
-                              u64 virt, int mr_access_flags,
-                              struct ib_udata *udata);
-
-int ehca_rereg_phys_mr(struct ib_mr *mr,
-                      int mr_rereg_mask,
-                      struct ib_pd *pd,
-                      struct ib_phys_buf *phys_buf_array,
-                      int num_phys_buf, int mr_access_flags, u64 *iova_start);
-
-int ehca_query_mr(struct ib_mr *mr, struct ib_mr_attr *mr_attr);
-
-int ehca_dereg_mr(struct ib_mr *mr);
-
-struct ib_mw *ehca_alloc_mw(struct ib_pd *pd, enum ib_mw_type type);
-
-int ehca_bind_mw(struct ib_qp *qp, struct ib_mw *mw,
-                struct ib_mw_bind *mw_bind);
-
-int ehca_dealloc_mw(struct ib_mw *mw);
-
-struct ib_fmr *ehca_alloc_fmr(struct ib_pd *pd,
-                             int mr_access_flags,
-                             struct ib_fmr_attr *fmr_attr);
-
-int ehca_map_phys_fmr(struct ib_fmr *fmr,
-                     u64 *page_list, int list_len, u64 iova);
-
-int ehca_unmap_fmr(struct list_head *fmr_list);
-
-int ehca_dealloc_fmr(struct ib_fmr *fmr);
-
-enum ehca_eq_type {
-       EHCA_EQ = 0, /* Event Queue              */
-       EHCA_NEQ     /* Notification Event Queue */
-};
-
-int ehca_create_eq(struct ehca_shca *shca, struct ehca_eq *eq,
-                  enum ehca_eq_type type, const u32 length);
-
-int ehca_destroy_eq(struct ehca_shca *shca, struct ehca_eq *eq);
-
-void *ehca_poll_eq(struct ehca_shca *shca, struct ehca_eq *eq);
-
-
-struct ib_cq *ehca_create_cq(struct ib_device *device,
-                            const struct ib_cq_init_attr *attr,
-                            struct ib_ucontext *context,
-                            struct ib_udata *udata);
-
-int ehca_destroy_cq(struct ib_cq *cq);
-
-int ehca_resize_cq(struct ib_cq *cq, int cqe, struct ib_udata *udata);
-
-int ehca_poll_cq(struct ib_cq *cq, int num_entries, struct ib_wc *wc);
-
-int ehca_peek_cq(struct ib_cq *cq, int wc_cnt);
-
-int ehca_req_notify_cq(struct ib_cq *cq, enum ib_cq_notify_flags notify_flags);
-
-struct ib_qp *ehca_create_qp(struct ib_pd *pd,
-                            struct ib_qp_init_attr *init_attr,
-                            struct ib_udata *udata);
-
-int ehca_destroy_qp(struct ib_qp *qp);
-
-int ehca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
-                  struct ib_udata *udata);
-
-int ehca_query_qp(struct ib_qp *qp, struct ib_qp_attr *qp_attr,
-                 int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr);
-
-int ehca_post_send(struct ib_qp *qp, struct ib_send_wr *send_wr,
-                  struct ib_send_wr **bad_send_wr);
-
-int ehca_post_recv(struct ib_qp *qp, struct ib_recv_wr *recv_wr,
-                  struct ib_recv_wr **bad_recv_wr);
-
-int ehca_post_srq_recv(struct ib_srq *srq,
-                      struct ib_recv_wr *recv_wr,
-                      struct ib_recv_wr **bad_recv_wr);
-
-struct ib_srq *ehca_create_srq(struct ib_pd *pd,
-                              struct ib_srq_init_attr *init_attr,
-                              struct ib_udata *udata);
-
-int ehca_modify_srq(struct ib_srq *srq, struct ib_srq_attr *attr,
-                   enum ib_srq_attr_mask attr_mask, struct ib_udata *udata);
-
-int ehca_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr);
-
-int ehca_destroy_srq(struct ib_srq *srq);
-
-u64 ehca_define_sqp(struct ehca_shca *shca, struct ehca_qp *ibqp,
-                   struct ib_qp_init_attr *qp_init_attr);
-
-int ehca_attach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid);
-
-int ehca_detach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid);
-
-struct ib_ucontext *ehca_alloc_ucontext(struct ib_device *device,
-                                       struct ib_udata *udata);
-
-int ehca_dealloc_ucontext(struct ib_ucontext *context);
-
-int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma);
-
-int ehca_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
-                    const struct ib_wc *in_wc, const struct ib_grh *in_grh,
-                    const struct ib_mad_hdr *in, size_t in_mad_size,
-                    struct ib_mad_hdr *out, size_t *out_mad_size,
-                    u16 *out_mad_pkey_index);
-
-void ehca_poll_eqs(unsigned long data);
-
-int ehca_calc_ipd(struct ehca_shca *shca, int port,
-                 enum ib_rate path_rate, u32 *ipd);
-
-void ehca_add_to_err_list(struct ehca_qp *qp, int on_sq);
-
-#ifdef CONFIG_PPC_64K_PAGES
-void *ehca_alloc_fw_ctrlblock(gfp_t flags);
-void ehca_free_fw_ctrlblock(void *ptr);
-#else
-#define ehca_alloc_fw_ctrlblock(flags) ((void *)get_zeroed_page(flags))
-#define ehca_free_fw_ctrlblock(ptr) free_page((unsigned long)(ptr))
-#endif
-
-void ehca_recover_sqp(struct ib_qp *sqp);
-
-#endif
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
deleted file mode 100644 (file)
index 8246418..0000000
+++ /dev/null
@@ -1,1123 +0,0 @@
-/*
- *  IBM eServer eHCA Infiniband device driver for Linux on POWER
- *
- *  module start stop, hca detection
- *
- *  Authors: Heiko J Schick <schickhj@de.ibm.com>
- *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
- *           Joachim Fenkes <fenkes@de.ibm.com>
- *
- *  Copyright (c) 2005 IBM Corporation
- *
- *  All rights reserved.
- *
- *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
- *  BSD.
- *
- * OpenIB BSD License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifdef CONFIG_PPC_64K_PAGES
-#include <linux/slab.h>
-#endif
-
-#include <linux/notifier.h>
-#include <linux/memory.h>
-#include <rdma/ib_mad.h>
-#include "ehca_classes.h"
-#include "ehca_iverbs.h"
-#include "ehca_mrmw.h"
-#include "ehca_tools.h"
-#include "hcp_if.h"
-
-#define HCAD_VERSION "0029"
-
-MODULE_LICENSE("Dual BSD/GPL");
-MODULE_AUTHOR("Christoph Raisch <raisch@de.ibm.com>");
-MODULE_DESCRIPTION("IBM eServer HCA InfiniBand Device Driver");
-MODULE_VERSION(HCAD_VERSION);
-
-static bool ehca_open_aqp1    = 0;
-static int ehca_hw_level      = 0;
-static bool ehca_poll_all_eqs = 1;
-
-int ehca_debug_level   = 0;
-int ehca_nr_ports      = -1;
-bool ehca_use_hp_mr    = 0;
-int ehca_port_act_time = 30;
-int ehca_static_rate   = -1;
-bool ehca_scaling_code = 0;
-int ehca_lock_hcalls   = -1;
-int ehca_max_cq        = -1;
-int ehca_max_qp        = -1;
-
-module_param_named(open_aqp1,     ehca_open_aqp1,     bool, S_IRUGO);
-module_param_named(debug_level,   ehca_debug_level,   int,  S_IRUGO);
-module_param_named(hw_level,      ehca_hw_level,      int,  S_IRUGO);
-module_param_named(nr_ports,      ehca_nr_ports,      int,  S_IRUGO);
-module_param_named(use_hp_mr,     ehca_use_hp_mr,     bool, S_IRUGO);
-module_param_named(port_act_time, ehca_port_act_time, int,  S_IRUGO);
-module_param_named(poll_all_eqs,  ehca_poll_all_eqs,  bool, S_IRUGO);
-module_param_named(static_rate,   ehca_static_rate,   int,  S_IRUGO);
-module_param_named(scaling_code,  ehca_scaling_code,  bool, S_IRUGO);
-module_param_named(lock_hcalls,   ehca_lock_hcalls,   bint, S_IRUGO);
-module_param_named(number_of_cqs, ehca_max_cq,        int,  S_IRUGO);
-module_param_named(number_of_qps, ehca_max_qp,        int,  S_IRUGO);
-
-MODULE_PARM_DESC(open_aqp1,
-                "Open AQP1 on startup (default: no)");
-MODULE_PARM_DESC(debug_level,
-                "Amount of debug output (0: none (default), 1: traces, "
-                "2: some dumps, 3: lots)");
-MODULE_PARM_DESC(hw_level,
-                "Hardware level (0: autosensing (default), "
-                "0x10..0x14: eHCA, 0x20..0x23: eHCA2)");
-MODULE_PARM_DESC(nr_ports,
-                "number of connected ports (-1: autodetect (default), "
-                "1: port one only, 2: two ports)");
-MODULE_PARM_DESC(use_hp_mr,
-                "Use high performance MRs (default: no)");
-MODULE_PARM_DESC(port_act_time,
-                "Time to wait for port activation (default: 30 sec)");
-MODULE_PARM_DESC(poll_all_eqs,
-                "Poll all event queues periodically (default: yes)");
-MODULE_PARM_DESC(static_rate,
-                "Set permanent static rate (default: no static rate)");
-MODULE_PARM_DESC(scaling_code,
-                "Enable scaling code (default: no)");
-MODULE_PARM_DESC(lock_hcalls,
-                "Serialize all hCalls made by the driver "
-                "(default: autodetect)");
-MODULE_PARM_DESC(number_of_cqs,
-               "Max number of CQs which can be allocated "
-               "(default: autodetect)");
-MODULE_PARM_DESC(number_of_qps,
-               "Max number of QPs which can be allocated "
-               "(default: autodetect)");
-
-DEFINE_RWLOCK(ehca_qp_idr_lock);
-DEFINE_RWLOCK(ehca_cq_idr_lock);
-DEFINE_IDR(ehca_qp_idr);
-DEFINE_IDR(ehca_cq_idr);
-
-static LIST_HEAD(shca_list); /* list of all registered ehcas */
-DEFINE_SPINLOCK(shca_list_lock);
-
-static struct timer_list poll_eqs_timer;
-
-#ifdef CONFIG_PPC_64K_PAGES
-static struct kmem_cache *ctblk_cache;
-
-void *ehca_alloc_fw_ctrlblock(gfp_t flags)
-{
-       void *ret = kmem_cache_zalloc(ctblk_cache, flags);
-       if (!ret)
-               ehca_gen_err("Out of memory for ctblk");
-       return ret;
-}
-
-void ehca_free_fw_ctrlblock(void *ptr)
-{
-       if (ptr)
-               kmem_cache_free(ctblk_cache, ptr);
-
-}
-#endif
-
-int ehca2ib_return_code(u64 ehca_rc)
-{
-       switch (ehca_rc) {
-       case H_SUCCESS:
-               return 0;
-       case H_RESOURCE:             /* Resource in use */
-       case H_BUSY:
-               return -EBUSY;
-       case H_NOT_ENOUGH_RESOURCES: /* insufficient resources */
-       case H_CONSTRAINED:          /* resource constraint */
-       case H_NO_MEM:
-               return -ENOMEM;
-       default:
-               return -EINVAL;
-       }
-}
-
-static int ehca_create_slab_caches(void)
-{
-       int ret;
-
-       ret = ehca_init_pd_cache();
-       if (ret) {
-               ehca_gen_err("Cannot create PD SLAB cache.");
-               return ret;
-       }
-
-       ret = ehca_init_cq_cache();
-       if (ret) {
-               ehca_gen_err("Cannot create CQ SLAB cache.");
-               goto create_slab_caches2;
-       }
-
-       ret = ehca_init_qp_cache();
-       if (ret) {
-               ehca_gen_err("Cannot create QP SLAB cache.");
-               goto create_slab_caches3;
-       }
-
-       ret = ehca_init_av_cache();
-       if (ret) {
-               ehca_gen_err("Cannot create AV SLAB cache.");
-               goto create_slab_caches4;
-       }
-
-       ret = ehca_init_mrmw_cache();
-       if (ret) {
-               ehca_gen_err("Cannot create MR&MW SLAB cache.");
-               goto create_slab_caches5;
-       }
-
-       ret = ehca_init_small_qp_cache();
-       if (ret) {
-               ehca_gen_err("Cannot create small queue SLAB cache.");
-               goto create_slab_caches6;
-       }
-
-#ifdef CONFIG_PPC_64K_PAGES
-       ctblk_cache = kmem_cache_create("ehca_cache_ctblk",
-                                       EHCA_PAGESIZE, H_CB_ALIGNMENT,
-                                       SLAB_HWCACHE_ALIGN,
-                                       NULL);
-       if (!ctblk_cache) {
-               ehca_gen_err("Cannot create ctblk SLAB cache.");
-               ehca_cleanup_small_qp_cache();
-               ret = -ENOMEM;
-               goto create_slab_caches6;
-       }
-#endif
-       return 0;
-
-create_slab_caches6:
-       ehca_cleanup_mrmw_cache();
-
-create_slab_caches5:
-       ehca_cleanup_av_cache();
-
-create_slab_caches4:
-       ehca_cleanup_qp_cache();
-
-create_slab_caches3:
-       ehca_cleanup_cq_cache();
-
-create_slab_caches2:
-       ehca_cleanup_pd_cache();
-
-       return ret;
-}
-
-static void ehca_destroy_slab_caches(void)
-{
-       ehca_cleanup_small_qp_cache();
-       ehca_cleanup_mrmw_cache();
-       ehca_cleanup_av_cache();
-       ehca_cleanup_qp_cache();
-       ehca_cleanup_cq_cache();
-       ehca_cleanup_pd_cache();
-#ifdef CONFIG_PPC_64K_PAGES
-       if (ctblk_cache)
-               kmem_cache_destroy(ctblk_cache);
-#endif
-}
-
-#define EHCA_HCAAVER  EHCA_BMASK_IBM(32, 39)
-#define EHCA_REVID    EHCA_BMASK_IBM(40, 63)
-
-static struct cap_descr {
-       u64 mask;
-       char *descr;
-} hca_cap_descr[] = {
-       { HCA_CAP_AH_PORT_NR_CHECK, "HCA_CAP_AH_PORT_NR_CHECK" },
-       { HCA_CAP_ATOMIC, "HCA_CAP_ATOMIC" },
-       { HCA_CAP_AUTO_PATH_MIG, "HCA_CAP_AUTO_PATH_MIG" },
-       { HCA_CAP_BAD_P_KEY_CTR, "HCA_CAP_BAD_P_KEY_CTR" },
-       { HCA_CAP_SQD_RTS_PORT_CHANGE, "HCA_CAP_SQD_RTS_PORT_CHANGE" },
-       { HCA_CAP_CUR_QP_STATE_MOD, "HCA_CAP_CUR_QP_STATE_MOD" },
-       { HCA_CAP_INIT_TYPE, "HCA_CAP_INIT_TYPE" },
-       { HCA_CAP_PORT_ACTIVE_EVENT, "HCA_CAP_PORT_ACTIVE_EVENT" },
-       { HCA_CAP_Q_KEY_VIOL_CTR, "HCA_CAP_Q_KEY_VIOL_CTR" },
-       { HCA_CAP_WQE_RESIZE, "HCA_CAP_WQE_RESIZE" },
-       { HCA_CAP_RAW_PACKET_MCAST, "HCA_CAP_RAW_PACKET_MCAST" },
-       { HCA_CAP_SHUTDOWN_PORT, "HCA_CAP_SHUTDOWN_PORT" },
-       { HCA_CAP_RC_LL_QP, "HCA_CAP_RC_LL_QP" },
-       { HCA_CAP_SRQ, "HCA_CAP_SRQ" },
-       { HCA_CAP_UD_LL_QP, "HCA_CAP_UD_LL_QP" },
-       { HCA_CAP_RESIZE_MR, "HCA_CAP_RESIZE_MR" },
-       { HCA_CAP_MINI_QP, "HCA_CAP_MINI_QP" },
-       { HCA_CAP_H_ALLOC_RES_SYNC, "HCA_CAP_H_ALLOC_RES_SYNC" },
-};
-
-static int ehca_sense_attributes(struct ehca_shca *shca)
-{
-       int i, ret = 0;
-       u64 h_ret;
-       struct hipz_query_hca *rblock;
-       struct hipz_query_port *port;
-       const char *loc_code;
-
-       static const u32 pgsize_map[] = {
-               HCA_CAP_MR_PGSIZE_4K,  0x1000,
-               HCA_CAP_MR_PGSIZE_64K, 0x10000,
-               HCA_CAP_MR_PGSIZE_1M,  0x100000,
-               HCA_CAP_MR_PGSIZE_16M, 0x1000000,
-       };
-
-       ehca_gen_dbg("Probing adapter %s...",
-                    shca->ofdev->dev.of_node->full_name);
-       loc_code = of_get_property(shca->ofdev->dev.of_node, "ibm,loc-code",
-                                  NULL);
-       if (loc_code)
-               ehca_gen_dbg(" ... location lode=%s", loc_code);
-
-       rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
-       if (!rblock) {
-               ehca_gen_err("Cannot allocate rblock memory.");
-               return -ENOMEM;
-       }
-
-       h_ret = hipz_h_query_hca(shca->ipz_hca_handle, rblock);
-       if (h_ret != H_SUCCESS) {
-               ehca_gen_err("Cannot query device properties. h_ret=%lli",
-                            h_ret);
-               ret = -EPERM;
-               goto sense_attributes1;
-       }
-
-       if (ehca_nr_ports == 1)
-               shca->num_ports = 1;
-       else
-               shca->num_ports = (u8)rblock->num_ports;
-
-       ehca_gen_dbg(" ... found %x ports", rblock->num_ports);
-
-       if (ehca_hw_level == 0) {
-               u32 hcaaver;
-               u32 revid;
-
-               hcaaver = EHCA_BMASK_GET(EHCA_HCAAVER, rblock->hw_ver);
-               revid   = EHCA_BMASK_GET(EHCA_REVID, rblock->hw_ver);
-
-               ehca_gen_dbg(" ... hardware version=%x:%x", hcaaver, revid);
-
-               if (hcaaver == 1) {
-                       if (revid <= 3)
-                               shca->hw_level = 0x10 | (revid + 1);
-                       else
-                               shca->hw_level = 0x14;
-               } else if (hcaaver == 2) {
-                       if (revid == 0)
-                               shca->hw_level = 0x21;
-                       else if (revid == 0x10)
-                               shca->hw_level = 0x22;
-                       else if (revid == 0x20 || revid == 0x21)
-                               shca->hw_level = 0x23;
-               }
-
-               if (!shca->hw_level) {
-                       ehca_gen_warn("unknown hardware version"
-                                     " - assuming default level");
-                       shca->hw_level = 0x22;
-               }
-       } else
-               shca->hw_level = ehca_hw_level;
-       ehca_gen_dbg(" ... hardware level=%x", shca->hw_level);
-
-       shca->hca_cap = rblock->hca_cap_indicators;
-       ehca_gen_dbg(" ... HCA capabilities:");
-       for (i = 0; i < ARRAY_SIZE(hca_cap_descr); i++)
-               if (EHCA_BMASK_GET(hca_cap_descr[i].mask, shca->hca_cap))
-                       ehca_gen_dbg("   %s", hca_cap_descr[i].descr);
-
-       /* Autodetect hCall locking -- the "H_ALLOC_RESOURCE synced" flag is
-        * a firmware property, so it's valid across all adapters
-        */
-       if (ehca_lock_hcalls == -1)
-               ehca_lock_hcalls = !EHCA_BMASK_GET(HCA_CAP_H_ALLOC_RES_SYNC,
-                                       shca->hca_cap);
-
-       /* translate supported MR page sizes; always support 4K */
-       shca->hca_cap_mr_pgsize = EHCA_PAGESIZE;
-       for (i = 0; i < ARRAY_SIZE(pgsize_map); i += 2)
-               if (rblock->memory_page_size_supported & pgsize_map[i])
-                       shca->hca_cap_mr_pgsize |= pgsize_map[i + 1];
-
-       /* Set maximum number of CQs and QPs to calculate EQ size */
-       if (shca->max_num_qps == -1)
-               shca->max_num_qps = min_t(int, rblock->max_qp,
-                                         EHCA_MAX_NUM_QUEUES);
-       else if (shca->max_num_qps < 1 || shca->max_num_qps > rblock->max_qp) {
-               ehca_gen_warn("The requested number of QPs is out of range "
-                             "(1 - %i) specified by HW. Value is set to %i",
-                             rblock->max_qp, rblock->max_qp);
-               shca->max_num_qps = rblock->max_qp;
-       }
-
-       if (shca->max_num_cqs == -1)
-               shca->max_num_cqs = min_t(int, rblock->max_cq,
-                                         EHCA_MAX_NUM_QUEUES);
-       else if (shca->max_num_cqs < 1 || shca->max_num_cqs > rblock->max_cq) {
-               ehca_gen_warn("The requested number of CQs is out of range "
-                             "(1 - %i) specified by HW. Value is set to %i",
-                             rblock->max_cq, rblock->max_cq);
-       }
-
-       /* query max MTU from first port -- it's the same for all ports */
-       port = (struct hipz_query_port *)rblock;
-       h_ret = hipz_h_query_port(shca->ipz_hca_handle, 1, port);
-       if (h_ret != H_SUCCESS) {
-               ehca_gen_err("Cannot query port properties. h_ret=%lli",
-                            h_ret);
-               ret = -EPERM;
-               goto sense_attributes1;
-       }
-
-       shca->max_mtu = port->max_mtu;
-
-sense_attributes1:
-       ehca_free_fw_ctrlblock(rblock);
-       return ret;
-}
-
-static int init_node_guid(struct ehca_shca *shca)
-{
-       int ret = 0;
-       struct hipz_query_hca *rblock;
-
-       rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
-       if (!rblock) {
-               ehca_err(&shca->ib_device, "Can't allocate rblock memory.");
-               return -ENOMEM;
-       }
-
-       if (hipz_h_query_hca(shca->ipz_hca_handle, rblock) != H_SUCCESS) {
-               ehca_err(&shca->ib_device, "Can't query device properties");
-               ret = -EINVAL;
-               goto init_node_guid1;
-       }
-
-       memcpy(&shca->ib_device.node_guid, &rblock->node_guid, sizeof(u64));
-
-init_node_guid1:
-       ehca_free_fw_ctrlblock(rblock);
-       return ret;
-}
-
-static int ehca_port_immutable(struct ib_device *ibdev, u8 port_num,
-                              struct ib_port_immutable *immutable)
-{
-       struct ib_port_attr attr;
-       int err;
-
-       err = ehca_query_port(ibdev, port_num, &attr);
-       if (err)
-               return err;
-
-       immutable->pkey_tbl_len = attr.pkey_tbl_len;
-       immutable->gid_tbl_len = attr.gid_tbl_len;
-       immutable->core_cap_flags = RDMA_CORE_PORT_IBA_IB;
-       immutable->max_mad_size = IB_MGMT_MAD_SIZE;
-
-       return 0;
-}
-
-static int ehca_init_device(struct ehca_shca *shca)
-{
-       int ret;
-
-       ret = init_node_guid(shca);
-       if (ret)
-               return ret;
-
-       strlcpy(shca->ib_device.name, "ehca%d", IB_DEVICE_NAME_MAX);
-       shca->ib_device.owner               = THIS_MODULE;
-
-       shca->ib_device.uverbs_abi_ver      = 8;
-       shca->ib_device.uverbs_cmd_mask     =
-               (1ull << IB_USER_VERBS_CMD_GET_CONTEXT)         |
-               (1ull << IB_USER_VERBS_CMD_QUERY_DEVICE)        |
-               (1ull << IB_USER_VERBS_CMD_QUERY_PORT)          |
-               (1ull << IB_USER_VERBS_CMD_ALLOC_PD)            |
-               (1ull << IB_USER_VERBS_CMD_DEALLOC_PD)          |
-               (1ull << IB_USER_VERBS_CMD_REG_MR)              |
-               (1ull << IB_USER_VERBS_CMD_DEREG_MR)            |
-               (1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) |
-               (1ull << IB_USER_VERBS_CMD_CREATE_CQ)           |
-               (1ull << IB_USER_VERBS_CMD_DESTROY_CQ)          |
-               (1ull << IB_USER_VERBS_CMD_CREATE_QP)           |
-               (1ull << IB_USER_VERBS_CMD_MODIFY_QP)           |
-               (1ull << IB_USER_VERBS_CMD_QUERY_QP)            |
-               (1ull << IB_USER_VERBS_CMD_DESTROY_QP)          |
-               (1ull << IB_USER_VERBS_CMD_ATTACH_MCAST)        |
-               (1ull << IB_USER_VERBS_CMD_DETACH_MCAST);
-
-       shca->ib_device.node_type           = RDMA_NODE_IB_CA;
-       shca->ib_device.phys_port_cnt       = shca->num_ports;
-       shca->ib_device.num_comp_vectors    = 1;
-       shca->ib_device.dma_device          = &shca->ofdev->dev;
-       shca->ib_device.query_device        = ehca_query_device;
-       shca->ib_device.query_port          = ehca_query_port;
-       shca->ib_device.query_gid           = ehca_query_gid;
-       shca->ib_device.query_pkey          = ehca_query_pkey;
-       /* shca->in_device.modify_device    = ehca_modify_device    */
-       shca->ib_device.modify_port         = ehca_modify_port;
-       shca->ib_device.alloc_ucontext      = ehca_alloc_ucontext;
-       shca->ib_device.dealloc_ucontext    = ehca_dealloc_ucontext;
-       shca->ib_device.alloc_pd            = ehca_alloc_pd;
-       shca->ib_device.dealloc_pd          = ehca_dealloc_pd;
-       shca->ib_device.create_ah           = ehca_create_ah;
-       /* shca->ib_device.modify_ah        = ehca_modify_ah;       */
-       shca->ib_device.query_ah            = ehca_query_ah;
-       shca->ib_device.destroy_ah          = ehca_destroy_ah;
-       shca->ib_device.create_qp           = ehca_create_qp;
-       shca->ib_device.modify_qp           = ehca_modify_qp;
-       shca->ib_device.query_qp            = ehca_query_qp;
-       shca->ib_device.destroy_qp          = ehca_destroy_qp;
-       shca->ib_device.post_send           = ehca_post_send;
-       shca->ib_device.post_recv           = ehca_post_recv;
-       shca->ib_device.create_cq           = ehca_create_cq;
-       shca->ib_device.destroy_cq          = ehca_destroy_cq;
-       shca->ib_device.resize_cq           = ehca_resize_cq;
-       shca->ib_device.poll_cq             = ehca_poll_cq;
-       /* shca->ib_device.peek_cq          = ehca_peek_cq;         */
-       shca->ib_device.req_notify_cq       = ehca_req_notify_cq;
-       /* shca->ib_device.req_ncomp_notif  = ehca_req_ncomp_notif; */
-       shca->ib_device.get_dma_mr          = ehca_get_dma_mr;
-       shca->ib_device.reg_phys_mr         = ehca_reg_phys_mr;
-       shca->ib_device.reg_user_mr         = ehca_reg_user_mr;
-       shca->ib_device.query_mr            = ehca_query_mr;
-       shca->ib_device.dereg_mr            = ehca_dereg_mr;
-       shca->ib_device.rereg_phys_mr       = ehca_rereg_phys_mr;
-       shca->ib_device.alloc_mw            = ehca_alloc_mw;
-       shca->ib_device.bind_mw             = ehca_bind_mw;
-       shca->ib_device.dealloc_mw          = ehca_dealloc_mw;
-       shca->ib_device.alloc_fmr           = ehca_alloc_fmr;
-       shca->ib_device.map_phys_fmr        = ehca_map_phys_fmr;
-       shca->ib_device.unmap_fmr           = ehca_unmap_fmr;
-       shca->ib_device.dealloc_fmr         = ehca_dealloc_fmr;
-       shca->ib_device.attach_mcast        = ehca_attach_mcast;
-       shca->ib_device.detach_mcast        = ehca_detach_mcast;
-       shca->ib_device.process_mad         = ehca_process_mad;
-       shca->ib_device.mmap                = ehca_mmap;
-       shca->ib_device.dma_ops             = &ehca_dma_mapping_ops;
-       shca->ib_device.get_port_immutable  = ehca_port_immutable;
-
-       if (EHCA_BMASK_GET(HCA_CAP_SRQ, shca->hca_cap)) {
-               shca->ib_device.uverbs_cmd_mask |=
-                       (1ull << IB_USER_VERBS_CMD_CREATE_SRQ) |
-                       (1ull << IB_USER_VERBS_CMD_MODIFY_SRQ) |
-                       (1ull << IB_USER_VERBS_CMD_QUERY_SRQ) |
-                       (1ull << IB_USER_VERBS_CMD_DESTROY_SRQ);
-
-               shca->ib_device.create_srq          = ehca_create_srq;
-               shca->ib_device.modify_srq          = ehca_modify_srq;
-               shca->ib_device.query_srq           = ehca_query_srq;
-               shca->ib_device.destroy_srq         = ehca_destroy_srq;
-               shca->ib_device.post_srq_recv       = ehca_post_srq_recv;
-       }
-
-       return ret;
-}
-
-static int ehca_create_aqp1(struct ehca_shca *shca, u32 port)
-{
-       struct ehca_sport *sport = &shca->sport[port - 1];
-       struct ib_cq *ibcq;
-       struct ib_qp *ibqp;
-       struct ib_qp_init_attr qp_init_attr;
-       struct ib_cq_init_attr cq_attr = {};
-       int ret;
-
-       if (sport->ibcq_aqp1) {
-               ehca_err(&shca->ib_device, "AQP1 CQ is already created.");
-               return -EPERM;
-       }
-
-       cq_attr.cqe = 10;
-       ibcq = ib_create_cq(&shca->ib_device, NULL, NULL, (void *)(-1),
-                           &cq_attr);
-       if (IS_ERR(ibcq)) {
-               ehca_err(&shca->ib_device, "Cannot create AQP1 CQ.");
-               return PTR_ERR(ibcq);
-       }
-       sport->ibcq_aqp1 = ibcq;
-
-       if (sport->ibqp_sqp[IB_QPT_GSI]) {
-               ehca_err(&shca->ib_device, "AQP1 QP is already created.");
-               ret = -EPERM;
-               goto create_aqp1;
-       }
-
-       memset(&qp_init_attr, 0, sizeof(struct ib_qp_init_attr));
-       qp_init_attr.send_cq          = ibcq;
-       qp_init_attr.recv_cq          = ibcq;
-       qp_init_attr.sq_sig_type      = IB_SIGNAL_ALL_WR;
-       qp_init_attr.cap.max_send_wr  = 100;
-       qp_init_attr.cap.max_recv_wr  = 100;
-       qp_init_attr.cap.max_send_sge = 2;
-       qp_init_attr.cap.max_recv_sge = 1;
-       qp_init_attr.qp_type          = IB_QPT_GSI;
-       qp_init_attr.port_num         = port;
-       qp_init_attr.qp_context       = NULL;
-       qp_init_attr.event_handler    = NULL;
-       qp_init_attr.srq              = NULL;
-
-       ibqp = ib_create_qp(&shca->pd->ib_pd, &qp_init_attr);
-       if (IS_ERR(ibqp)) {
-               ehca_err(&shca->ib_device, "Cannot create AQP1 QP.");
-               ret = PTR_ERR(ibqp);
-               goto create_aqp1;
-       }
-       sport->ibqp_sqp[IB_QPT_GSI] = ibqp;
-
-       return 0;
-
-create_aqp1:
-       ib_destroy_cq(sport->ibcq_aqp1);
-       return ret;
-}
-
-static int ehca_destroy_aqp1(struct ehca_sport *sport)
-{
-       int ret;
-
-       ret = ib_destroy_qp(sport->ibqp_sqp[IB_QPT_GSI]);
-       if (ret) {
-               ehca_gen_err("Cannot destroy AQP1 QP. ret=%i", ret);
-               return ret;
-       }
-
-       ret = ib_destroy_cq(sport->ibcq_aqp1);
-       if (ret)
-               ehca_gen_err("Cannot destroy AQP1 CQ. ret=%i", ret);
-
-       return ret;
-}
-
-static ssize_t ehca_show_debug_level(struct device_driver *ddp, char *buf)
-{
-       return snprintf(buf, PAGE_SIZE, "%d\n", ehca_debug_level);
-}
-
-static ssize_t ehca_store_debug_level(struct device_driver *ddp,
-                                     const char *buf, size_t count)
-{
-       int value = (*buf) - '0';
-       if (value >= 0 && value <= 9)
-               ehca_debug_level = value;
-       return 1;
-}
-
-static DRIVER_ATTR(debug_level, S_IRUSR | S_IWUSR,
-                  ehca_show_debug_level, ehca_store_debug_level);
-
-static struct attribute *ehca_drv_attrs[] = {
-       &driver_attr_debug_level.attr,
-       NULL
-};
-
-static struct attribute_group ehca_drv_attr_grp = {
-       .attrs = ehca_drv_attrs
-};
-
-static const struct attribute_group *ehca_drv_attr_groups[] = {
-       &ehca_drv_attr_grp,
-       NULL,
-};
-
-#define EHCA_RESOURCE_ATTR(name)                                           \
-static ssize_t  ehca_show_##name(struct device *dev,                       \
-                                struct device_attribute *attr,            \
-                                char *buf)                                \
-{                                                                         \
-       struct ehca_shca *shca;                                            \
-       struct hipz_query_hca *rblock;                                     \
-       int data;                                                          \
-                                                                          \
-       shca = dev_get_drvdata(dev);                                       \
-                                                                          \
-       rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);                      \
-       if (!rblock) {                                                     \
-               dev_err(dev, "Can't allocate rblock memory.\n");           \
-               return 0;                                                  \
-       }                                                                  \
-                                                                          \
-       if (hipz_h_query_hca(shca->ipz_hca_handle, rblock) != H_SUCCESS) { \
-               dev_err(dev, "Can't query device properties\n");           \
-               ehca_free_fw_ctrlblock(rblock);                            \
-               return 0;                                                  \
-       }                                                                  \
-                                                                          \
-       data = rblock->name;                                               \
-       ehca_free_fw_ctrlblock(rblock);                                    \
-                                                                          \
-       if ((strcmp(#name, "num_ports") == 0) && (ehca_nr_ports == 1))     \
-               return snprintf(buf, 256, "1\n");                          \
-       else                                                               \
-               return snprintf(buf, 256, "%d\n", data);                   \
-                                                                          \
-}                                                                         \
-static DEVICE_ATTR(name, S_IRUGO, ehca_show_##name, NULL);
-
-EHCA_RESOURCE_ATTR(num_ports);
-EHCA_RESOURCE_ATTR(hw_ver);
-EHCA_RESOURCE_ATTR(max_eq);
-EHCA_RESOURCE_ATTR(cur_eq);
-EHCA_RESOURCE_ATTR(max_cq);
-EHCA_RESOURCE_ATTR(cur_cq);
-EHCA_RESOURCE_ATTR(max_qp);
-EHCA_RESOURCE_ATTR(cur_qp);
-EHCA_RESOURCE_ATTR(max_mr);
-EHCA_RESOURCE_ATTR(cur_mr);
-EHCA_RESOURCE_ATTR(max_mw);
-EHCA_RESOURCE_ATTR(cur_mw);
-EHCA_RESOURCE_ATTR(max_pd);
-EHCA_RESOURCE_ATTR(max_ah);
-
-static ssize_t ehca_show_adapter_handle(struct device *dev,
-                                       struct device_attribute *attr,
-                                       char *buf)
-{
-       struct ehca_shca *shca = dev_get_drvdata(dev);
-
-       return sprintf(buf, "%llx\n", shca->ipz_hca_handle.handle);
-
-}
-static DEVICE_ATTR(adapter_handle, S_IRUGO, ehca_show_adapter_handle, NULL);
-
-static struct attribute *ehca_dev_attrs[] = {
-       &dev_attr_adapter_handle.attr,
-       &dev_attr_num_ports.attr,
-       &dev_attr_hw_ver.attr,
-       &dev_attr_max_eq.attr,
-       &dev_attr_cur_eq.attr,
-       &dev_attr_max_cq.attr,
-       &dev_attr_cur_cq.attr,
-       &dev_attr_max_qp.attr,
-       &dev_attr_cur_qp.attr,
-       &dev_attr_max_mr.attr,
-       &dev_attr_cur_mr.attr,
-       &dev_attr_max_mw.attr,
-       &dev_attr_cur_mw.attr,
-       &dev_attr_max_pd.attr,
-       &dev_attr_max_ah.attr,
-       NULL
-};
-
-static struct attribute_group ehca_dev_attr_grp = {
-       .attrs = ehca_dev_attrs
-};
-
-static int ehca_probe(struct platform_device *dev)
-{
-       struct ehca_shca *shca;
-       const u64 *handle;
-       struct ib_pd *ibpd;
-       int ret, i, eq_size;
-       unsigned long flags;
-
-       handle = of_get_property(dev->dev.of_node, "ibm,hca-handle", NULL);
-       if (!handle) {
-               ehca_gen_err("Cannot get eHCA handle for adapter: %s.",
-                            dev->dev.of_node->full_name);
-               return -ENODEV;
-       }
-
-       if (!(*handle)) {
-               ehca_gen_err("Wrong eHCA handle for adapter: %s.",
-                            dev->dev.of_node->full_name);
-               return -ENODEV;
-       }
-
-       shca = (struct ehca_shca *)ib_alloc_device(sizeof(*shca));
-       if (!shca) {
-               ehca_gen_err("Cannot allocate shca memory.");
-               return -ENOMEM;
-       }
-
-       mutex_init(&shca->modify_mutex);
-       atomic_set(&shca->num_cqs, 0);
-       atomic_set(&shca->num_qps, 0);
-       shca->max_num_qps = ehca_max_qp;
-       shca->max_num_cqs = ehca_max_cq;
-
-       for (i = 0; i < ARRAY_SIZE(shca->sport); i++)
-               spin_lock_init(&shca->sport[i].mod_sqp_lock);
-
-       shca->ofdev = dev;
-       shca->ipz_hca_handle.handle = *handle;
-       dev_set_drvdata(&dev->dev, shca);
-
-       ret = ehca_sense_attributes(shca);
-       if (ret < 0) {
-               ehca_gen_err("Cannot sense eHCA attributes.");
-               goto probe1;
-       }
-
-       ret = ehca_init_device(shca);
-       if (ret) {
-               ehca_gen_err("Cannot init ehca  device struct");
-               goto probe1;
-       }
-
-       eq_size = 2 * shca->max_num_cqs + 4 * shca->max_num_qps;
-       /* create event queues */
-       ret = ehca_create_eq(shca, &shca->eq, EHCA_EQ, eq_size);
-       if (ret) {
-               ehca_err(&shca->ib_device, "Cannot create EQ.");
-               goto probe1;
-       }
-
-       ret = ehca_create_eq(shca, &shca->neq, EHCA_NEQ, 513);
-       if (ret) {
-               ehca_err(&shca->ib_device, "Cannot create NEQ.");
-               goto probe3;
-       }
-
-       /* create internal protection domain */
-       ibpd = ehca_alloc_pd(&shca->ib_device, (void *)(-1), NULL);
-       if (IS_ERR(ibpd)) {
-               ehca_err(&shca->ib_device, "Cannot create internal PD.");
-               ret = PTR_ERR(ibpd);
-               goto probe4;
-       }
-
-       shca->pd = container_of(ibpd, struct ehca_pd, ib_pd);
-       shca->pd->ib_pd.device = &shca->ib_device;
-
-       /* create internal max MR */
-       ret = ehca_reg_internal_maxmr(shca, shca->pd, &shca->maxmr);
-
-       if (ret) {
-               ehca_err(&shca->ib_device, "Cannot create internal MR ret=%i",
-                        ret);
-               goto probe5;
-       }
-
-       ret = ib_register_device(&shca->ib_device, NULL);
-       if (ret) {
-               ehca_err(&shca->ib_device,
-                        "ib_register_device() failed ret=%i", ret);
-               goto probe6;
-       }
-
-       /* create AQP1 for port 1 */
-       if (ehca_open_aqp1 == 1) {
-               shca->sport[0].port_state = IB_PORT_DOWN;
-               ret = ehca_create_aqp1(shca, 1);
-               if (ret) {
-                       ehca_err(&shca->ib_device,
-                                "Cannot create AQP1 for port 1.");
-                       goto probe7;
-               }
-       }
-
-       /* create AQP1 for port 2 */
-       if ((ehca_open_aqp1 == 1) && (shca->num_ports == 2)) {
-               shca->sport[1].port_state = IB_PORT_DOWN;
-               ret = ehca_create_aqp1(shca, 2);
-               if (ret) {
-                       ehca_err(&shca->ib_device,
-                                "Cannot create AQP1 for port 2.");
-                       goto probe8;
-               }
-       }
-
-       ret = sysfs_create_group(&dev->dev.kobj, &ehca_dev_attr_grp);
-       if (ret) /* only complain; we can live without attributes */
-               ehca_err(&shca->ib_device,
-                        "Cannot create device attributes  ret=%d", ret);
-
-       spin_lock_irqsave(&shca_list_lock, flags);
-       list_add(&shca->shca_list, &shca_list);
-       spin_unlock_irqrestore(&shca_list_lock, flags);
-
-       return 0;
-
-probe8:
-       ret = ehca_destroy_aqp1(&shca->sport[0]);
-       if (ret)
-               ehca_err(&shca->ib_device,
-                        "Cannot destroy AQP1 for port 1. ret=%i", ret);
-
-probe7:
-       ib_unregister_device(&shca->ib_device);
-
-probe6:
-       ret = ehca_dereg_internal_maxmr(shca);
-       if (ret)
-               ehca_err(&shca->ib_device,
-                        "Cannot destroy internal MR. ret=%x", ret);
-
-probe5:
-       ret = ehca_dealloc_pd(&shca->pd->ib_pd);
-       if (ret)
-               ehca_err(&shca->ib_device,
-                        "Cannot destroy internal PD. ret=%x", ret);
-
-probe4:
-       ret = ehca_destroy_eq(shca, &shca->neq);
-       if (ret)
-               ehca_err(&shca->ib_device,
-                        "Cannot destroy NEQ. ret=%x", ret);
-
-probe3:
-       ret = ehca_destroy_eq(shca, &shca->eq);
-       if (ret)
-               ehca_err(&shca->ib_device,
-                        "Cannot destroy EQ. ret=%x", ret);
-
-probe1:
-       ib_dealloc_device(&shca->ib_device);
-
-       return -EINVAL;
-}
-
-static int ehca_remove(struct platform_device *dev)
-{
-       struct ehca_shca *shca = dev_get_drvdata(&dev->dev);
-       unsigned long flags;
-       int ret;
-
-       sysfs_remove_group(&dev->dev.kobj, &ehca_dev_attr_grp);
-
-       if (ehca_open_aqp1 == 1) {
-               int i;
-               for (i = 0; i < shca->num_ports; i++) {
-                       ret = ehca_destroy_aqp1(&shca->sport[i]);
-                       if (ret)
-                               ehca_err(&shca->ib_device,
-                                        "Cannot destroy AQP1 for port %x "
-                                        "ret=%i", ret, i);
-               }
-       }
-
-       ib_unregister_device(&shca->ib_device);
-
-       ret = ehca_dereg_internal_maxmr(shca);
-       if (ret)
-               ehca_err(&shca->ib_device,
-                        "Cannot destroy internal MR. ret=%i", ret);
-
-       ret = ehca_dealloc_pd(&shca->pd->ib_pd);
-       if (ret)
-               ehca_err(&shca->ib_device,
-                        "Cannot destroy internal PD. ret=%i", ret);
-
-       ret = ehca_destroy_eq(shca, &shca->eq);
-       if (ret)
-               ehca_err(&shca->ib_device, "Cannot destroy EQ. ret=%i", ret);
-
-       ret = ehca_destroy_eq(shca, &shca->neq);
-       if (ret)
-               ehca_err(&shca->ib_device, "Canot destroy NEQ. ret=%i", ret);
-
-       ib_dealloc_device(&shca->ib_device);
-
-       spin_lock_irqsave(&shca_list_lock, flags);
-       list_del(&shca->shca_list);
-       spin_unlock_irqrestore(&shca_list_lock, flags);
-
-       return ret;
-}
-
-static struct of_device_id ehca_device_table[] =
-{
-       {
-               .name       = "lhca",
-               .compatible = "IBM,lhca",
-       },
-       {},
-};
-MODULE_DEVICE_TABLE(of, ehca_device_table);
-
-static struct platform_driver ehca_driver = {
-       .probe       = ehca_probe,
-       .remove      = ehca_remove,
-       .driver = {
-               .name = "ehca",
-               .owner = THIS_MODULE,
-               .groups = ehca_drv_attr_groups,
-               .of_match_table = ehca_device_table,
-       },
-};
-
-void ehca_poll_eqs(unsigned long data)
-{
-       struct ehca_shca *shca;
-
-       spin_lock(&shca_list_lock);
-       list_for_each_entry(shca, &shca_list, shca_list) {
-               if (shca->eq.is_initialized) {
-                       /* call deadman proc only if eq ptr does not change */
-                       struct ehca_eq *eq = &shca->eq;
-                       int max = 3;
-                       volatile u64 q_ofs, q_ofs2;
-                       unsigned long flags;
-                       spin_lock_irqsave(&eq->spinlock, flags);
-                       q_ofs = eq->ipz_queue.current_q_offset;
-                       spin_unlock_irqrestore(&eq->spinlock, flags);
-                       do {
-                               spin_lock_irqsave(&eq->spinlock, flags);
-                               q_ofs2 = eq->ipz_queue.current_q_offset;
-                               spin_unlock_irqrestore(&eq->spinlock, flags);
-                               max--;
-                       } while (q_ofs == q_ofs2 && max > 0);
-                       if (q_ofs == q_ofs2)
-                               ehca_process_eq(shca, 0);
-               }
-       }
-       mod_timer(&poll_eqs_timer, round_jiffies(jiffies + HZ));
-       spin_unlock(&shca_list_lock);
-}
-
-static int ehca_mem_notifier(struct notifier_block *nb,
-                            unsigned long action, void *data)
-{
-       static unsigned long ehca_dmem_warn_time;
-       unsigned long flags;
-
-       switch (action) {
-       case MEM_CANCEL_OFFLINE:
-       case MEM_CANCEL_ONLINE:
-       case MEM_ONLINE:
-       case MEM_OFFLINE:
-               return NOTIFY_OK;
-       case MEM_GOING_ONLINE:
-       case MEM_GOING_OFFLINE:
-               /* only ok if no hca is attached to the lpar */
-               spin_lock_irqsave(&shca_list_lock, flags);
-               if (list_empty(&shca_list)) {
-                       spin_unlock_irqrestore(&shca_list_lock, flags);
-                       return NOTIFY_OK;
-               } else {
-                       spin_unlock_irqrestore(&shca_list_lock, flags);
-                       if (printk_timed_ratelimit(&ehca_dmem_warn_time,
-                                                  30 * 1000))
-                               ehca_gen_err("DMEM operations are not allowed"
-                                            "in conjunction with eHCA");
-                       return NOTIFY_BAD;
-               }
-       }
-       return NOTIFY_OK;
-}
-
-static struct notifier_block ehca_mem_nb = {
-       .notifier_call = ehca_mem_notifier,
-};
-
-static int __init ehca_module_init(void)
-{
-       int ret;
-
-       printk(KERN_INFO "eHCA Infiniband Device Driver "
-              "(Version " HCAD_VERSION ")\n");
-
-       ret = ehca_create_comp_pool();
-       if (ret) {
-               ehca_gen_err("Cannot create comp pool.");
-               return ret;
-       }
-
-       ret = ehca_create_slab_caches();
-       if (ret) {
-               ehca_gen_err("Cannot create SLAB caches");
-               ret = -ENOMEM;
-               goto module_init1;
-       }
-
-       ret = ehca_create_busmap();
-       if (ret) {
-               ehca_gen_err("Cannot create busmap.");
-               goto module_init2;
-       }
-
-       ret = ibmebus_register_driver(&ehca_driver);
-       if (ret) {
-               ehca_gen_err("Cannot register eHCA device driver");
-               ret = -EINVAL;
-               goto module_init3;
-       }
-
-       ret = register_memory_notifier(&ehca_mem_nb);
-       if (ret) {
-               ehca_gen_err("Failed registering memory add/remove notifier");
-               goto module_init4;
-       }
-
-       if (ehca_poll_all_eqs != 1) {
-               ehca_gen_err("WARNING!!!");
-               ehca_gen_err("It is possible to lose interrupts.");
-       } else {
-               init_timer(&poll_eqs_timer);
-               poll_eqs_timer.function = ehca_poll_eqs;
-               poll_eqs_timer.expires = jiffies + HZ;
-               add_timer(&poll_eqs_timer);
-       }
-
-       return 0;
-
-module_init4:
-       ibmebus_unregister_driver(&ehca_driver);
-
-module_init3:
-       ehca_destroy_busmap();
-
-module_init2:
-       ehca_destroy_slab_caches();
-
-module_init1:
-       ehca_destroy_comp_pool();
-       return ret;
-};
-
-static void __exit ehca_module_exit(void)
-{
-       if (ehca_poll_all_eqs == 1)
-               del_timer_sync(&poll_eqs_timer);
-
-       ibmebus_unregister_driver(&ehca_driver);
-
-       unregister_memory_notifier(&ehca_mem_nb);
-
-       ehca_destroy_busmap();
-
-       ehca_destroy_slab_caches();
-
-       ehca_destroy_comp_pool();
-
-       idr_destroy(&ehca_cq_idr);
-       idr_destroy(&ehca_qp_idr);
-};
-
-module_init(ehca_module_init);
-module_exit(ehca_module_exit);
diff --git a/drivers/infiniband/hw/ehca/ehca_mcast.c b/drivers/infiniband/hw/ehca/ehca_mcast.c
deleted file mode 100644 (file)
index cec1815..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- *  IBM eServer eHCA Infiniband device driver for Linux on POWER
- *
- *  mcast  functions
- *
- *  Authors: Khadija Souissi <souissik@de.ibm.com>
- *           Waleri Fomin <fomin@de.ibm.com>
- *           Reinhard Ernst <rernst@de.ibm.com>
- *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
- *           Heiko J Schick <schickhj@de.ibm.com>
- *
- *  Copyright (c) 2005 IBM Corporation
- *
- *  All rights reserved.
- *
- *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
- *  BSD.
- *
- * OpenIB BSD License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <linux/module.h>
-#include <linux/err.h>
-#include "ehca_classes.h"
-#include "ehca_tools.h"
-#include "ehca_qes.h"
-#include "ehca_iverbs.h"
-#include "hcp_if.h"
-
-#define MAX_MC_LID 0xFFFE
-#define MIN_MC_LID 0xC000      /* Multicast limits */
-#define EHCA_VALID_MULTICAST_GID(gid)  ((gid)[0] == 0xFF)
-#define EHCA_VALID_MULTICAST_LID(lid) \
-       (((lid) >= MIN_MC_LID) && ((lid) <= MAX_MC_LID))
-
-int ehca_attach_mcast(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
-{
-       struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp);
-       struct ehca_shca *shca = container_of(ibqp->device, struct ehca_shca,
-                                             ib_device);
-       union ib_gid my_gid;
-       u64 subnet_prefix, interface_id, h_ret;
-
-       if (ibqp->qp_type != IB_QPT_UD) {
-               ehca_err(ibqp->device, "invalid qp_type=%x", ibqp->qp_type);
-               return -EINVAL;
-       }
-
-       if (!(EHCA_VALID_MULTICAST_GID(gid->raw))) {
-               ehca_err(ibqp->device, "invalid mulitcast gid");
-               return -EINVAL;
-       } else if ((lid < MIN_MC_LID) || (lid > MAX_MC_LID)) {
-               ehca_err(ibqp->device, "invalid mulitcast lid=%x", lid);
-               return -EINVAL;
-       }
-
-       memcpy(&my_gid, gid->raw, sizeof(union ib_gid));
-
-       subnet_prefix = be64_to_cpu(my_gid.global.subnet_prefix);
-       interface_id = be64_to_cpu(my_gid.global.interface_id);
-       h_ret = hipz_h_attach_mcqp(shca->ipz_hca_handle,
-                                  my_qp->ipz_qp_handle,
-                                  my_qp->galpas.kernel,
-                                  lid, subnet_prefix, interface_id);
-       if (h_ret != H_SUCCESS)
-               ehca_err(ibqp->device,
-                        "ehca_qp=%p qp_num=%x hipz_h_attach_mcqp() failed "
-                        "h_ret=%lli", my_qp, ibqp->qp_num, h_ret);
-
-       return ehca2ib_return_code(h_ret);
-}
-
-int ehca_detach_mcast(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
-{
-       struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp);
-       struct ehca_shca *shca = container_of(ibqp->pd->device,
-                                             struct ehca_shca, ib_device);
-       union ib_gid my_gid;
-       u64 subnet_prefix, interface_id, h_ret;
-
-       if (ibqp->qp_type != IB_QPT_UD) {
-               ehca_err(ibqp->device, "invalid qp_type %x", ibqp->qp_type);
-               return -EINVAL;
-       }
-
-       if (!(EHCA_VALID_MULTICAST_GID(gid->raw))) {
-               ehca_err(ibqp->device, "invalid mulitcast gid");
-               return -EINVAL;
-       } else if ((lid < MIN_MC_LID) || (lid > MAX_MC_LID)) {
-               ehca_err(ibqp->device, "invalid mulitcast lid=%x", lid);
-               return -EINVAL;
-       }
-
-       memcpy(&my_gid, gid->raw, sizeof(union ib_gid));
-
-       subnet_prefix = be64_to_cpu(my_gid.global.subnet_prefix);
-       interface_id = be64_to_cpu(my_gid.global.interface_id);
-       h_ret = hipz_h_detach_mcqp(shca->ipz_hca_handle,
-                                  my_qp->ipz_qp_handle,
-                                  my_qp->galpas.kernel,
-                                  lid, subnet_prefix, interface_id);
-       if (h_ret != H_SUCCESS)
-               ehca_err(ibqp->device,
-                        "ehca_qp=%p qp_num=%x hipz_h_detach_mcqp() failed "
-                        "h_ret=%lli", my_qp, ibqp->qp_num, h_ret);
-
-       return ehca2ib_return_code(h_ret);
-}
diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c b/drivers/infiniband/hw/ehca/ehca_mrmw.c
deleted file mode 100644 (file)
index f914b30..0000000
+++ /dev/null
@@ -1,2593 +0,0 @@
-/*
- *  IBM eServer eHCA Infiniband device driver for Linux on POWER
- *
- *  MR/MW functions
- *
- *  Authors: Dietmar Decker <ddecker@de.ibm.com>
- *           Christoph Raisch <raisch@de.ibm.com>
- *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
- *
- *  Copyright (c) 2005 IBM Corporation
- *
- *  All rights reserved.
- *
- *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
- *  BSD.
- *
- * OpenIB BSD License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <linux/slab.h>
-#include <rdma/ib_umem.h>
-
-#include "ehca_iverbs.h"
-#include "ehca_mrmw.h"
-#include "hcp_if.h"
-#include "hipz_hw.h"
-
-#define NUM_CHUNKS(length, chunk_size) \
-       (((length) + (chunk_size - 1)) / (chunk_size))
-
-/* max number of rpages (per hcall register_rpages) */
-#define MAX_RPAGES 512
-
-/* DMEM toleration management */
-#define EHCA_SECTSHIFT        SECTION_SIZE_BITS
-#define EHCA_SECTSIZE          (1UL << EHCA_SECTSHIFT)
-#define EHCA_HUGEPAGESHIFT     34
-#define EHCA_HUGEPAGE_SIZE     (1UL << EHCA_HUGEPAGESHIFT)
-#define EHCA_HUGEPAGE_PFN_MASK ((EHCA_HUGEPAGE_SIZE - 1) >> PAGE_SHIFT)
-#define EHCA_INVAL_ADDR        0xFFFFFFFFFFFFFFFFULL
-#define EHCA_DIR_INDEX_SHIFT 13                   /* 8k Entries in 64k block */
-#define EHCA_TOP_INDEX_SHIFT (EHCA_DIR_INDEX_SHIFT * 2)
-#define EHCA_MAP_ENTRIES (1 << EHCA_DIR_INDEX_SHIFT)
-#define EHCA_TOP_MAP_SIZE (0x10000)               /* currently fixed map size */
-#define EHCA_DIR_MAP_SIZE (0x10000)
-#define EHCA_ENT_MAP_SIZE (0x10000)
-#define EHCA_INDEX_MASK (EHCA_MAP_ENTRIES - 1)
-
-static unsigned long ehca_mr_len;
-
-/*
- * Memory map data structures
- */
-struct ehca_dir_bmap {
-       u64 ent[EHCA_MAP_ENTRIES];
-};
-struct ehca_top_bmap {
-       struct ehca_dir_bmap *dir[EHCA_MAP_ENTRIES];
-};
-struct ehca_bmap {
-       struct ehca_top_bmap *top[EHCA_MAP_ENTRIES];
-};
-
-static struct ehca_bmap *ehca_bmap;
-
-static struct kmem_cache *mr_cache;
-static struct kmem_cache *mw_cache;
-
-enum ehca_mr_pgsize {
-       EHCA_MR_PGSIZE4K  = 0x1000L,
-       EHCA_MR_PGSIZE64K = 0x10000L,
-       EHCA_MR_PGSIZE1M  = 0x100000L,
-       EHCA_MR_PGSIZE16M = 0x1000000L
-};
-
-#define EHCA_MR_PGSHIFT4K  12
-#define EHCA_MR_PGSHIFT64K 16
-#define EHCA_MR_PGSHIFT1M  20
-#define EHCA_MR_PGSHIFT16M 24
-
-static u64 ehca_map_vaddr(void *caddr);
-
-static u32 ehca_encode_hwpage_size(u32 pgsize)
-{
-       int log = ilog2(pgsize);
-       WARN_ON(log < 12 || log > 24 || log & 3);
-       return (log - 12) / 4;
-}
-
-static u64 ehca_get_max_hwpage_size(struct ehca_shca *shca)
-{
-       return rounddown_pow_of_two(shca->hca_cap_mr_pgsize);
-}
-
-static struct ehca_mr *ehca_mr_new(void)
-{
-       struct ehca_mr *me;
-
-       me = kmem_cache_zalloc(mr_cache, GFP_KERNEL);
-       if (me)
-               spin_lock_init(&me->mrlock);
-       else
-               ehca_gen_err("alloc failed");
-
-       return me;
-}
-
-static void ehca_mr_delete(struct ehca_mr *me)
-{
-       kmem_cache_free(mr_cache, me);
-}
-
-static struct ehca_mw *ehca_mw_new(void)
-{
-       struct ehca_mw *me;
-
-       me = kmem_cache_zalloc(mw_cache, GFP_KERNEL);
-       if (me)
-               spin_lock_init(&me->mwlock);
-       else
-               ehca_gen_err("alloc failed");
-
-       return me;
-}
-
-static void ehca_mw_delete(struct ehca_mw *me)
-{
-       kmem_cache_free(mw_cache, me);
-}
-
-/*----------------------------------------------------------------------*/
-
-struct ib_mr *ehca_get_dma_mr(struct ib_pd *pd, int mr_access_flags)
-{
-       struct ib_mr *ib_mr;
-       int ret;
-       struct ehca_mr *e_maxmr;
-       struct ehca_pd *e_pd = container_of(pd, struct ehca_pd, ib_pd);
-       struct ehca_shca *shca =
-               container_of(pd->device, struct ehca_shca, ib_device);
-
-       if (shca->maxmr) {
-               e_maxmr = ehca_mr_new();
-               if (!e_maxmr) {
-                       ehca_err(&shca->ib_device, "out of memory");
-                       ib_mr = ERR_PTR(-ENOMEM);
-                       goto get_dma_mr_exit0;
-               }
-
-               ret = ehca_reg_maxmr(shca, e_maxmr,
-                                    (void *)ehca_map_vaddr((void *)(KERNELBASE + PHYSICAL_START)),
-                                    mr_access_flags, e_pd,
-                                    &e_maxmr->ib.ib_mr.lkey,
-                                    &e_maxmr->ib.ib_mr.rkey);
-               if (ret) {
-                       ehca_mr_delete(e_maxmr);
-                       ib_mr = ERR_PTR(ret);
-                       goto get_dma_mr_exit0;
-               }
-               ib_mr = &e_maxmr->ib.ib_mr;
-       } else {
-               ehca_err(&shca->ib_device, "no internal max-MR exist!");
-               ib_mr = ERR_PTR(-EINVAL);
-               goto get_dma_mr_exit0;
-       }
-
-get_dma_mr_exit0:
-       if (IS_ERR(ib_mr))
-               ehca_err(&shca->ib_device, "h_ret=%li pd=%p mr_access_flags=%x",
-                        PTR_ERR(ib_mr), pd, mr_access_flags);
-       return ib_mr;
-} /* end ehca_get_dma_mr() */
-
-/*----------------------------------------------------------------------*/
-
-struct ib_mr *ehca_reg_phys_mr(struct ib_pd *pd,
-                              struct ib_phys_buf *phys_buf_array,
-                              int num_phys_buf,
-                              int mr_access_flags,
-                              u64 *iova_start)
-{
-       struct ib_mr *ib_mr;
-       int ret;
-       struct ehca_mr *e_mr;
-       struct ehca_shca *shca =
-               container_of(pd->device, struct ehca_shca, ib_device);
-       struct ehca_pd *e_pd = container_of(pd, struct ehca_pd, ib_pd);
-
-       u64 size;
-
-       if ((num_phys_buf <= 0) || !phys_buf_array) {
-               ehca_err(pd->device, "bad input values: num_phys_buf=%x "
-                        "phys_buf_array=%p", num_phys_buf, phys_buf_array);
-               ib_mr = ERR_PTR(-EINVAL);
-               goto reg_phys_mr_exit0;
-       }
-       if (((mr_access_flags & IB_ACCESS_REMOTE_WRITE) &&
-            !(mr_access_flags & IB_ACCESS_LOCAL_WRITE)) ||
-           ((mr_access_flags & IB_ACCESS_REMOTE_ATOMIC) &&
-            !(mr_access_flags & IB_ACCESS_LOCAL_WRITE))) {
-               /*
-                * Remote Write Access requires Local Write Access
-                * Remote Atomic Access requires Local Write Access
-                */
-               ehca_err(pd->device, "bad input values: mr_access_flags=%x",
-                        mr_access_flags);
-               ib_mr = ERR_PTR(-EINVAL);
-               goto reg_phys_mr_exit0;
-       }
-
-       /* check physical buffer list and calculate size */
-       ret = ehca_mr_chk_buf_and_calc_size(phys_buf_array, num_phys_buf,
-                                           iova_start, &size);
-       if (ret) {
-               ib_mr = ERR_PTR(ret);
-               goto reg_phys_mr_exit0;
-       }
-       if ((size == 0) ||
-           (((u64)iova_start + size) < (u64)iova_start)) {
-               ehca_err(pd->device, "bad input values: size=%llx iova_start=%p",
-                        size, iova_start);
-               ib_mr = ERR_PTR(-EINVAL);
-               goto reg_phys_mr_exit0;
-       }
-
-       e_mr = ehca_mr_new();
-       if (!e_mr) {
-               ehca_err(pd->device, "out of memory");
-               ib_mr = ERR_PTR(-ENOMEM);
-               goto reg_phys_mr_exit0;
-       }
-
-       /* register MR on HCA */
-       if (ehca_mr_is_maxmr(size, iova_start)) {
-               e_mr->flags |= EHCA_MR_FLAG_MAXMR;
-               ret = ehca_reg_maxmr(shca, e_mr, iova_start, mr_access_flags,
-                                    e_pd, &e_mr->ib.ib_mr.lkey,
-                                    &e_mr->ib.ib_mr.rkey);
-               if (ret) {
-                       ib_mr = ERR_PTR(ret);
-                       goto reg_phys_mr_exit1;
-               }
-       } else {
-               struct ehca_mr_pginfo pginfo;
-               u32 num_kpages;
-               u32 num_hwpages;
-               u64 hw_pgsize;
-
-               num_kpages = NUM_CHUNKS(((u64)iova_start % PAGE_SIZE) + size,
-                                       PAGE_SIZE);
-               /* for kernel space we try most possible pgsize */
-               hw_pgsize = ehca_get_max_hwpage_size(shca);
-               num_hwpages = NUM_CHUNKS(((u64)iova_start % hw_pgsize) + size,
-                                        hw_pgsize);
-               memset(&pginfo, 0, sizeof(pginfo));
-               pginfo.type = EHCA_MR_PGI_PHYS;
-               pginfo.num_kpages = num_kpages;
-               pginfo.hwpage_size = hw_pgsize;
-               pginfo.num_hwpages = num_hwpages;
-               pginfo.u.phy.num_phys_buf = num_phys_buf;
-               pginfo.u.phy.phys_buf_array = phys_buf_array;
-               pginfo.next_hwpage =
-                       ((u64)iova_start & ~PAGE_MASK) / hw_pgsize;
-
-               ret = ehca_reg_mr(shca, e_mr, iova_start, size, mr_access_flags,
-                                 e_pd, &pginfo, &e_mr->ib.ib_mr.lkey,
-                                 &e_mr->ib.ib_mr.rkey, EHCA_REG_MR);
-               if (ret) {
-                       ib_mr = ERR_PTR(ret);
-                       goto reg_phys_mr_exit1;
-               }
-       }
-
-       /* successful registration of all pages */
-       return &e_mr->ib.ib_mr;
-
-reg_phys_mr_exit1:
-       ehca_mr_delete(e_mr);
-reg_phys_mr_exit0:
-       if (IS_ERR(ib_mr))
-               ehca_err(pd->device, "h_ret=%li pd=%p phys_buf_array=%p "
-                        "num_phys_buf=%x mr_access_flags=%x iova_start=%p",
-                        PTR_ERR(ib_mr), pd, phys_buf_array,
-                        num_phys_buf, mr_access_flags, iova_start);
-       return ib_mr;
-} /* end ehca_reg_phys_mr() */
-
-/*----------------------------------------------------------------------*/
-
-struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
-                              u64 virt, int mr_access_flags,
-                              struct ib_udata *udata)
-{
-       struct ib_mr *ib_mr;
-       struct ehca_mr *e_mr;
-       struct ehca_shca *shca =
-               container_of(pd->device, struct ehca_shca, ib_device);
-       struct ehca_pd *e_pd = container_of(pd, struct ehca_pd, ib_pd);
-       struct ehca_mr_pginfo pginfo;
-       int ret, page_shift;
-       u32 num_kpages;
-       u32 num_hwpages;
-       u64 hwpage_size;
-
-       if (!pd) {
-               ehca_gen_err("bad pd=%p", pd);
-               return ERR_PTR(-EFAULT);
-       }
-
-       if (((mr_access_flags & IB_ACCESS_REMOTE_WRITE) &&
-            !(mr_access_flags & IB_ACCESS_LOCAL_WRITE)) ||
-           ((mr_access_flags & IB_ACCESS_REMOTE_ATOMIC) &&
-            !(mr_access_flags & IB_ACCESS_LOCAL_WRITE))) {
-               /*
-                * Remote Write Access requires Local Write Access
-                * Remote Atomic Access requires Local Write Access
-                */
-               ehca_err(pd->device, "bad input values: mr_access_flags=%x",
-                        mr_access_flags);
-               ib_mr = ERR_PTR(-EINVAL);
-               goto reg_user_mr_exit0;
-       }
-
-       if (length == 0 || virt + length < virt) {
-               ehca_err(pd->device, "bad input values: length=%llx "
-                        "virt_base=%llx", length, virt);
-               ib_mr = ERR_PTR(-EINVAL);
-               goto reg_user_mr_exit0;
-       }
-
-       e_mr = ehca_mr_new();
-       if (!e_mr) {
-               ehca_err(pd->device, "out of memory");
-               ib_mr = ERR_PTR(-ENOMEM);
-               goto reg_user_mr_exit0;
-       }
-
-       e_mr->umem = ib_umem_get(pd->uobject->context, start, length,
-                                mr_access_flags, 0);
-       if (IS_ERR(e_mr->umem)) {
-               ib_mr = (void *)e_mr->umem;
-               goto reg_user_mr_exit1;
-       }
-
-       if (e_mr->umem->page_size != PAGE_SIZE) {
-               ehca_err(pd->device, "page size not supported, "
-                        "e_mr->umem->page_size=%x", e_mr->umem->page_size);
-               ib_mr = ERR_PTR(-EINVAL);
-               goto reg_user_mr_exit2;
-       }
-
-       /* determine number of MR pages */
-       num_kpages = NUM_CHUNKS((virt % PAGE_SIZE) + length, PAGE_SIZE);
-       /* select proper hw_pgsize */
-       page_shift = PAGE_SHIFT;
-       if (e_mr->umem->hugetlb) {
-               /* determine page_shift, clamp between 4K and 16M */
-               page_shift = (fls64(length - 1) + 3) & ~3;
-               page_shift = min(max(page_shift, EHCA_MR_PGSHIFT4K),
-                                EHCA_MR_PGSHIFT16M);
-       }
-       hwpage_size = 1UL << page_shift;
-
-       /* now that we have the desired page size, shift until it's
-        * supported, too. 4K is always supported, so this terminates.
-        */
-       while (!(hwpage_size & shca->hca_cap_mr_pgsize))
-               hwpage_size >>= 4;
-
-reg_user_mr_fallback:
-       num_hwpages = NUM_CHUNKS((virt % hwpage_size) + length, hwpage_size);
-       /* register MR on HCA */
-       memset(&pginfo, 0, sizeof(pginfo));
-       pginfo.type = EHCA_MR_PGI_USER;
-       pginfo.hwpage_size = hwpage_size;
-       pginfo.num_kpages = num_kpages;
-       pginfo.num_hwpages = num_hwpages;
-       pginfo.u.usr.region = e_mr->umem;
-       pginfo.next_hwpage = ib_umem_offset(e_mr->umem) / hwpage_size;
-       pginfo.u.usr.next_sg = pginfo.u.usr.region->sg_head.sgl;
-       ret = ehca_reg_mr(shca, e_mr, (u64 *)virt, length, mr_access_flags,
-                         e_pd, &pginfo, &e_mr->ib.ib_mr.lkey,
-                         &e_mr->ib.ib_mr.rkey, EHCA_REG_MR);
-       if (ret == -EINVAL && pginfo.hwpage_size > PAGE_SIZE) {
-               ehca_warn(pd->device, "failed to register mr "
-                         "with hwpage_size=%llx", hwpage_size);
-               ehca_info(pd->device, "try to register mr with "
-                         "kpage_size=%lx", PAGE_SIZE);
-               /*
-                * this means kpages are not contiguous for a hw page
-                * try kernel page size as fallback solution
-                */
-               hwpage_size = PAGE_SIZE;
-               goto reg_user_mr_fallback;
-       }
-       if (ret) {
-               ib_mr = ERR_PTR(ret);
-               goto reg_user_mr_exit2;
-       }
-
-       /* successful registration of all pages */
-       return &e_mr->ib.ib_mr;
-
-reg_user_mr_exit2:
-       ib_umem_release(e_mr->umem);
-reg_user_mr_exit1:
-       ehca_mr_delete(e_mr);
-reg_user_mr_exit0:
-       if (IS_ERR(ib_mr))
-               ehca_err(pd->device, "rc=%li pd=%p mr_access_flags=%x udata=%p",
-                        PTR_ERR(ib_mr), pd, mr_access_flags, udata);
-       return ib_mr;
-} /* end ehca_reg_user_mr() */
-
-/*----------------------------------------------------------------------*/
-
-int ehca_rereg_phys_mr(struct ib_mr *mr,
-                      int mr_rereg_mask,
-                      struct ib_pd *pd,
-                      struct ib_phys_buf *phys_buf_array,
-                      int num_phys_buf,
-                      int mr_access_flags,
-                      u64 *iova_start)
-{
-       int ret;
-
-       struct ehca_shca *shca =
-               container_of(mr->device, struct ehca_shca, ib_device);
-       struct ehca_mr *e_mr = container_of(mr, struct ehca_mr, ib.ib_mr);
-       u64 new_size;
-       u64 *new_start;
-       u32 new_acl;
-       struct ehca_pd *new_pd;
-       u32 tmp_lkey, tmp_rkey;
-       unsigned long sl_flags;
-       u32 num_kpages = 0;
-       u32 num_hwpages = 0;
-       struct ehca_mr_pginfo pginfo;
-
-       if (!(mr_rereg_mask & IB_MR_REREG_TRANS)) {
-               /* TODO not supported, because PHYP rereg hCall needs pages */
-               ehca_err(mr->device, "rereg without IB_MR_REREG_TRANS not "
-                        "supported yet, mr_rereg_mask=%x", mr_rereg_mask);
-               ret = -EINVAL;
-               goto rereg_phys_mr_exit0;
-       }
-
-       if (mr_rereg_mask & IB_MR_REREG_PD) {
-               if (!pd) {
-                       ehca_err(mr->device, "rereg with bad pd, pd=%p "
-                                "mr_rereg_mask=%x", pd, mr_rereg_mask);
-                       ret = -EINVAL;
-                       goto rereg_phys_mr_exit0;
-               }
-       }
-
-       if ((mr_rereg_mask &
-            ~(IB_MR_REREG_TRANS | IB_MR_REREG_PD | IB_MR_REREG_ACCESS)) ||
-           (mr_rereg_mask == 0)) {
-               ret = -EINVAL;
-               goto rereg_phys_mr_exit0;
-       }
-
-       /* check other parameters */
-       if (e_mr == shca->maxmr) {
-               /* should be impossible, however reject to be sure */
-               ehca_err(mr->device, "rereg internal max-MR impossible, mr=%p "
-                        "shca->maxmr=%p mr->lkey=%x",
-                        mr, shca->maxmr, mr->lkey);
-               ret = -EINVAL;
-               goto rereg_phys_mr_exit0;
-       }
-       if (mr_rereg_mask & IB_MR_REREG_TRANS) { /* transl., i.e. addr/size */
-               if (e_mr->flags & EHCA_MR_FLAG_FMR) {
-                       ehca_err(mr->device, "not supported for FMR, mr=%p "
-                                "flags=%x", mr, e_mr->flags);
-                       ret = -EINVAL;
-                       goto rereg_phys_mr_exit0;
-               }
-               if (!phys_buf_array || num_phys_buf <= 0) {
-                       ehca_err(mr->device, "bad input values mr_rereg_mask=%x"
-                                " phys_buf_array=%p num_phys_buf=%x",
-                                mr_rereg_mask, phys_buf_array, num_phys_buf);
-                       ret = -EINVAL;
-                       goto rereg_phys_mr_exit0;
-               }
-       }
-       if ((mr_rereg_mask & IB_MR_REREG_ACCESS) &&     /* change ACL */
-           (((mr_access_flags & IB_ACCESS_REMOTE_WRITE) &&
-             !(mr_access_flags & IB_ACCESS_LOCAL_WRITE)) ||
-            ((mr_access_flags & IB_ACCESS_REMOTE_ATOMIC) &&
-             !(mr_access_flags & IB_ACCESS_LOCAL_WRITE)))) {
-               /*
-                * Remote Write Access requires Local Write Access
-                * Remote Atomic Access requires Local Write Access
-                */
-               ehca_err(mr->device, "bad input values: mr_rereg_mask=%x "
-                        "mr_access_flags=%x", mr_rereg_mask, mr_access_flags);
-               ret = -EINVAL;
-               goto rereg_phys_mr_exit0;
-       }
-
-       /* set requested values dependent on rereg request */
-       spin_lock_irqsave(&e_mr->mrlock, sl_flags);
-       new_start = e_mr->start;
-       new_size = e_mr->size;
-       new_acl = e_mr->acl;
-       new_pd = container_of(mr->pd, struct ehca_pd, ib_pd);
-
-       if (mr_rereg_mask & IB_MR_REREG_TRANS) {
-               u64 hw_pgsize = ehca_get_max_hwpage_size(shca);
-
-               new_start = iova_start; /* change address */
-               /* check physical buffer list and calculate size */
-               ret = ehca_mr_chk_buf_and_calc_size(phys_buf_array,
-                                                   num_phys_buf, iova_start,
-                                                   &new_size);
-               if (ret)
-                       goto rereg_phys_mr_exit1;
-               if ((new_size == 0) ||
-                   (((u64)iova_start + new_size) < (u64)iova_start)) {
-                       ehca_err(mr->device, "bad input values: new_size=%llx "
-                                "iova_start=%p", new_size, iova_start);
-                       ret = -EINVAL;
-                       goto rereg_phys_mr_exit1;
-               }
-               num_kpages = NUM_CHUNKS(((u64)new_start % PAGE_SIZE) +
-                                       new_size, PAGE_SIZE);
-               num_hwpages = NUM_CHUNKS(((u64)new_start % hw_pgsize) +
-                                        new_size, hw_pgsize);
-               memset(&pginfo, 0, sizeof(pginfo));
-               pginfo.type = EHCA_MR_PGI_PHYS;
-               pginfo.num_kpages = num_kpages;
-               pginfo.hwpage_size = hw_pgsize;
-               pginfo.num_hwpages = num_hwpages;
-               pginfo.u.phy.num_phys_buf = num_phys_buf;
-               pginfo.u.phy.phys_buf_array = phys_buf_array;
-               pginfo.next_hwpage =
-                       ((u64)iova_start & ~PAGE_MASK) / hw_pgsize;
-       }
-       if (mr_rereg_mask & IB_MR_REREG_ACCESS)
-               new_acl = mr_access_flags;
-       if (mr_rereg_mask & IB_MR_REREG_PD)
-               new_pd = container_of(pd, struct ehca_pd, ib_pd);
-
-       ret = ehca_rereg_mr(shca, e_mr, new_start, new_size, new_acl,
-                           new_pd, &pginfo, &tmp_lkey, &tmp_rkey);
-       if (ret)
-               goto rereg_phys_mr_exit1;
-
-       /* successful reregistration */
-       if (mr_rereg_mask & IB_MR_REREG_PD)
-               mr->pd = pd;
-       mr->lkey = tmp_lkey;
-       mr->rkey = tmp_rkey;
-
-rereg_phys_mr_exit1:
-       spin_unlock_irqrestore(&e_mr->mrlock, sl_flags);
-rereg_phys_mr_exit0:
-       if (ret)
-               ehca_err(mr->device, "ret=%i mr=%p mr_rereg_mask=%x pd=%p "
-                        "phys_buf_array=%p num_phys_buf=%x mr_access_flags=%x "
-                        "iova_start=%p",
-                        ret, mr, mr_rereg_mask, pd, phys_buf_array,
-                        num_phys_buf, mr_access_flags, iova_start);
-       return ret;
-} /* end ehca_rereg_phys_mr() */
-
-/*----------------------------------------------------------------------*/
-
-int ehca_query_mr(struct ib_mr *mr, struct ib_mr_attr *mr_attr)
-{
-       int ret = 0;
-       u64 h_ret;
-       struct ehca_shca *shca =
-               container_of(mr->device, struct ehca_shca, ib_device);
-       struct ehca_mr *e_mr = container_of(mr, struct ehca_mr, ib.ib_mr);
-       unsigned long sl_flags;
-       struct ehca_mr_hipzout_parms hipzout;
-
-       if ((e_mr->flags & EHCA_MR_FLAG_FMR)) {
-               ehca_err(mr->device, "not supported for FMR, mr=%p e_mr=%p "
-                        "e_mr->flags=%x", mr, e_mr, e_mr->flags);
-               ret = -EINVAL;
-               goto query_mr_exit0;
-       }
-
-       memset(mr_attr, 0, sizeof(struct ib_mr_attr));
-       spin_lock_irqsave(&e_mr->mrlock, sl_flags);
-
-       h_ret = hipz_h_query_mr(shca->ipz_hca_handle, e_mr, &hipzout);
-       if (h_ret != H_SUCCESS) {
-               ehca_err(mr->device, "hipz_mr_query failed, h_ret=%lli mr=%p "
-                        "hca_hndl=%llx mr_hndl=%llx lkey=%x",
-                        h_ret, mr, shca->ipz_hca_handle.handle,
-                        e_mr->ipz_mr_handle.handle, mr->lkey);
-               ret = ehca2ib_return_code(h_ret);
-               goto query_mr_exit1;
-       }
-       mr_attr->pd = mr->pd;
-       mr_attr->device_virt_addr = hipzout.vaddr;
-       mr_attr->size = hipzout.len;
-       mr_attr->lkey = hipzout.lkey;
-       mr_attr->rkey = hipzout.rkey;
-       ehca_mrmw_reverse_map_acl(&hipzout.acl, &mr_attr->mr_access_flags);
-
-query_mr_exit1:
-       spin_unlock_irqrestore(&e_mr->mrlock, sl_flags);
-query_mr_exit0:
-       if (ret)
-               ehca_err(mr->device, "ret=%i mr=%p mr_attr=%p",
-                        ret, mr, mr_attr);
-       return ret;
-} /* end ehca_query_mr() */
-
-/*----------------------------------------------------------------------*/
-
-int ehca_dereg_mr(struct ib_mr *mr)
-{
-       int ret = 0;
-       u64 h_ret;
-       struct ehca_shca *shca =
-               container_of(mr->device, struct ehca_shca, ib_device);
-       struct ehca_mr *e_mr = container_of(mr, struct ehca_mr, ib.ib_mr);
-
-       if ((e_mr->flags & EHCA_MR_FLAG_FMR)) {
-               ehca_err(mr->device, "not supported for FMR, mr=%p e_mr=%p "
-                        "e_mr->flags=%x", mr, e_mr, e_mr->flags);
-               ret = -EINVAL;
-               goto dereg_mr_exit0;
-       } else if (e_mr == shca->maxmr) {
-               /* should be impossible, however reject to be sure */
-               ehca_err(mr->device, "dereg internal max-MR impossible, mr=%p "
-                        "shca->maxmr=%p mr->lkey=%x",
-                        mr, shca->maxmr, mr->lkey);
-               ret = -EINVAL;
-               goto dereg_mr_exit0;
-       }
-
-       /* TODO: BUSY: MR still has bound window(s) */
-       h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_mr);
-       if (h_ret != H_SUCCESS) {
-               ehca_err(mr->device, "hipz_free_mr failed, h_ret=%lli shca=%p "
-                        "e_mr=%p hca_hndl=%llx mr_hndl=%llx mr->lkey=%x",
-                        h_ret, shca, e_mr, shca->ipz_hca_handle.handle,
-                        e_mr->ipz_mr_handle.handle, mr->lkey);
-               ret = ehca2ib_return_code(h_ret);
-               goto dereg_mr_exit0;
-       }
-
-       if (e_mr->umem)
-               ib_umem_release(e_mr->umem);
-
-       /* successful deregistration */
-       ehca_mr_delete(e_mr);
-
-dereg_mr_exit0:
-       if (ret)
-               ehca_err(mr->device, "ret=%i mr=%p", ret, mr);
-       return ret;
-} /* end ehca_dereg_mr() */
-
-/*----------------------------------------------------------------------*/
-
-struct ib_mw *ehca_alloc_mw(struct ib_pd *pd, enum ib_mw_type type)
-{
-       struct ib_mw *ib_mw;
-       u64 h_ret;
-       struct ehca_mw *e_mw;
-       struct ehca_pd *e_pd = container_of(pd, struct ehca_pd, ib_pd);
-       struct ehca_shca *shca =
-               container_of(pd->device, struct ehca_shca, ib_device);
-       struct ehca_mw_hipzout_parms hipzout;
-
-       if (type != IB_MW_TYPE_1)
-               return ERR_PTR(-EINVAL);
-
-       e_mw = ehca_mw_new();
-       if (!e_mw) {
-               ib_mw = ERR_PTR(-ENOMEM);
-               goto alloc_mw_exit0;
-       }
-
-       h_ret = hipz_h_alloc_resource_mw(shca->ipz_hca_handle, e_mw,
-                                        e_pd->fw_pd, &hipzout);
-       if (h_ret != H_SUCCESS) {
-               ehca_err(pd->device, "hipz_mw_allocate failed, h_ret=%lli "
-                        "shca=%p hca_hndl=%llx mw=%p",
-                        h_ret, shca, shca->ipz_hca_handle.handle, e_mw);
-               ib_mw = ERR_PTR(ehca2ib_return_code(h_ret));
-               goto alloc_mw_exit1;
-       }
-       /* successful MW allocation */
-       e_mw->ipz_mw_handle = hipzout.handle;
-       e_mw->ib_mw.rkey    = hipzout.rkey;
-       return &e_mw->ib_mw;
-
-alloc_mw_exit1:
-       ehca_mw_delete(e_mw);
-alloc_mw_exit0:
-       if (IS_ERR(ib_mw))
-               ehca_err(pd->device, "h_ret=%li pd=%p", PTR_ERR(ib_mw), pd);
-       return ib_mw;
-} /* end ehca_alloc_mw() */
-
-/*----------------------------------------------------------------------*/
-
-int ehca_bind_mw(struct ib_qp *qp,
-                struct ib_mw *mw,
-                struct ib_mw_bind *mw_bind)
-{
-       /* TODO: not supported up to now */
-       ehca_gen_err("bind MW currently not supported by HCAD");
-
-       return -EPERM;
-} /* end ehca_bind_mw() */
-
-/*----------------------------------------------------------------------*/
-
-int ehca_dealloc_mw(struct ib_mw *mw)
-{
-       u64 h_ret;
-       struct ehca_shca *shca =
-               container_of(mw->device, struct ehca_shca, ib_device);
-       struct ehca_mw *e_mw = container_of(mw, struct ehca_mw, ib_mw);
-
-       h_ret = hipz_h_free_resource_mw(shca->ipz_hca_handle, e_mw);
-       if (h_ret != H_SUCCESS) {
-               ehca_err(mw->device, "hipz_free_mw failed, h_ret=%lli shca=%p "
-                        "mw=%p rkey=%x hca_hndl=%llx mw_hndl=%llx",
-                        h_ret, shca, mw, mw->rkey, shca->ipz_hca_handle.handle,
-                        e_mw->ipz_mw_handle.handle);
-               return ehca2ib_return_code(h_ret);
-       }
-       /* successful deallocation */
-       ehca_mw_delete(e_mw);
-       return 0;
-} /* end ehca_dealloc_mw() */
-
-/*----------------------------------------------------------------------*/
-
-struct ib_fmr *ehca_alloc_fmr(struct ib_pd *pd,
-                             int mr_access_flags,
-                             struct ib_fmr_attr *fmr_attr)
-{
-       struct ib_fmr *ib_fmr;
-       struct ehca_shca *shca =
-               container_of(pd->device, struct ehca_shca, ib_device);
-       struct ehca_pd *e_pd = container_of(pd, struct ehca_pd, ib_pd);
-       struct ehca_mr *e_fmr;
-       int ret;
-       u32 tmp_lkey, tmp_rkey;
-       struct ehca_mr_pginfo pginfo;
-       u64 hw_pgsize;
-
-       /* check other parameters */
-       if (((mr_access_flags & IB_ACCESS_REMOTE_WRITE) &&
-            !(mr_access_flags & IB_ACCESS_LOCAL_WRITE)) ||
-           ((mr_access_flags & IB_ACCESS_REMOTE_ATOMIC) &&
-            !(mr_access_flags & IB_ACCESS_LOCAL_WRITE))) {
-               /*
-                * Remote Write Access requires Local Write Access
-                * Remote Atomic Access requires Local Write Access
-                */
-               ehca_err(pd->device, "bad input values: mr_access_flags=%x",
-                        mr_access_flags);
-               ib_fmr = ERR_PTR(-EINVAL);
-               goto alloc_fmr_exit0;
-       }
-       if (mr_access_flags & IB_ACCESS_MW_BIND) {
-               ehca_err(pd->device, "bad input values: mr_access_flags=%x",
-                        mr_access_flags);
-               ib_fmr = ERR_PTR(-EINVAL);
-               goto alloc_fmr_exit0;
-       }
-       if ((fmr_attr->max_pages == 0) || (fmr_attr->max_maps == 0)) {
-               ehca_err(pd->device, "bad input values: fmr_attr->max_pages=%x "
-                        "fmr_attr->max_maps=%x fmr_attr->page_shift=%x",
-                        fmr_attr->max_pages, fmr_attr->max_maps,
-                        fmr_attr->page_shift);
-               ib_fmr = ERR_PTR(-EINVAL);
-               goto alloc_fmr_exit0;
-       }
-
-       hw_pgsize = 1 << fmr_attr->page_shift;
-       if (!(hw_pgsize & shca->hca_cap_mr_pgsize)) {
-               ehca_err(pd->device, "unsupported fmr_attr->page_shift=%x",
-                        fmr_attr->page_shift);
-               ib_fmr = ERR_PTR(-EINVAL);
-               goto alloc_fmr_exit0;
-       }
-
-       e_fmr = ehca_mr_new();
-       if (!e_fmr) {
-               ib_fmr = ERR_PTR(-ENOMEM);
-               goto alloc_fmr_exit0;
-       }
-       e_fmr->flags |= EHCA_MR_FLAG_FMR;
-
-       /* register MR on HCA */
-       memset(&pginfo, 0, sizeof(pginfo));
-       pginfo.hwpage_size = hw_pgsize;
-       /*
-        * pginfo.num_hwpages==0, ie register_rpages() will not be called
-        * but deferred to map_phys_fmr()
-        */
-       ret = ehca_reg_mr(shca, e_fmr, NULL,
-                         fmr_attr->max_pages * (1 << fmr_attr->page_shift),
-                         mr_access_flags, e_pd, &pginfo,
-                         &tmp_lkey, &tmp_rkey, EHCA_REG_MR);
-       if (ret) {
-               ib_fmr = ERR_PTR(ret);
-               goto alloc_fmr_exit1;
-       }
-
-       /* successful */
-       e_fmr->hwpage_size = hw_pgsize;
-       e_fmr->fmr_page_size = 1 << fmr_attr->page_shift;
-       e_fmr->fmr_max_pages = fmr_attr->max_pages;
-       e_fmr->fmr_max_maps = fmr_attr->max_maps;
-       e_fmr->fmr_map_cnt = 0;
-       return &e_fmr->ib.ib_fmr;
-
-alloc_fmr_exit1:
-       ehca_mr_delete(e_fmr);
-alloc_fmr_exit0:
-       return ib_fmr;
-} /* end ehca_alloc_fmr() */
-
-/*----------------------------------------------------------------------*/
-
-int ehca_map_phys_fmr(struct ib_fmr *fmr,
-                     u64 *page_list,
-                     int list_len,
-                     u64 iova)
-{
-       int ret;
-       struct ehca_shca *shca =
-               container_of(fmr->device, struct ehca_shca, ib_device);
-       struct ehca_mr *e_fmr = container_of(fmr, struct ehca_mr, ib.ib_fmr);
-       struct ehca_pd *e_pd = container_of(fmr->pd, struct ehca_pd, ib_pd);
-       struct ehca_mr_pginfo pginfo;
-       u32 tmp_lkey, tmp_rkey;
-
-       if (!(e_fmr->flags & EHCA_MR_FLAG_FMR)) {
-               ehca_err(fmr->device, "not a FMR, e_fmr=%p e_fmr->flags=%x",
-                        e_fmr, e_fmr->flags);
-               ret = -EINVAL;
-               goto map_phys_fmr_exit0;
-       }
-       ret = ehca_fmr_check_page_list(e_fmr, page_list, list_len);
-       if (ret)
-               goto map_phys_fmr_exit0;
-       if (iova % e_fmr->fmr_page_size) {
-               /* only whole-numbered pages */
-               ehca_err(fmr->device, "bad iova, iova=%llx fmr_page_size=%x",
-                        iova, e_fmr->fmr_page_size);
-               ret = -EINVAL;
-               goto map_phys_fmr_exit0;
-       }
-       if (e_fmr->fmr_map_cnt >= e_fmr->fmr_max_maps) {
-               /* HCAD does not limit the maps, however trace this anyway */
-               ehca_info(fmr->device, "map limit exceeded, fmr=%p "
-                         "e_fmr->fmr_map_cnt=%x e_fmr->fmr_max_maps=%x",
-                         fmr, e_fmr->fmr_map_cnt, e_fmr->fmr_max_maps);
-       }
-
-       memset(&pginfo, 0, sizeof(pginfo));
-       pginfo.type = EHCA_MR_PGI_FMR;
-       pginfo.num_kpages = list_len;
-       pginfo.hwpage_size = e_fmr->hwpage_size;
-       pginfo.num_hwpages =
-               list_len * e_fmr->fmr_page_size / pginfo.hwpage_size;
-       pginfo.u.fmr.page_list = page_list;
-       pginfo.next_hwpage =
-               (iova & (e_fmr->fmr_page_size-1)) / pginfo.hwpage_size;
-       pginfo.u.fmr.fmr_pgsize = e_fmr->fmr_page_size;
-
-       ret = ehca_rereg_mr(shca, e_fmr, (u64 *)iova,
-                           list_len * e_fmr->fmr_page_size,
-                           e_fmr->acl, e_pd, &pginfo, &tmp_lkey, &tmp_rkey);
-       if (ret)
-               goto map_phys_fmr_exit0;
-
-       /* successful reregistration */
-       e_fmr->fmr_map_cnt++;
-       e_fmr->ib.ib_fmr.lkey = tmp_lkey;
-       e_fmr->ib.ib_fmr.rkey = tmp_rkey;
-       return 0;
-
-map_phys_fmr_exit0:
-       if (ret)
-               ehca_err(fmr->device, "ret=%i fmr=%p page_list=%p list_len=%x "
-                        "iova=%llx", ret, fmr, page_list, list_len, iova);
-       return ret;
-} /* end ehca_map_phys_fmr() */
-
-/*----------------------------------------------------------------------*/
-
-int ehca_unmap_fmr(struct list_head *fmr_list)
-{
-       int ret = 0;
-       struct ib_fmr *ib_fmr;
-       struct ehca_shca *shca = NULL;
-       struct ehca_shca *prev_shca;
-       struct ehca_mr *e_fmr;
-       u32 num_fmr = 0;
-       u32 unmap_fmr_cnt = 0;
-
-       /* check all FMR belong to same SHCA, and check internal flag */
-       list_for_each_entry(ib_fmr, fmr_list, list) {
-               prev_shca = shca;
-               shca = container_of(ib_fmr->device, struct ehca_shca,
-                                   ib_device);
-               e_fmr = container_of(ib_fmr, struct ehca_mr, ib.ib_fmr);
-               if ((shca != prev_shca) && prev_shca) {
-                       ehca_err(&shca->ib_device, "SHCA mismatch, shca=%p "
-                                "prev_shca=%p e_fmr=%p",
-                                shca, prev_shca, e_fmr);
-                       ret = -EINVAL;
-                       goto unmap_fmr_exit0;
-               }
-               if (!(e_fmr->flags & EHCA_MR_FLAG_FMR)) {
-                       ehca_err(&shca->ib_device, "not a FMR, e_fmr=%p "
-                                "e_fmr->flags=%x", e_fmr, e_fmr->flags);
-                       ret = -EINVAL;
-                       goto unmap_fmr_exit0;
-               }
-               num_fmr++;
-       }
-
-       /* loop over all FMRs to unmap */
-       list_for_each_entry(ib_fmr, fmr_list, list) {
-               unmap_fmr_cnt++;
-               e_fmr = container_of(ib_fmr, struct ehca_mr, ib.ib_fmr);
-               shca = container_of(ib_fmr->device, struct ehca_shca,
-                                   ib_device);
-               ret = ehca_unmap_one_fmr(shca, e_fmr);
-               if (ret) {
-                       /* unmap failed, stop unmapping of rest of FMRs */
-                       ehca_err(&shca->ib_device, "unmap of one FMR failed, "
-                                "stop rest, e_fmr=%p num_fmr=%x "
-                                "unmap_fmr_cnt=%x lkey=%x", e_fmr, num_fmr,
-                                unmap_fmr_cnt, e_fmr->ib.ib_fmr.lkey);
-                       goto unmap_fmr_exit0;
-               }
-       }
-
-unmap_fmr_exit0:
-       if (ret)
-               ehca_gen_err("ret=%i fmr_list=%p num_fmr=%x unmap_fmr_cnt=%x",
-                            ret, fmr_list, num_fmr, unmap_fmr_cnt);
-       return ret;
-} /* end ehca_unmap_fmr() */
-
-/*----------------------------------------------------------------------*/
-
-int ehca_dealloc_fmr(struct ib_fmr *fmr)
-{
-       int ret;
-       u64 h_ret;
-       struct ehca_shca *shca =
-               container_of(fmr->device, struct ehca_shca, ib_device);
-       struct ehca_mr *e_fmr = container_of(fmr, struct ehca_mr, ib.ib_fmr);
-
-       if (!(e_fmr->flags & EHCA_MR_FLAG_FMR)) {
-               ehca_err(fmr->device, "not a FMR, e_fmr=%p e_fmr->flags=%x",
-                        e_fmr, e_fmr->flags);
-               ret = -EINVAL;
-               goto free_fmr_exit0;
-       }
-
-       h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_fmr);
-       if (h_ret != H_SUCCESS) {
-               ehca_err(fmr->device, "hipz_free_mr failed, h_ret=%lli e_fmr=%p "
-                        "hca_hndl=%llx fmr_hndl=%llx fmr->lkey=%x",
-                        h_ret, e_fmr, shca->ipz_hca_handle.handle,
-                        e_fmr->ipz_mr_handle.handle, fmr->lkey);
-               ret = ehca2ib_return_code(h_ret);
-               goto free_fmr_exit0;
-       }
-       /* successful deregistration */
-       ehca_mr_delete(e_fmr);
-       return 0;
-
-free_fmr_exit0:
-       if (ret)
-               ehca_err(&shca->ib_device, "ret=%i fmr=%p", ret, fmr);
-       return ret;
-} /* end ehca_dealloc_fmr() */
-
-/*----------------------------------------------------------------------*/
-
-static int ehca_reg_bmap_mr_rpages(struct ehca_shca *shca,
-                                  struct ehca_mr *e_mr,
-                                  struct ehca_mr_pginfo *pginfo);
-
-int ehca_reg_mr(struct ehca_shca *shca,
-               struct ehca_mr *e_mr,
-               u64 *iova_start,
-               u64 size,
-               int acl,
-               struct ehca_pd *e_pd,
-               struct ehca_mr_pginfo *pginfo,
-               u32 *lkey, /*OUT*/
-               u32 *rkey, /*OUT*/
-               enum ehca_reg_type reg_type)
-{
-       int ret;
-       u64 h_ret;
-       u32 hipz_acl;
-       struct ehca_mr_hipzout_parms hipzout;
-
-       ehca_mrmw_map_acl(acl, &hipz_acl);
-       ehca_mrmw_set_pgsize_hipz_acl(pginfo->hwpage_size, &hipz_acl);
-       if (ehca_use_hp_mr == 1)
-               hipz_acl |= 0x00000001;
-
-       h_ret = hipz_h_alloc_resource_mr(shca->ipz_hca_handle, e_mr,
-                                        (u64)iova_start, size, hipz_acl,
-                                        e_pd->fw_pd, &hipzout);
-       if (h_ret != H_SUCCESS) {
-               ehca_err(&shca->ib_device, "hipz_alloc_mr failed, h_ret=%lli "
-                        "hca_hndl=%llx", h_ret, shca->ipz_hca_handle.handle);
-               ret = ehca2ib_return_code(h_ret);
-               goto ehca_reg_mr_exit0;
-       }
-
-       e_mr->ipz_mr_handle = hipzout.handle;
-
-       if (reg_type == EHCA_REG_BUSMAP_MR)
-               ret = ehca_reg_bmap_mr_rpages(shca, e_mr, pginfo);
-       else if (reg_type == EHCA_REG_MR)
-               ret = ehca_reg_mr_rpages(shca, e_mr, pginfo);
-       else
-               ret = -EINVAL;
-
-       if (ret)
-               goto ehca_reg_mr_exit1;
-
-       /* successful registration */
-       e_mr->num_kpages = pginfo->num_kpages;
-       e_mr->num_hwpages = pginfo->num_hwpages;
-       e_mr->hwpage_size = pginfo->hwpage_size;
-       e_mr->start = iova_start;
-       e_mr->size = size;
-       e_mr->acl = acl;
-       *lkey = hipzout.lkey;
-       *rkey = hipzout.rkey;
-       return 0;
-
-ehca_reg_mr_exit1:
-       h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_mr);
-       if (h_ret != H_SUCCESS) {
-               ehca_err(&shca->ib_device, "h_ret=%lli shca=%p e_mr=%p "
-                        "iova_start=%p size=%llx acl=%x e_pd=%p lkey=%x "
-                        "pginfo=%p num_kpages=%llx num_hwpages=%llx ret=%i",
-                        h_ret, shca, e_mr, iova_start, size, acl, e_pd,
-                        hipzout.lkey, pginfo, pginfo->num_kpages,
-                        pginfo->num_hwpages, ret);
-               ehca_err(&shca->ib_device, "internal error in ehca_reg_mr, "
-                        "not recoverable");
-       }
-ehca_reg_mr_exit0:
-       if (ret)
-               ehca_err(&shca->ib_device, "ret=%i shca=%p e_mr=%p "
-                        "iova_start=%p size=%llx acl=%x e_pd=%p pginfo=%p "
-                        "num_kpages=%llx num_hwpages=%llx",
-                        ret, shca, e_mr, iova_start, size, acl, e_pd, pginfo,
-                        pginfo->num_kpages, pginfo->num_hwpages);
-       return ret;
-} /* end ehca_reg_mr() */
-
-/*----------------------------------------------------------------------*/
-
-int ehca_reg_mr_rpages(struct ehca_shca *shca,
-                      struct ehca_mr *e_mr,
-                      struct ehca_mr_pginfo *pginfo)
-{
-       int ret = 0;
-       u64 h_ret;
-       u32 rnum;
-       u64 rpage;
-       u32 i;
-       u64 *kpage;
-
-       if (!pginfo->num_hwpages) /* in case of fmr */
-               return 0;
-
-       kpage = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
-       if (!kpage) {
-               ehca_err(&shca->ib_device, "kpage alloc failed");
-               ret = -ENOMEM;
-               goto ehca_reg_mr_rpages_exit0;
-       }
-
-       /* max MAX_RPAGES ehca mr pages per register call */
-       for (i = 0; i < NUM_CHUNKS(pginfo->num_hwpages, MAX_RPAGES); i++) {
-
-               if (i == NUM_CHUNKS(pginfo->num_hwpages, MAX_RPAGES) - 1) {
-                       rnum = pginfo->num_hwpages % MAX_RPAGES; /* last shot */
-                       if (rnum == 0)
-                               rnum = MAX_RPAGES;      /* last shot is full */
-               } else
-                       rnum = MAX_RPAGES;
-
-               ret = ehca_set_pagebuf(pginfo, rnum, kpage);
-               if (ret) {
-                       ehca_err(&shca->ib_device, "ehca_set_pagebuf "
-                                "bad rc, ret=%i rnum=%x kpage=%p",
-                                ret, rnum, kpage);
-                       goto ehca_reg_mr_rpages_exit1;
-               }
-
-               if (rnum > 1) {
-                       rpage = __pa(kpage);
-                       if (!rpage) {
-                               ehca_err(&shca->ib_device, "kpage=%p i=%x",
-                                        kpage, i);
-                               ret = -EFAULT;
-                               goto ehca_reg_mr_rpages_exit1;
-                       }
-               } else
-                       rpage = *kpage;
-
-               h_ret = hipz_h_register_rpage_mr(
-                       shca->ipz_hca_handle, e_mr,
-                       ehca_encode_hwpage_size(pginfo->hwpage_size),
-                       0, rpage, rnum);
-
-               if (i == NUM_CHUNKS(pginfo->num_hwpages, MAX_RPAGES) - 1) {
-                       /*
-                        * check for 'registration complete'==H_SUCCESS
-                        * and for 'page registered'==H_PAGE_REGISTERED
-                        */
-                       if (h_ret != H_SUCCESS) {
-                               ehca_err(&shca->ib_device, "last "
-                                        "hipz_reg_rpage_mr failed, h_ret=%lli "
-                                        "e_mr=%p i=%x hca_hndl=%llx mr_hndl=%llx"
-                                        " lkey=%x", h_ret, e_mr, i,
-                                        shca->ipz_hca_handle.handle,
-                                        e_mr->ipz_mr_handle.handle,
-                                        e_mr->ib.ib_mr.lkey);
-                               ret = ehca2ib_return_code(h_ret);
-                               break;
-                       } else
-                               ret = 0;
-               } else if (h_ret != H_PAGE_REGISTERED) {
-                       ehca_err(&shca->ib_device, "hipz_reg_rpage_mr failed, "
-                                "h_ret=%lli e_mr=%p i=%x lkey=%x hca_hndl=%llx "
-                                "mr_hndl=%llx", h_ret, e_mr, i,
-                                e_mr->ib.ib_mr.lkey,
-                                shca->ipz_hca_handle.handle,
-                                e_mr->ipz_mr_handle.handle);
-                       ret = ehca2ib_return_code(h_ret);
-                       break;
-               } else
-                       ret = 0;
-       } /* end for(i) */
-
-
-ehca_reg_mr_rpages_exit1:
-       ehca_free_fw_ctrlblock(kpage);
-ehca_reg_mr_rpages_exit0:
-       if (ret)
-               ehca_err(&shca->ib_device, "ret=%i shca=%p e_mr=%p pginfo=%p "
-                        "num_kpages=%llx num_hwpages=%llx", ret, shca, e_mr,
-                        pginfo, pginfo->num_kpages, pginfo->num_hwpages);
-       return ret;
-} /* end ehca_reg_mr_rpages() */
-
-/*----------------------------------------------------------------------*/
-
-inline int ehca_rereg_mr_rereg1(struct ehca_shca *shca,
-                               struct ehca_mr *e_mr,
-                               u64 *iova_start,
-                               u64 size,
-                               u32 acl,
-                               struct ehca_pd *e_pd,
-                               struct ehca_mr_pginfo *pginfo,
-                               u32 *lkey, /*OUT*/
-                               u32 *rkey) /*OUT*/
-{
-       int ret;
-       u64 h_ret;
-       u32 hipz_acl;
-       u64 *kpage;
-       u64 rpage;
-       struct ehca_mr_pginfo pginfo_save;
-       struct ehca_mr_hipzout_parms hipzout;
-
-       ehca_mrmw_map_acl(acl, &hipz_acl);
-       ehca_mrmw_set_pgsize_hipz_acl(pginfo->hwpage_size, &hipz_acl);
-
-       kpage = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
-       if (!kpage) {
-               ehca_err(&shca->ib_device, "kpage alloc failed");
-               ret = -ENOMEM;
-               goto ehca_rereg_mr_rereg1_exit0;
-       }
-
-       pginfo_save = *pginfo;
-       ret = ehca_set_pagebuf(pginfo, pginfo->num_hwpages, kpage);
-       if (ret) {
-               ehca_err(&shca->ib_device, "set pagebuf failed, e_mr=%p "
-                        "pginfo=%p type=%x num_kpages=%llx num_hwpages=%llx "
-                        "kpage=%p", e_mr, pginfo, pginfo->type,
-                        pginfo->num_kpages, pginfo->num_hwpages, kpage);
-               goto ehca_rereg_mr_rereg1_exit1;
-       }
-       rpage = __pa(kpage);
-       if (!rpage) {
-               ehca_err(&shca->ib_device, "kpage=%p", kpage);
-               ret = -EFAULT;
-               goto ehca_rereg_mr_rereg1_exit1;
-       }
-       h_ret = hipz_h_reregister_pmr(shca->ipz_hca_handle, e_mr,
-                                     (u64)iova_start, size, hipz_acl,
-                                     e_pd->fw_pd, rpage, &hipzout);
-       if (h_ret != H_SUCCESS) {
-               /*
-                * reregistration unsuccessful, try it again with the 3 hCalls,
-                * e.g. this is required in case H_MR_CONDITION
-                * (MW bound or MR is shared)
-                */
-               ehca_warn(&shca->ib_device, "hipz_h_reregister_pmr failed "
-                         "(Rereg1), h_ret=%lli e_mr=%p", h_ret, e_mr);
-               *pginfo = pginfo_save;
-               ret = -EAGAIN;
-       } else if ((u64 *)hipzout.vaddr != iova_start) {
-               ehca_err(&shca->ib_device, "PHYP changed iova_start in "
-                        "rereg_pmr, iova_start=%p iova_start_out=%llx e_mr=%p "
-                        "mr_handle=%llx lkey=%x lkey_out=%x", iova_start,
-                        hipzout.vaddr, e_mr, e_mr->ipz_mr_handle.handle,
-                        e_mr->ib.ib_mr.lkey, hipzout.lkey);
-               ret = -EFAULT;
-       } else {
-               /*
-                * successful reregistration
-                * note: start and start_out are identical for eServer HCAs
-                */
-               e_mr->num_kpages = pginfo->num_kpages;
-               e_mr->num_hwpages = pginfo->num_hwpages;
-               e_mr->hwpage_size = pginfo->hwpage_size;
-               e_mr->start = iova_start;
-               e_mr->size = size;
-               e_mr->acl = acl;
-               *lkey = hipzout.lkey;
-               *rkey = hipzout.rkey;
-       }
-
-ehca_rereg_mr_rereg1_exit1:
-       ehca_free_fw_ctrlblock(kpage);
-ehca_rereg_mr_rereg1_exit0:
-       if ( ret && (ret != -EAGAIN) )
-               ehca_err(&shca->ib_device, "ret=%i lkey=%x rkey=%x "
-                        "pginfo=%p num_kpages=%llx num_hwpages=%llx",
-                        ret, *lkey, *rkey, pginfo, pginfo->num_kpages,
-                        pginfo->num_hwpages);
-       return ret;
-} /* end ehca_rereg_mr_rereg1() */
-
-/*----------------------------------------------------------------------*/
-
-int ehca_rereg_mr(struct ehca_shca *shca,
-                 struct ehca_mr *e_mr,
-                 u64 *iova_start,
-                 u64 size,
-                 int acl,
-                 struct ehca_pd *e_pd,
-                 struct ehca_mr_pginfo *pginfo,
-                 u32 *lkey,
-                 u32 *rkey)
-{
-       int ret = 0;
-       u64 h_ret;
-       int rereg_1_hcall = 1; /* 1: use hipz_h_reregister_pmr directly */
-       int rereg_3_hcall = 0; /* 1: use 3 hipz calls for reregistration */
-
-       /* first determine reregistration hCall(s) */
-       if ((pginfo->num_hwpages > MAX_RPAGES) ||
-           (e_mr->num_hwpages > MAX_RPAGES) ||
-           (pginfo->num_hwpages > e_mr->num_hwpages)) {
-               ehca_dbg(&shca->ib_device, "Rereg3 case, "
-                        "pginfo->num_hwpages=%llx e_mr->num_hwpages=%x",
-                        pginfo->num_hwpages, e_mr->num_hwpages);
-               rereg_1_hcall = 0;
-               rereg_3_hcall = 1;
-       }
-
-       if (e_mr->flags & EHCA_MR_FLAG_MAXMR) { /* check for max-MR */
-               rereg_1_hcall = 0;
-               rereg_3_hcall = 1;
-               e_mr->flags &= ~EHCA_MR_FLAG_MAXMR;
-               ehca_err(&shca->ib_device, "Rereg MR for max-MR! e_mr=%p",
-                        e_mr);
-       }
-
-       if (rereg_1_hcall) {
-               ret = ehca_rereg_mr_rereg1(shca, e_mr, iova_start, size,
-                                          acl, e_pd, pginfo, lkey, rkey);
-               if (ret) {
-                       if (ret == -EAGAIN)
-                               rereg_3_hcall = 1;
-                       else
-                               goto ehca_rereg_mr_exit0;
-               }
-       }
-
-       if (rereg_3_hcall) {
-               struct ehca_mr save_mr;
-
-               /* first deregister old MR */
-               h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_mr);
-               if (h_ret != H_SUCCESS) {
-                       ehca_err(&shca->ib_device, "hipz_free_mr failed, "
-                                "h_ret=%lli e_mr=%p hca_hndl=%llx mr_hndl=%llx "
-                                "mr->lkey=%x",
-                                h_ret, e_mr, shca->ipz_hca_handle.handle,
-                                e_mr->ipz_mr_handle.handle,
-                                e_mr->ib.ib_mr.lkey);
-                       ret = ehca2ib_return_code(h_ret);
-                       goto ehca_rereg_mr_exit0;
-               }
-               /* clean ehca_mr_t, without changing struct ib_mr and lock */
-               save_mr = *e_mr;
-               ehca_mr_deletenew(e_mr);
-
-               /* set some MR values */
-               e_mr->flags = save_mr.flags;
-               e_mr->hwpage_size = save_mr.hwpage_size;
-               e_mr->fmr_page_size = save_mr.fmr_page_size;
-               e_mr->fmr_max_pages = save_mr.fmr_max_pages;
-               e_mr->fmr_max_maps = save_mr.fmr_max_maps;
-               e_mr->fmr_map_cnt = save_mr.fmr_map_cnt;
-
-               ret = ehca_reg_mr(shca, e_mr, iova_start, size, acl,
-                                 e_pd, pginfo, lkey, rkey, EHCA_REG_MR);
-               if (ret) {
-                       u32 offset = (u64)(&e_mr->flags) - (u64)e_mr;
-                       memcpy(&e_mr->flags, &(save_mr.flags),
-                              sizeof(struct ehca_mr) - offset);
-                       goto ehca_rereg_mr_exit0;
-               }
-       }
-
-ehca_rereg_mr_exit0:
-       if (ret)
-               ehca_err(&shca->ib_device, "ret=%i shca=%p e_mr=%p "
-                        "iova_start=%p size=%llx acl=%x e_pd=%p pginfo=%p "
-                        "num_kpages=%llx lkey=%x rkey=%x rereg_1_hcall=%x "
-                        "rereg_3_hcall=%x", ret, shca, e_mr, iova_start, size,
-                        acl, e_pd, pginfo, pginfo->num_kpages, *lkey, *rkey,
-                        rereg_1_hcall, rereg_3_hcall);
-       return ret;
-} /* end ehca_rereg_mr() */
-
-/*----------------------------------------------------------------------*/
-
-int ehca_unmap_one_fmr(struct ehca_shca *shca,
-                      struct ehca_mr *e_fmr)
-{
-       int ret = 0;
-       u64 h_ret;
-       struct ehca_pd *e_pd =
-               container_of(e_fmr->ib.ib_fmr.pd, struct ehca_pd, ib_pd);
-       struct ehca_mr save_fmr;
-       u32 tmp_lkey, tmp_rkey;
-       struct ehca_mr_pginfo pginfo;
-       struct ehca_mr_hipzout_parms hipzout;
-       struct ehca_mr save_mr;
-
-       if (e_fmr->fmr_max_pages <= MAX_RPAGES) {
-               /*
-                * note: after using rereg hcall with len=0,
-                * rereg hcall must be used again for registering pages
-                */
-               h_ret = hipz_h_reregister_pmr(shca->ipz_hca_handle, e_fmr, 0,
-                                             0, 0, e_pd->fw_pd, 0, &hipzout);
-               if (h_ret == H_SUCCESS) {
-                       /* successful reregistration */
-                       e_fmr->start = NULL;
-                       e_fmr->size = 0;
-                       tmp_lkey = hipzout.lkey;
-                       tmp_rkey = hipzout.rkey;
-                       return 0;
-               }
-               /*
-                * should not happen, because length checked above,
-                * FMRs are not shared and no MW bound to FMRs
-                */
-               ehca_err(&shca->ib_device, "hipz_reregister_pmr failed "
-                        "(Rereg1), h_ret=%lli e_fmr=%p hca_hndl=%llx "
-                        "mr_hndl=%llx lkey=%x lkey_out=%x",
-                        h_ret, e_fmr, shca->ipz_hca_handle.handle,
-                        e_fmr->ipz_mr_handle.handle,
-                        e_fmr->ib.ib_fmr.lkey, hipzout.lkey);
-               /* try free and rereg */
-       }
-
-       /* first free old FMR */
-       h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_fmr);
-       if (h_ret != H_SUCCESS) {
-               ehca_err(&shca->ib_device, "hipz_free_mr failed, "
-                        "h_ret=%lli e_fmr=%p hca_hndl=%llx mr_hndl=%llx "
-                        "lkey=%x",
-                        h_ret, e_fmr, shca->ipz_hca_handle.handle,
-                        e_fmr->ipz_mr_handle.handle,
-                        e_fmr->ib.ib_fmr.lkey);
-               ret = ehca2ib_return_code(h_ret);
-               goto ehca_unmap_one_fmr_exit0;
-       }
-       /* clean ehca_mr_t, without changing lock */
-       save_fmr = *e_fmr;
-       ehca_mr_deletenew(e_fmr);
-
-       /* set some MR values */
-       e_fmr->flags = save_fmr.flags;
-       e_fmr->hwpage_size = save_fmr.hwpage_size;
-       e_fmr->fmr_page_size = save_fmr.fmr_page_size;
-       e_fmr->fmr_max_pages = save_fmr.fmr_max_pages;
-       e_fmr->fmr_max_maps = save_fmr.fmr_max_maps;
-       e_fmr->fmr_map_cnt = save_fmr.fmr_map_cnt;
-       e_fmr->acl = save_fmr.acl;
-
-       memset(&pginfo, 0, sizeof(pginfo));
-       pginfo.type = EHCA_MR_PGI_FMR;
-       ret = ehca_reg_mr(shca, e_fmr, NULL,
-                         (e_fmr->fmr_max_pages * e_fmr->fmr_page_size),
-                         e_fmr->acl, e_pd, &pginfo, &tmp_lkey,
-                         &tmp_rkey, EHCA_REG_MR);
-       if (ret) {
-               u32 offset = (u64)(&e_fmr->flags) - (u64)e_fmr;
-               memcpy(&e_fmr->flags, &(save_mr.flags),
-                      sizeof(struct ehca_mr) - offset);
-       }
-
-ehca_unmap_one_fmr_exit0:
-       if (ret)
-               ehca_err(&shca->ib_device, "ret=%i tmp_lkey=%x tmp_rkey=%x "
-                        "fmr_max_pages=%x",
-                        ret, tmp_lkey, tmp_rkey, e_fmr->fmr_max_pages);
-       return ret;
-} /* end ehca_unmap_one_fmr() */
-
-/*----------------------------------------------------------------------*/
-
-int ehca_reg_smr(struct ehca_shca *shca,
-                struct ehca_mr *e_origmr,
-                struct ehca_mr *e_newmr,
-                u64 *iova_start,
-                int acl,
-                struct ehca_pd *e_pd,
-                u32 *lkey, /*OUT*/
-                u32 *rkey) /*OUT*/
-{
-       int ret = 0;
-       u64 h_ret;
-       u32 hipz_acl;
-       struct ehca_mr_hipzout_parms hipzout;
-
-       ehca_mrmw_map_acl(acl, &hipz_acl);
-       ehca_mrmw_set_pgsize_hipz_acl(e_origmr->hwpage_size, &hipz_acl);
-
-       h_ret = hipz_h_register_smr(shca->ipz_hca_handle, e_newmr, e_origmr,
-                                   (u64)iova_start, hipz_acl, e_pd->fw_pd,
-                                   &hipzout);
-       if (h_ret != H_SUCCESS) {
-               ehca_err(&shca->ib_device, "hipz_reg_smr failed, h_ret=%lli "
-                        "shca=%p e_origmr=%p e_newmr=%p iova_start=%p acl=%x "
-                        "e_pd=%p hca_hndl=%llx mr_hndl=%llx lkey=%x",
-                        h_ret, shca, e_origmr, e_newmr, iova_start, acl, e_pd,
-                        shca->ipz_hca_handle.handle,
-                        e_origmr->ipz_mr_handle.handle,
-                        e_origmr->ib.ib_mr.lkey);
-               ret = ehca2ib_return_code(h_ret);
-               goto ehca_reg_smr_exit0;
-       }
-       /* successful registration */
-       e_newmr->num_kpages = e_origmr->num_kpages;
-       e_newmr->num_hwpages = e_origmr->num_hwpages;
-       e_newmr->hwpage_size   = e_origmr->hwpage_size;
-       e_newmr->start = iova_start;
-       e_newmr->size = e_origmr->size;
-       e_newmr->acl = acl;
-       e_newmr->ipz_mr_handle = hipzout.handle;
-       *lkey = hipzout.lkey;
-       *rkey = hipzout.rkey;
-       return 0;
-
-ehca_reg_smr_exit0:
-       if (ret)
-               ehca_err(&shca->ib_device, "ret=%i shca=%p e_origmr=%p "
-                        "e_newmr=%p iova_start=%p acl=%x e_pd=%p",
-                        ret, shca, e_origmr, e_newmr, iova_start, acl, e_pd);
-       return ret;
-} /* end ehca_reg_smr() */
-
-/*----------------------------------------------------------------------*/
-static inline void *ehca_calc_sectbase(int top, int dir, int idx)
-{
-       unsigned long ret = idx;
-       ret |= dir << EHCA_DIR_INDEX_SHIFT;
-       ret |= top << EHCA_TOP_INDEX_SHIFT;
-       return __va(ret << SECTION_SIZE_BITS);
-}
-
-#define ehca_bmap_valid(entry) \
-       ((u64)entry != (u64)EHCA_INVAL_ADDR)
-
-static u64 ehca_reg_mr_section(int top, int dir, int idx, u64 *kpage,
-                              struct ehca_shca *shca, struct ehca_mr *mr,
-                              struct ehca_mr_pginfo *pginfo)
-{
-       u64 h_ret = 0;
-       unsigned long page = 0;
-       u64 rpage = __pa(kpage);
-       int page_count;
-
-       void *sectbase = ehca_calc_sectbase(top, dir, idx);
-       if ((unsigned long)sectbase & (pginfo->hwpage_size - 1)) {
-               ehca_err(&shca->ib_device, "reg_mr_section will probably fail:"
-                                          "hwpage_size does not fit to "
-                                          "section start address");
-       }
-       page_count = EHCA_SECTSIZE / pginfo->hwpage_size;
-
-       while (page < page_count) {
-               u64 rnum;
-               for (rnum = 0; (rnum < MAX_RPAGES) && (page < page_count);
-                    rnum++) {
-                       void *pg = sectbase + ((page++) * pginfo->hwpage_size);
-                       kpage[rnum] = __pa(pg);
-               }
-
-               h_ret = hipz_h_register_rpage_mr(shca->ipz_hca_handle, mr,
-                       ehca_encode_hwpage_size(pginfo->hwpage_size),
-                       0, rpage, rnum);
-
-               if ((h_ret != H_SUCCESS) && (h_ret != H_PAGE_REGISTERED)) {
-                       ehca_err(&shca->ib_device, "register_rpage_mr failed");
-                       return h_ret;
-               }
-       }
-       return h_ret;
-}
-
-static u64 ehca_reg_mr_sections(int top, int dir, u64 *kpage,
-                               struct ehca_shca *shca, struct ehca_mr *mr,
-                               struct ehca_mr_pginfo *pginfo)
-{
-       u64 hret = H_SUCCESS;
-       int idx;
-
-       for (idx = 0; idx < EHCA_MAP_ENTRIES; idx++) {
-               if (!ehca_bmap_valid(ehca_bmap->top[top]->dir[dir]->ent[idx]))
-                       continue;
-
-               hret = ehca_reg_mr_section(top, dir, idx, kpage, shca, mr,
-                                          pginfo);
-               if ((hret != H_SUCCESS) && (hret != H_PAGE_REGISTERED))
-                               return hret;
-       }
-       return hret;
-}
-
-static u64 ehca_reg_mr_dir_sections(int top, u64 *kpage, struct ehca_shca *shca,
-                                   struct ehca_mr *mr,
-                                   struct ehca_mr_pginfo *pginfo)
-{
-       u64 hret = H_SUCCESS;
-       int dir;
-
-       for (dir = 0; dir < EHCA_MAP_ENTRIES; dir++) {
-               if (!ehca_bmap_valid(ehca_bmap->top[top]->dir[dir]))
-                       continue;
-
-               hret = ehca_reg_mr_sections(top, dir, kpage, shca, mr, pginfo);
-               if ((hret != H_SUCCESS) && (hret != H_PAGE_REGISTERED))
-                               return hret;
-       }
-       return hret;
-}
-
-/* register internal max-MR to internal SHCA */
-int ehca_reg_internal_maxmr(
-       struct ehca_shca *shca,
-       struct ehca_pd *e_pd,
-       struct ehca_mr **e_maxmr)  /*OUT*/
-{
-       int ret;
-       struct ehca_mr *e_mr;
-       u64 *iova_start;
-       u64 size_maxmr;
-       struct ehca_mr_pginfo pginfo;
-       struct ib_phys_buf ib_pbuf;
-       u32 num_kpages;
-       u32 num_hwpages;
-       u64 hw_pgsize;
-
-       if (!ehca_bmap) {
-               ret = -EFAULT;
-               goto ehca_reg_internal_maxmr_exit0;
-       }
-
-       e_mr = ehca_mr_new();
-       if (!e_mr) {
-               ehca_err(&shca->ib_device, "out of memory");
-               ret = -ENOMEM;
-               goto ehca_reg_internal_maxmr_exit0;
-       }
-       e_mr->flags |= EHCA_MR_FLAG_MAXMR;
-
-       /* register internal max-MR on HCA */
-       size_maxmr = ehca_mr_len;
-       iova_start = (u64 *)ehca_map_vaddr((void *)(KERNELBASE + PHYSICAL_START));
-       ib_pbuf.addr = 0;
-       ib_pbuf.size = size_maxmr;
-       num_kpages = NUM_CHUNKS(((u64)iova_start % PAGE_SIZE) + size_maxmr,
-                               PAGE_SIZE);
-       hw_pgsize = ehca_get_max_hwpage_size(shca);
-       num_hwpages = NUM_CHUNKS(((u64)iova_start % hw_pgsize) + size_maxmr,
-                                hw_pgsize);
-
-       memset(&pginfo, 0, sizeof(pginfo));
-       pginfo.type = EHCA_MR_PGI_PHYS;
-       pginfo.num_kpages = num_kpages;
-       pginfo.num_hwpages = num_hwpages;
-       pginfo.hwpage_size = hw_pgsize;
-       pginfo.u.phy.num_phys_buf = 1;
-       pginfo.u.phy.phys_buf_array = &ib_pbuf;
-
-       ret = ehca_reg_mr(shca, e_mr, iova_start, size_maxmr, 0, e_pd,
-                         &pginfo, &e_mr->ib.ib_mr.lkey,
-                         &e_mr->ib.ib_mr.rkey, EHCA_REG_BUSMAP_MR);
-       if (ret) {
-               ehca_err(&shca->ib_device, "reg of internal max MR failed, "
-                        "e_mr=%p iova_start=%p size_maxmr=%llx num_kpages=%x "
-                        "num_hwpages=%x", e_mr, iova_start, size_maxmr,
-                        num_kpages, num_hwpages);
-               goto ehca_reg_internal_maxmr_exit1;
-       }
-
-       /* successful registration of all pages */
-       e_mr->ib.ib_mr.device = e_pd->ib_pd.device;
-       e_mr->ib.ib_mr.pd = &e_pd->ib_pd;
-       e_mr->ib.ib_mr.uobject = NULL;
-       atomic_inc(&(e_pd->ib_pd.usecnt));
-       atomic_set(&(e_mr->ib.ib_mr.usecnt), 0);
-       *e_maxmr = e_mr;
-       return 0;
-
-ehca_reg_internal_maxmr_exit1:
-       ehca_mr_delete(e_mr);
-ehca_reg_internal_maxmr_exit0:
-       if (ret)
-               ehca_err(&shca->ib_device, "ret=%i shca=%p e_pd=%p e_maxmr=%p",
-                        ret, shca, e_pd, e_maxmr);
-       return ret;
-} /* end ehca_reg_internal_maxmr() */
-
-/*----------------------------------------------------------------------*/
-
-int ehca_reg_maxmr(struct ehca_shca *shca,
-                  struct ehca_mr *e_newmr,
-                  u64 *iova_start,
-                  int acl,
-                  struct ehca_pd *e_pd,
-                  u32 *lkey,
-                  u32 *rkey)
-{
-       u64 h_ret;
-       struct ehca_mr *e_origmr = shca->maxmr;
-       u32 hipz_acl;
-       struct ehca_mr_hipzout_parms hipzout;
-
-       ehca_mrmw_map_acl(acl, &hipz_acl);
-       ehca_mrmw_set_pgsize_hipz_acl(e_origmr->hwpage_size, &hipz_acl);
-
-       h_ret = hipz_h_register_smr(shca->ipz_hca_handle, e_newmr, e_origmr,
-                                   (u64)iova_start, hipz_acl, e_pd->fw_pd,
-                                   &hipzout);
-       if (h_ret != H_SUCCESS) {
-               ehca_err(&shca->ib_device, "hipz_reg_smr failed, h_ret=%lli "
-                        "e_origmr=%p hca_hndl=%llx mr_hndl=%llx lkey=%x",
-                        h_ret, e_origmr, shca->ipz_hca_handle.handle,
-                        e_origmr->ipz_mr_handle.handle,
-                        e_origmr->ib.ib_mr.lkey);
-               return ehca2ib_return_code(h_ret);
-       }
-       /* successful registration */
-       e_newmr->num_kpages = e_origmr->num_kpages;
-       e_newmr->num_hwpages = e_origmr->num_hwpages;
-       e_newmr->hwpage_size = e_origmr->hwpage_size;
-       e_newmr->start = iova_start;
-       e_newmr->size = e_origmr->size;
-       e_newmr->acl = acl;
-       e_newmr->ipz_mr_handle = hipzout.handle;
-       *lkey = hipzout.lkey;
-       *rkey = hipzout.rkey;
-       return 0;
-} /* end ehca_reg_maxmr() */
-
-/*----------------------------------------------------------------------*/
-
-int ehca_dereg_internal_maxmr(struct ehca_shca *shca)
-{
-       int ret;
-       struct ehca_mr *e_maxmr;
-       struct ib_pd *ib_pd;
-
-       if (!shca->maxmr) {
-               ehca_err(&shca->ib_device, "bad call, shca=%p", shca);
-               ret = -EINVAL;
-               goto ehca_dereg_internal_maxmr_exit0;
-       }
-
-       e_maxmr = shca->maxmr;
-       ib_pd = e_maxmr->ib.ib_mr.pd;
-       shca->maxmr = NULL; /* remove internal max-MR indication from SHCA */
-
-       ret = ehca_dereg_mr(&e_maxmr->ib.ib_mr);
-       if (ret) {
-               ehca_err(&shca->ib_device, "dereg internal max-MR failed, "
-                        "ret=%i e_maxmr=%p shca=%p lkey=%x",
-                        ret, e_maxmr, shca, e_maxmr->ib.ib_mr.lkey);
-               shca->maxmr = e_maxmr;
-               goto ehca_dereg_internal_maxmr_exit0;
-       }
-
-       atomic_dec(&ib_pd->usecnt);
-
-ehca_dereg_internal_maxmr_exit0:
-       if (ret)
-               ehca_err(&shca->ib_device, "ret=%i shca=%p shca->maxmr=%p",
-                        ret, shca, shca->maxmr);
-       return ret;
-} /* end ehca_dereg_internal_maxmr() */
-
-/*----------------------------------------------------------------------*/
-
-/*
- * check physical buffer array of MR verbs for validness and
- * calculates MR size
- */
-int ehca_mr_chk_buf_and_calc_size(struct ib_phys_buf *phys_buf_array,
-                                 int num_phys_buf,
-                                 u64 *iova_start,
-                                 u64 *size)
-{
-       struct ib_phys_buf *pbuf = phys_buf_array;
-       u64 size_count = 0;
-       u32 i;
-
-       if (num_phys_buf == 0) {
-               ehca_gen_err("bad phys buf array len, num_phys_buf=0");
-               return -EINVAL;
-       }
-       /* check first buffer */
-       if (((u64)iova_start & ~PAGE_MASK) != (pbuf->addr & ~PAGE_MASK)) {
-               ehca_gen_err("iova_start/addr mismatch, iova_start=%p "
-                            "pbuf->addr=%llx pbuf->size=%llx",
-                            iova_start, pbuf->addr, pbuf->size);
-               return -EINVAL;
-       }
-       if (((pbuf->addr + pbuf->size) % PAGE_SIZE) &&
-           (num_phys_buf > 1)) {
-               ehca_gen_err("addr/size mismatch in 1st buf, pbuf->addr=%llx "
-                            "pbuf->size=%llx", pbuf->addr, pbuf->size);
-               return -EINVAL;
-       }
-
-       for (i = 0; i < num_phys_buf; i++) {
-               if ((i > 0) && (pbuf->addr % PAGE_SIZE)) {
-                       ehca_gen_err("bad address, i=%x pbuf->addr=%llx "
-                                    "pbuf->size=%llx",
-                                    i, pbuf->addr, pbuf->size);
-                       return -EINVAL;
-               }
-               if (((i > 0) && /* not 1st */
-                    (i < (num_phys_buf - 1)) &&        /* not last */
-                    (pbuf->size % PAGE_SIZE)) || (pbuf->size == 0)) {
-                       ehca_gen_err("bad size, i=%x pbuf->size=%llx",
-                                    i, pbuf->size);
-                       return -EINVAL;
-               }
-               size_count += pbuf->size;
-               pbuf++;
-       }
-
-       *size = size_count;
-       return 0;
-} /* end ehca_mr_chk_buf_and_calc_size() */
-
-/*----------------------------------------------------------------------*/
-
-/* check page list of map FMR verb for validness */
-int ehca_fmr_check_page_list(struct ehca_mr *e_fmr,
-                            u64 *page_list,
-                            int list_len)
-{
-       u32 i;
-       u64 *page;
-
-       if ((list_len == 0) || (list_len > e_fmr->fmr_max_pages)) {
-               ehca_gen_err("bad list_len, list_len=%x "
-                            "e_fmr->fmr_max_pages=%x fmr=%p",
-                            list_len, e_fmr->fmr_max_pages, e_fmr);
-               return -EINVAL;
-       }
-
-       /* each page must be aligned */
-       page = page_list;
-       for (i = 0; i < list_len; i++) {
-               if (*page % e_fmr->fmr_page_size) {
-                       ehca_gen_err("bad page, i=%x *page=%llx page=%p fmr=%p "
-                                    "fmr_page_size=%x", i, *page, page, e_fmr,
-                                    e_fmr->fmr_page_size);
-                       return -EINVAL;
-               }
-               page++;
-       }
-
-       return 0;
-} /* end ehca_fmr_check_page_list() */
-
-/*----------------------------------------------------------------------*/
-
-/* PAGE_SIZE >= pginfo->hwpage_size */
-static int ehca_set_pagebuf_user1(struct ehca_mr_pginfo *pginfo,
-                                 u32 number,
-                                 u64 *kpage)
-{
-       int ret = 0;
-       u64 pgaddr;
-       u32 j = 0;
-       int hwpages_per_kpage = PAGE_SIZE / pginfo->hwpage_size;
-       struct scatterlist **sg = &pginfo->u.usr.next_sg;
-
-       while (*sg != NULL) {
-               pgaddr = page_to_pfn(sg_page(*sg))
-                       << PAGE_SHIFT;
-               *kpage = pgaddr + (pginfo->next_hwpage *
-                                  pginfo->hwpage_size);
-               if (!(*kpage)) {
-                       ehca_gen_err("pgaddr=%llx "
-                                    "sg_dma_address=%llx "
-                                    "entry=%llx next_hwpage=%llx",
-                                    pgaddr, (u64)sg_dma_address(*sg),
-                                    pginfo->u.usr.next_nmap,
-                                    pginfo->next_hwpage);
-                       return -EFAULT;
-               }
-               (pginfo->hwpage_cnt)++;
-               (pginfo->next_hwpage)++;
-               kpage++;
-               if (pginfo->next_hwpage % hwpages_per_kpage == 0) {
-                       (pginfo->kpage_cnt)++;
-                       (pginfo->u.usr.next_nmap)++;
-                       pginfo->next_hwpage = 0;
-                       *sg = sg_next(*sg);
-               }
-               j++;
-               if (j >= number)
-                       break;
-       }
-
-       return ret;
-}
-
-/*
- * check given pages for contiguous layout
- * last page addr is returned in prev_pgaddr for further check
- */
-static int ehca_check_kpages_per_ate(struct scatterlist **sg,
-                                    int num_pages,
-                                    u64 *prev_pgaddr)
-{
-       for (; *sg && num_pages > 0; *sg = sg_next(*sg), num_pages--) {
-               u64 pgaddr = page_to_pfn(sg_page(*sg)) << PAGE_SHIFT;
-               if (ehca_debug_level >= 3)
-                       ehca_gen_dbg("chunk_page=%llx value=%016llx", pgaddr,
-                                    *(u64 *)__va(pgaddr));
-               if (pgaddr - PAGE_SIZE != *prev_pgaddr) {
-                       ehca_gen_err("uncontiguous page found pgaddr=%llx "
-                                    "prev_pgaddr=%llx entries_left_in_hwpage=%x",
-                                    pgaddr, *prev_pgaddr, num_pages);
-                       return -EINVAL;
-               }
-               *prev_pgaddr = pgaddr;
-       }
-       return 0;
-}
-
-/* PAGE_SIZE < pginfo->hwpage_size */
-static int ehca_set_pagebuf_user2(struct ehca_mr_pginfo *pginfo,
-                                 u32 number,
-                                 u64 *kpage)
-{
-       int ret = 0;
-       u64 pgaddr, prev_pgaddr;
-       u32 j = 0;
-       int kpages_per_hwpage = pginfo->hwpage_size / PAGE_SIZE;
-       int nr_kpages = kpages_per_hwpage;
-       struct scatterlist **sg = &pginfo->u.usr.next_sg;
-
-       while (*sg != NULL) {
-
-               if (nr_kpages == kpages_per_hwpage) {
-                       pgaddr = (page_to_pfn(sg_page(*sg))
-                                  << PAGE_SHIFT);
-                       *kpage = pgaddr;
-                       if (!(*kpage)) {
-                               ehca_gen_err("pgaddr=%llx entry=%llx",
-                                            pgaddr, pginfo->u.usr.next_nmap);
-                               ret = -EFAULT;
-                               return ret;
-                       }
-                       /*
-                        * The first page in a hwpage must be aligned;
-                        * the first MR page is exempt from this rule.
-                        */
-                       if (pgaddr & (pginfo->hwpage_size - 1)) {
-                               if (pginfo->hwpage_cnt) {
-                                       ehca_gen_err(
-                                               "invalid alignment "
-                                               "pgaddr=%llx entry=%llx "
-                                               "mr_pgsize=%llx",
-                                               pgaddr, pginfo->u.usr.next_nmap,
-                                               pginfo->hwpage_size);
-                                       ret = -EFAULT;
-                                       return ret;
-                               }
-                               /* first MR page */
-                               pginfo->kpage_cnt =
-                                       (pgaddr &
-                                        (pginfo->hwpage_size - 1)) >>
-                                       PAGE_SHIFT;
-                               nr_kpages -= pginfo->kpage_cnt;
-                               *kpage = pgaddr &
-                                        ~(pginfo->hwpage_size - 1);
-                       }
-                       if (ehca_debug_level >= 3) {
-                               u64 val = *(u64 *)__va(pgaddr);
-                               ehca_gen_dbg("kpage=%llx page=%llx "
-                                            "value=%016llx",
-                                            *kpage, pgaddr, val);
-                       }
-                       prev_pgaddr = pgaddr;
-                       *sg = sg_next(*sg);
-                       pginfo->kpage_cnt++;
-                       pginfo->u.usr.next_nmap++;
-                       nr_kpages--;
-                       if (!nr_kpages)
-                               goto next_kpage;
-                       continue;
-               }
-
-               ret = ehca_check_kpages_per_ate(sg, nr_kpages,
-                                               &prev_pgaddr);
-               if (ret)
-                       return ret;
-               pginfo->kpage_cnt += nr_kpages;
-               pginfo->u.usr.next_nmap += nr_kpages;
-
-next_kpage:
-               nr_kpages = kpages_per_hwpage;
-               (pginfo->hwpage_cnt)++;
-               kpage++;
-               j++;
-               if (j >= number)
-                       break;
-       }
-
-       return ret;
-}
-
-static int ehca_set_pagebuf_phys(struct ehca_mr_pginfo *pginfo,
-                                u32 number, u64 *kpage)
-{
-       int ret = 0;
-       struct ib_phys_buf *pbuf;
-       u64 num_hw, offs_hw;
-       u32 i = 0;
-
-       /* loop over desired phys_buf_array entries */
-       while (i < number) {
-               pbuf   = pginfo->u.phy.phys_buf_array + pginfo->u.phy.next_buf;
-               num_hw  = NUM_CHUNKS((pbuf->addr % pginfo->hwpage_size) +
-                                    pbuf->size, pginfo->hwpage_size);
-               offs_hw = (pbuf->addr & ~(pginfo->hwpage_size - 1)) /
-                       pginfo->hwpage_size;
-               while (pginfo->next_hwpage < offs_hw + num_hw) {
-                       /* sanity check */
-                       if ((pginfo->kpage_cnt >= pginfo->num_kpages) ||
-                           (pginfo->hwpage_cnt >= pginfo->num_hwpages)) {
-                               ehca_gen_err("kpage_cnt >= num_kpages, "
-                                            "kpage_cnt=%llx num_kpages=%llx "
-                                            "hwpage_cnt=%llx "
-                                            "num_hwpages=%llx i=%x",
-                                            pginfo->kpage_cnt,
-                                            pginfo->num_kpages,
-                                            pginfo->hwpage_cnt,
-                                            pginfo->num_hwpages, i);
-                               return -EFAULT;
-                       }
-                       *kpage = (pbuf->addr & ~(pginfo->hwpage_size - 1)) +
-                                (pginfo->next_hwpage * pginfo->hwpage_size);
-                       if ( !(*kpage) && pbuf->addr ) {
-                               ehca_gen_err("pbuf->addr=%llx pbuf->size=%llx "
-                                            "next_hwpage=%llx", pbuf->addr,
-                                            pbuf->size, pginfo->next_hwpage);
-                               return -EFAULT;
-                       }
-                       (pginfo->hwpage_cnt)++;
-                       (pginfo->next_hwpage)++;
-                       if (PAGE_SIZE >= pginfo->hwpage_size) {
-                               if (pginfo->next_hwpage %
-                                   (PAGE_SIZE / pginfo->hwpage_size) == 0)
-                                       (pginfo->kpage_cnt)++;
-                       } else
-                               pginfo->kpage_cnt += pginfo->hwpage_size /
-                                       PAGE_SIZE;
-                       kpage++;
-                       i++;
-                       if (i >= number) break;
-               }
-               if (pginfo->next_hwpage >= offs_hw + num_hw) {
-                       (pginfo->u.phy.next_buf)++;
-                       pginfo->next_hwpage = 0;
-               }
-       }
-       return ret;
-}
-
-static int ehca_set_pagebuf_fmr(struct ehca_mr_pginfo *pginfo,
-                               u32 number, u64 *kpage)
-{
-       int ret = 0;
-       u64 *fmrlist;
-       u32 i;
-
-       /* loop over desired page_list entries */
-       fmrlist = pginfo->u.fmr.page_list + pginfo->u.fmr.next_listelem;
-       for (i = 0; i < number; i++) {
-               *kpage = (*fmrlist & ~(pginfo->hwpage_size - 1)) +
-                          pginfo->next_hwpage * pginfo->hwpage_size;
-               if ( !(*kpage) ) {
-                       ehca_gen_err("*fmrlist=%llx fmrlist=%p "
-                                    "next_listelem=%llx next_hwpage=%llx",
-                                    *fmrlist, fmrlist,
-                                    pginfo->u.fmr.next_listelem,
-                                    pginfo->next_hwpage);
-                       return -EFAULT;
-               }
-               (pginfo->hwpage_cnt)++;
-               if (pginfo->u.fmr.fmr_pgsize >= pginfo->hwpage_size) {
-                       if (pginfo->next_hwpage %
-                           (pginfo->u.fmr.fmr_pgsize /
-                            pginfo->hwpage_size) == 0) {
-                               (pginfo->kpage_cnt)++;
-                               (pginfo->u.fmr.next_listelem)++;
-                               fmrlist++;
-                               pginfo->next_hwpage = 0;
-                       } else
-                               (pginfo->next_hwpage)++;
-               } else {
-                       unsigned int cnt_per_hwpage = pginfo->hwpage_size /
-                               pginfo->u.fmr.fmr_pgsize;
-                       unsigned int j;
-                       u64 prev = *kpage;
-                       /* check if adrs are contiguous */
-                       for (j = 1; j < cnt_per_hwpage; j++) {
-                               u64 p = fmrlist[j] & ~(pginfo->hwpage_size - 1);
-                               if (prev + pginfo->u.fmr.fmr_pgsize != p) {
-                                       ehca_gen_err("uncontiguous fmr pages "
-                                                    "found prev=%llx p=%llx "
-                                                    "idx=%x", prev, p, i + j);
-                                       return -EINVAL;
-                               }
-                               prev = p;
-                       }
-                       pginfo->kpage_cnt += cnt_per_hwpage;
-                       pginfo->u.fmr.next_listelem += cnt_per_hwpage;
-                       fmrlist += cnt_per_hwpage;
-               }
-               kpage++;
-       }
-       return ret;
-}
-
-/* setup page buffer from page info */
-int ehca_set_pagebuf(struct ehca_mr_pginfo *pginfo,
-                    u32 number,
-                    u64 *kpage)
-{
-       int ret;
-
-       switch (pginfo->type) {
-       case EHCA_MR_PGI_PHYS:
-               ret = ehca_set_pagebuf_phys(pginfo, number, kpage);
-               break;
-       case EHCA_MR_PGI_USER:
-               ret = PAGE_SIZE >= pginfo->hwpage_size ?
-                       ehca_set_pagebuf_user1(pginfo, number, kpage) :
-                       ehca_set_pagebuf_user2(pginfo, number, kpage);
-               break;
-       case EHCA_MR_PGI_FMR:
-               ret = ehca_set_pagebuf_fmr(pginfo, number, kpage);
-               break;
-       default:
-               ehca_gen_err("bad pginfo->type=%x", pginfo->type);
-               ret = -EFAULT;
-               break;
-       }
-       return ret;
-} /* end ehca_set_pagebuf() */
-
-/*----------------------------------------------------------------------*/
-
-/*
- * check MR if it is a max-MR, i.e. uses whole memory
- * in case it's a max-MR 1 is returned, else 0
- */
-int ehca_mr_is_maxmr(u64 size,
-                    u64 *iova_start)
-{
-       /* a MR is treated as max-MR only if it fits following: */
-       if ((size == ehca_mr_len) &&
-           (iova_start == (void *)ehca_map_vaddr((void *)(KERNELBASE + PHYSICAL_START)))) {
-               ehca_gen_dbg("this is a max-MR");
-               return 1;
-       } else
-               return 0;
-} /* end ehca_mr_is_maxmr() */
-
-/*----------------------------------------------------------------------*/
-
-/* map access control for MR/MW. This routine is used for MR and MW. */
-void ehca_mrmw_map_acl(int ib_acl,
-                      u32 *hipz_acl)
-{
-       *hipz_acl = 0;
-       if (ib_acl & IB_ACCESS_REMOTE_READ)
-               *hipz_acl |= HIPZ_ACCESSCTRL_R_READ;
-       if (ib_acl & IB_ACCESS_REMOTE_WRITE)
-               *hipz_acl |= HIPZ_ACCESSCTRL_R_WRITE;
-       if (ib_acl & IB_ACCESS_REMOTE_ATOMIC)
-               *hipz_acl |= HIPZ_ACCESSCTRL_R_ATOMIC;
-       if (ib_acl & IB_ACCESS_LOCAL_WRITE)
-               *hipz_acl |= HIPZ_ACCESSCTRL_L_WRITE;
-       if (ib_acl & IB_ACCESS_MW_BIND)
-               *hipz_acl |= HIPZ_ACCESSCTRL_MW_BIND;
-} /* end ehca_mrmw_map_acl() */
-
-/*----------------------------------------------------------------------*/
-
-/* sets page size in hipz access control for MR/MW. */
-void ehca_mrmw_set_pgsize_hipz_acl(u32 pgsize, u32 *hipz_acl) /*INOUT*/
-{
-       *hipz_acl |= (ehca_encode_hwpage_size(pgsize) << 24);
-} /* end ehca_mrmw_set_pgsize_hipz_acl() */
-
-/*----------------------------------------------------------------------*/
-
-/*
- * reverse map access control for MR/MW.
- * This routine is used for MR and MW.
- */
-void ehca_mrmw_reverse_map_acl(const u32 *hipz_acl,
-                              int *ib_acl) /*OUT*/
-{
-       *ib_acl = 0;
-       if (*hipz_acl & HIPZ_ACCESSCTRL_R_READ)
-               *ib_acl |= IB_ACCESS_REMOTE_READ;
-       if (*hipz_acl & HIPZ_ACCESSCTRL_R_WRITE)
-               *ib_acl |= IB_ACCESS_REMOTE_WRITE;
-       if (*hipz_acl & HIPZ_ACCESSCTRL_R_ATOMIC)
-               *ib_acl |= IB_ACCESS_REMOTE_ATOMIC;
-       if (*hipz_acl & HIPZ_ACCESSCTRL_L_WRITE)
-               *ib_acl |= IB_ACCESS_LOCAL_WRITE;
-       if (*hipz_acl & HIPZ_ACCESSCTRL_MW_BIND)
-               *ib_acl |= IB_ACCESS_MW_BIND;
-} /* end ehca_mrmw_reverse_map_acl() */
-
-
-/*----------------------------------------------------------------------*/
-
-/*
- * MR destructor and constructor
- * used in Reregister MR verb, sets all fields in ehca_mr_t to 0,
- * except struct ib_mr and spinlock
- */
-void ehca_mr_deletenew(struct ehca_mr *mr)
-{
-       mr->flags = 0;
-       mr->num_kpages = 0;
-       mr->num_hwpages = 0;
-       mr->acl = 0;
-       mr->start = NULL;
-       mr->fmr_page_size = 0;
-       mr->fmr_max_pages = 0;
-       mr->fmr_max_maps = 0;
-       mr->fmr_map_cnt = 0;
-       memset(&mr->ipz_mr_handle, 0, sizeof(mr->ipz_mr_handle));
-       memset(&mr->galpas, 0, sizeof(mr->galpas));
-} /* end ehca_mr_deletenew() */
-
-int ehca_init_mrmw_cache(void)
-{
-       mr_cache = kmem_cache_create("ehca_cache_mr",
-                                    sizeof(struct ehca_mr), 0,
-                                    SLAB_HWCACHE_ALIGN,
-                                    NULL);
-       if (!mr_cache)
-               return -ENOMEM;
-       mw_cache = kmem_cache_create("ehca_cache_mw",
-                                    sizeof(struct ehca_mw), 0,
-                                    SLAB_HWCACHE_ALIGN,
-                                    NULL);
-       if (!mw_cache) {
-               kmem_cache_destroy(mr_cache);
-               mr_cache = NULL;
-               return -ENOMEM;
-       }
-       return 0;
-}
-
-void ehca_cleanup_mrmw_cache(void)
-{
-       if (mr_cache)
-               kmem_cache_destroy(mr_cache);
-       if (mw_cache)
-               kmem_cache_destroy(mw_cache);
-}
-
-static inline int ehca_init_top_bmap(struct ehca_top_bmap *ehca_top_bmap,
-                                    int dir)
-{
-       if (!ehca_bmap_valid(ehca_top_bmap->dir[dir])) {
-               ehca_top_bmap->dir[dir] =
-                       kmalloc(sizeof(struct ehca_dir_bmap), GFP_KERNEL);
-               if (!ehca_top_bmap->dir[dir])
-                       return -ENOMEM;
-               /* Set map block to 0xFF according to EHCA_INVAL_ADDR */
-               memset(ehca_top_bmap->dir[dir], 0xFF, EHCA_ENT_MAP_SIZE);
-       }
-       return 0;
-}
-
-static inline int ehca_init_bmap(struct ehca_bmap *ehca_bmap, int top, int dir)
-{
-       if (!ehca_bmap_valid(ehca_bmap->top[top])) {
-               ehca_bmap->top[top] =
-                       kmalloc(sizeof(struct ehca_top_bmap), GFP_KERNEL);
-               if (!ehca_bmap->top[top])
-                       return -ENOMEM;
-               /* Set map block to 0xFF according to EHCA_INVAL_ADDR */
-               memset(ehca_bmap->top[top], 0xFF, EHCA_DIR_MAP_SIZE);
-       }
-       return ehca_init_top_bmap(ehca_bmap->top[top], dir);
-}
-
-static inline int ehca_calc_index(unsigned long i, unsigned long s)
-{
-       return (i >> s) & EHCA_INDEX_MASK;
-}
-
-void ehca_destroy_busmap(void)
-{
-       int top, dir;
-
-       if (!ehca_bmap)
-               return;
-
-       for (top = 0; top < EHCA_MAP_ENTRIES; top++) {
-               if (!ehca_bmap_valid(ehca_bmap->top[top]))
-                       continue;
-               for (dir = 0; dir < EHCA_MAP_ENTRIES; dir++) {
-                       if (!ehca_bmap_valid(ehca_bmap->top[top]->dir[dir]))
-                               continue;
-
-                       kfree(ehca_bmap->top[top]->dir[dir]);
-               }
-
-               kfree(ehca_bmap->top[top]);
-       }
-
-       kfree(ehca_bmap);
-       ehca_bmap = NULL;
-}
-
-static int ehca_update_busmap(unsigned long pfn, unsigned long nr_pages)
-{
-       unsigned long i, start_section, end_section;
-       int top, dir, idx;
-
-       if (!nr_pages)
-               return 0;
-
-       if (!ehca_bmap) {
-               ehca_bmap = kmalloc(sizeof(struct ehca_bmap), GFP_KERNEL);
-               if (!ehca_bmap)
-                       return -ENOMEM;
-               /* Set map block to 0xFF according to EHCA_INVAL_ADDR */
-               memset(ehca_bmap, 0xFF, EHCA_TOP_MAP_SIZE);
-       }
-
-       start_section = (pfn * PAGE_SIZE) / EHCA_SECTSIZE;
-       end_section = ((pfn + nr_pages) * PAGE_SIZE) / EHCA_SECTSIZE;
-       for (i = start_section; i < end_section; i++) {
-               int ret;
-               top = ehca_calc_index(i, EHCA_TOP_INDEX_SHIFT);
-               dir = ehca_calc_index(i, EHCA_DIR_INDEX_SHIFT);
-               idx = i & EHCA_INDEX_MASK;
-
-               ret = ehca_init_bmap(ehca_bmap, top, dir);
-               if (ret) {
-                       ehca_destroy_busmap();
-                       return ret;
-               }
-               ehca_bmap->top[top]->dir[dir]->ent[idx] = ehca_mr_len;
-               ehca_mr_len += EHCA_SECTSIZE;
-       }
-       return 0;
-}
-
-static int ehca_is_hugepage(unsigned long pfn)
-{
-       int page_order;
-
-       if (pfn & EHCA_HUGEPAGE_PFN_MASK)
-               return 0;
-
-       page_order = compound_order(pfn_to_page(pfn));
-       if (page_order + PAGE_SHIFT != EHCA_HUGEPAGESHIFT)
-               return 0;
-
-       return 1;
-}
-
-static int ehca_create_busmap_callback(unsigned long initial_pfn,
-                                      unsigned long total_nr_pages, void *arg)
-{
-       int ret;
-       unsigned long pfn, start_pfn, end_pfn, nr_pages;
-
-       if ((total_nr_pages * PAGE_SIZE) < EHCA_HUGEPAGE_SIZE)
-               return ehca_update_busmap(initial_pfn, total_nr_pages);
-
-       /* Given chunk is >= 16GB -> check for hugepages */
-       start_pfn = initial_pfn;
-       end_pfn = initial_pfn + total_nr_pages;
-       pfn = start_pfn;
-
-       while (pfn < end_pfn) {
-               if (ehca_is_hugepage(pfn)) {
-                       /* Add mem found in front of the hugepage */
-                       nr_pages = pfn - start_pfn;
-                       ret = ehca_update_busmap(start_pfn, nr_pages);
-                       if (ret)
-                               return ret;
-                       /* Skip the hugepage */
-                       pfn += (EHCA_HUGEPAGE_SIZE / PAGE_SIZE);
-                       start_pfn = pfn;
-               } else
-                       pfn += (EHCA_SECTSIZE / PAGE_SIZE);
-       }
-
-       /* Add mem found behind the hugepage(s)  */
-       nr_pages = pfn - start_pfn;
-       return ehca_update_busmap(start_pfn, nr_pages);
-}
-
-int ehca_create_busmap(void)
-{
-       int ret;
-
-       ehca_mr_len = 0;
-       ret = walk_system_ram_range(0, 1ULL << MAX_PHYSMEM_BITS, NULL,
-                                  ehca_create_busmap_callback);
-       return ret;
-}
-
-static int ehca_reg_bmap_mr_rpages(struct ehca_shca *shca,
-                                  struct ehca_mr *e_mr,
-                                  struct ehca_mr_pginfo *pginfo)
-{
-       int top;
-       u64 hret, *kpage;
-
-       kpage = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
-       if (!kpage) {
-               ehca_err(&shca->ib_device, "kpage alloc failed");
-               return -ENOMEM;
-       }
-       for (top = 0; top < EHCA_MAP_ENTRIES; top++) {
-               if (!ehca_bmap_valid(ehca_bmap->top[top]))
-                       continue;
-               hret = ehca_reg_mr_dir_sections(top, kpage, shca, e_mr, pginfo);
-               if ((hret != H_PAGE_REGISTERED) && (hret != H_SUCCESS))
-                       break;
-       }
-
-       ehca_free_fw_ctrlblock(kpage);
-
-       if (hret == H_SUCCESS)
-               return 0; /* Everything is fine */
-       else {
-               ehca_err(&shca->ib_device, "ehca_reg_bmap_mr_rpages failed, "
-                                "h_ret=%lli e_mr=%p top=%x lkey=%x "
-                                "hca_hndl=%llx mr_hndl=%llx", hret, e_mr, top,
-                                e_mr->ib.ib_mr.lkey,
-                                shca->ipz_hca_handle.handle,
-                                e_mr->ipz_mr_handle.handle);
-               return ehca2ib_return_code(hret);
-       }
-}
-
-static u64 ehca_map_vaddr(void *caddr)
-{
-       int top, dir, idx;
-       unsigned long abs_addr, offset;
-       u64 entry;
-
-       if (!ehca_bmap)
-               return EHCA_INVAL_ADDR;
-
-       abs_addr = __pa(caddr);
-       top = ehca_calc_index(abs_addr, EHCA_TOP_INDEX_SHIFT + EHCA_SECTSHIFT);
-       if (!ehca_bmap_valid(ehca_bmap->top[top]))
-               return EHCA_INVAL_ADDR;
-
-       dir = ehca_calc_index(abs_addr, EHCA_DIR_INDEX_SHIFT + EHCA_SECTSHIFT);
-       if (!ehca_bmap_valid(ehca_bmap->top[top]->dir[dir]))
-               return EHCA_INVAL_ADDR;
-
-       idx = ehca_calc_index(abs_addr, EHCA_SECTSHIFT);
-
-       entry = ehca_bmap->top[top]->dir[dir]->ent[idx];
-       if (ehca_bmap_valid(entry)) {
-               offset = (unsigned long)caddr & (EHCA_SECTSIZE - 1);
-               return entry | offset;
-       } else
-               return EHCA_INVAL_ADDR;
-}
-
-static int ehca_dma_mapping_error(struct ib_device *dev, u64 dma_addr)
-{
-       return dma_addr == EHCA_INVAL_ADDR;
-}
-
-static u64 ehca_dma_map_single(struct ib_device *dev, void *cpu_addr,
-                              size_t size, enum dma_data_direction direction)
-{
-       if (cpu_addr)
-               return ehca_map_vaddr(cpu_addr);
-       else
-               return EHCA_INVAL_ADDR;
-}
-
-static void ehca_dma_unmap_single(struct ib_device *dev, u64 addr, size_t size,
-                                 enum dma_data_direction direction)
-{
-       /* This is only a stub; nothing to be done here */
-}
-
-static u64 ehca_dma_map_page(struct ib_device *dev, struct page *page,
-                            unsigned long offset, size_t size,
-                            enum dma_data_direction direction)
-{
-       u64 addr;
-
-       if (offset + size > PAGE_SIZE)
-               return EHCA_INVAL_ADDR;
-
-       addr = ehca_map_vaddr(page_address(page));
-       if (!ehca_dma_mapping_error(dev, addr))
-               addr += offset;
-
-       return addr;
-}
-
-static void ehca_dma_unmap_page(struct ib_device *dev, u64 addr, size_t size,
-                               enum dma_data_direction direction)
-{
-       /* This is only a stub; nothing to be done here */
-}
-
-static int ehca_dma_map_sg(struct ib_device *dev, struct scatterlist *sgl,
-                          int nents, enum dma_data_direction direction)
-{
-       struct scatterlist *sg;
-       int i;
-
-       for_each_sg(sgl, sg, nents, i) {
-               u64 addr;
-               addr = ehca_map_vaddr(sg_virt(sg));
-               if (ehca_dma_mapping_error(dev, addr))
-                       return 0;
-
-               sg->dma_address = addr;
-               sg->dma_length = sg->length;
-       }
-       return nents;
-}
-
-static void ehca_dma_unmap_sg(struct ib_device *dev, struct scatterlist *sg,
-                             int nents, enum dma_data_direction direction)
-{
-       /* This is only a stub; nothing to be done here */
-}
-
-static void ehca_dma_sync_single_for_cpu(struct ib_device *dev, u64 addr,
-                                        size_t size,
-                                        enum dma_data_direction dir)
-{
-       dma_sync_single_for_cpu(dev->dma_device, addr, size, dir);
-}
-
-static void ehca_dma_sync_single_for_device(struct ib_device *dev, u64 addr,
-                                           size_t size,
-                                           enum dma_data_direction dir)
-{
-       dma_sync_single_for_device(dev->dma_device, addr, size, dir);
-}
-
-static void *ehca_dma_alloc_coherent(struct ib_device *dev, size_t size,
-                                    u64 *dma_handle, gfp_t flag)
-{
-       struct page *p;
-       void *addr = NULL;
-       u64 dma_addr;
-
-       p = alloc_pages(flag, get_order(size));
-       if (p) {
-               addr = page_address(p);
-               dma_addr = ehca_map_vaddr(addr);
-               if (ehca_dma_mapping_error(dev, dma_addr)) {
-                       free_pages((unsigned long)addr, get_order(size));
-                       return NULL;
-               }
-               if (dma_handle)
-                       *dma_handle = dma_addr;
-               return addr;
-       }
-       return NULL;
-}
-
-static void ehca_dma_free_coherent(struct ib_device *dev, size_t size,
-                                  void *cpu_addr, u64 dma_handle)
-{
-       if (cpu_addr && size)
-               free_pages((unsigned long)cpu_addr, get_order(size));
-}
-
-
-struct ib_dma_mapping_ops ehca_dma_mapping_ops = {
-       .mapping_error          = ehca_dma_mapping_error,
-       .map_single             = ehca_dma_map_single,
-       .unmap_single           = ehca_dma_unmap_single,
-       .map_page               = ehca_dma_map_page,
-       .unmap_page             = ehca_dma_unmap_page,
-       .map_sg                 = ehca_dma_map_sg,
-       .unmap_sg               = ehca_dma_unmap_sg,
-       .sync_single_for_cpu    = ehca_dma_sync_single_for_cpu,
-       .sync_single_for_device = ehca_dma_sync_single_for_device,
-       .alloc_coherent         = ehca_dma_alloc_coherent,
-       .free_coherent          = ehca_dma_free_coherent,
-};
diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.h b/drivers/infiniband/hw/ehca/ehca_mrmw.h
deleted file mode 100644 (file)
index 50d8b51..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- *  IBM eServer eHCA Infiniband device driver for Linux on POWER
- *
- *  MR/MW declarations and inline functions
- *
- *  Authors: Dietmar Decker <ddecker@de.ibm.com>
- *           Christoph Raisch <raisch@de.ibm.com>
- *
- *  Copyright (c) 2005 IBM Corporation
- *
- *  All rights reserved.
- *
- *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
- *  BSD.
- *
- * OpenIB BSD License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef _EHCA_MRMW_H_
-#define _EHCA_MRMW_H_
-
-enum ehca_reg_type {
-       EHCA_REG_MR,
-       EHCA_REG_BUSMAP_MR
-};
-
-int ehca_reg_mr(struct ehca_shca *shca,
-               struct ehca_mr *e_mr,
-               u64 *iova_start,
-               u64 size,
-               int acl,
-               struct ehca_pd *e_pd,
-               struct ehca_mr_pginfo *pginfo,
-               u32 *lkey,
-               u32 *rkey,
-               enum ehca_reg_type reg_type);
-
-int ehca_reg_mr_rpages(struct ehca_shca *shca,
-                      struct ehca_mr *e_mr,
-                      struct ehca_mr_pginfo *pginfo);
-
-int ehca_rereg_mr(struct ehca_shca *shca,
-                 struct ehca_mr *e_mr,
-                 u64 *iova_start,
-                 u64 size,
-                 int mr_access_flags,
-                 struct ehca_pd *e_pd,
-                 struct ehca_mr_pginfo *pginfo,
-                 u32 *lkey,
-                 u32 *rkey);
-
-int ehca_unmap_one_fmr(struct ehca_shca *shca,
-                      struct ehca_mr *e_fmr);
-
-int ehca_reg_smr(struct ehca_shca *shca,
-                struct ehca_mr *e_origmr,
-                struct ehca_mr *e_newmr,
-                u64 *iova_start,
-                int acl,
-                struct ehca_pd *e_pd,
-                u32 *lkey,
-                u32 *rkey);
-
-int ehca_reg_internal_maxmr(struct ehca_shca *shca,
-                           struct ehca_pd *e_pd,
-                           struct ehca_mr **maxmr);
-
-int ehca_reg_maxmr(struct ehca_shca *shca,
-                  struct ehca_mr *e_newmr,
-                  u64 *iova_start,
-                  int acl,
-                  struct ehca_pd *e_pd,
-                  u32 *lkey,
-                  u32 *rkey);
-
-int ehca_dereg_internal_maxmr(struct ehca_shca *shca);
-
-int ehca_mr_chk_buf_and_calc_size(struct ib_phys_buf *phys_buf_array,
-                                 int num_phys_buf,
-                                 u64 *iova_start,
-                                 u64 *size);
-
-int ehca_fmr_check_page_list(struct ehca_mr *e_fmr,
-                            u64 *page_list,
-                            int list_len);
-
-int ehca_set_pagebuf(struct ehca_mr_pginfo *pginfo,
-                    u32 number,
-                    u64 *kpage);
-
-int ehca_mr_is_maxmr(u64 size,
-                    u64 *iova_start);
-
-void ehca_mrmw_map_acl(int ib_acl,
-                      u32 *hipz_acl);
-
-void ehca_mrmw_set_pgsize_hipz_acl(u32 pgsize, u32 *hipz_acl);
-
-void ehca_mrmw_reverse_map_acl(const u32 *hipz_acl,
-                              int *ib_acl);
-
-void ehca_mr_deletenew(struct ehca_mr *mr);
-
-int ehca_create_busmap(void);
-
-void ehca_destroy_busmap(void);
-
-extern struct ib_dma_mapping_ops ehca_dma_mapping_ops;
-#endif  /*_EHCA_MRMW_H_*/
diff --git a/drivers/infiniband/hw/ehca/ehca_pd.c b/drivers/infiniband/hw/ehca/ehca_pd.c
deleted file mode 100644 (file)
index 351577a..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- *  IBM eServer eHCA Infiniband device driver for Linux on POWER
- *
- *  PD functions
- *
- *  Authors: Christoph Raisch <raisch@de.ibm.com>
- *
- *  Copyright (c) 2005 IBM Corporation
- *
- *  All rights reserved.
- *
- *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
- *  BSD.
- *
- * OpenIB BSD License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <linux/slab.h>
-
-#include "ehca_tools.h"
-#include "ehca_iverbs.h"
-
-static struct kmem_cache *pd_cache;
-
-struct ib_pd *ehca_alloc_pd(struct ib_device *device,
-                           struct ib_ucontext *context, struct ib_udata *udata)
-{
-       struct ehca_pd *pd;
-       int i;
-
-       pd = kmem_cache_zalloc(pd_cache, GFP_KERNEL);
-       if (!pd) {
-               ehca_err(device, "device=%p context=%p out of memory",
-                        device, context);
-               return ERR_PTR(-ENOMEM);
-       }
-
-       for (i = 0; i < 2; i++) {
-               INIT_LIST_HEAD(&pd->free[i]);
-               INIT_LIST_HEAD(&pd->full[i]);
-       }
-       mutex_init(&pd->lock);
-
-       /*
-        * Kernel PD: when device = -1, 0
-        * User   PD: when context != -1
-        */
-       if (!context) {
-               /*
-                * Kernel PDs after init reuses always
-                * the one created in ehca_shca_reopen()
-                */
-               struct ehca_shca *shca = container_of(device, struct ehca_shca,
-                                                     ib_device);
-               pd->fw_pd.value = shca->pd->fw_pd.value;
-       } else
-               pd->fw_pd.value = (u64)pd;
-
-       return &pd->ib_pd;
-}
-
-int ehca_dealloc_pd(struct ib_pd *pd)
-{
-       struct ehca_pd *my_pd = container_of(pd, struct ehca_pd, ib_pd);
-       int i, leftovers = 0;
-       struct ipz_small_queue_page *page, *tmp;
-
-       for (i = 0; i < 2; i++) {
-               list_splice(&my_pd->full[i], &my_pd->free[i]);
-               list_for_each_entry_safe(page, tmp, &my_pd->free[i], list) {
-                       leftovers = 1;
-                       free_page(page->page);
-                       kmem_cache_free(small_qp_cache, page);
-               }
-       }
-
-       if (leftovers)
-               ehca_warn(pd->device,
-                         "Some small queue pages were not freed");
-
-       kmem_cache_free(pd_cache, my_pd);
-
-       return 0;
-}
-
-int ehca_init_pd_cache(void)
-{
-       pd_cache = kmem_cache_create("ehca_cache_pd",
-                                    sizeof(struct ehca_pd), 0,
-                                    SLAB_HWCACHE_ALIGN,
-                                    NULL);
-       if (!pd_cache)
-               return -ENOMEM;
-       return 0;
-}
-
-void ehca_cleanup_pd_cache(void)
-{
-       if (pd_cache)
-               kmem_cache_destroy(pd_cache);
-}
diff --git a/drivers/infiniband/hw/ehca/ehca_qes.h b/drivers/infiniband/hw/ehca/ehca_qes.h
deleted file mode 100644 (file)
index 90c4efa..0000000
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- *  IBM eServer eHCA Infiniband device driver for Linux on POWER
- *
- *  Hardware request structures
- *
- *  Authors: Waleri Fomin <fomin@de.ibm.com>
- *           Reinhard Ernst <rernst@de.ibm.com>
- *           Christoph Raisch <raisch@de.ibm.com>
- *
- *  Copyright (c) 2005 IBM Corporation
- *
- *  All rights reserved.
- *
- *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
- *  BSD.
- *
- * OpenIB BSD License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef _EHCA_QES_H_
-#define _EHCA_QES_H_
-
-#include "ehca_tools.h"
-
-/* virtual scatter gather entry to specify remote addresses with length */
-struct ehca_vsgentry {
-       u64 vaddr;
-       u32 lkey;
-       u32 length;
-};
-
-#define GRH_FLAG_MASK        EHCA_BMASK_IBM( 7,  7)
-#define GRH_IPVERSION_MASK   EHCA_BMASK_IBM( 0,  3)
-#define GRH_TCLASS_MASK      EHCA_BMASK_IBM( 4, 12)
-#define GRH_FLOWLABEL_MASK   EHCA_BMASK_IBM(13, 31)
-#define GRH_PAYLEN_MASK      EHCA_BMASK_IBM(32, 47)
-#define GRH_NEXTHEADER_MASK  EHCA_BMASK_IBM(48, 55)
-#define GRH_HOPLIMIT_MASK    EHCA_BMASK_IBM(56, 63)
-
-/*
- * Unreliable Datagram Address Vector Format
- * see IBTA Vol1 chapter 8.3 Global Routing Header
- */
-struct ehca_ud_av {
-       u8 sl;
-       u8 lnh;
-       u16 dlid;
-       u8 reserved1;
-       u8 reserved2;
-       u8 reserved3;
-       u8 slid_path_bits;
-       u8 reserved4;
-       u8 ipd;
-       u8 reserved5;
-       u8 pmtu;
-       u32 reserved6;
-       u64 reserved7;
-       union {
-               struct {
-                       u64 word_0; /* always set to 6  */
-                       /*should be 0x1B for IB transport */
-                       u64 word_1;
-                       u64 word_2;
-                       u64 word_3;
-                       u64 word_4;
-               } grh;
-               struct {
-                       u32 wd_0;
-                       u32 wd_1;
-                       /* DWord_1 --> SGID */
-
-                       u32 sgid_wd3;
-                       u32 sgid_wd2;
-
-                       u32 sgid_wd1;
-                       u32 sgid_wd0;
-                       /* DWord_3 --> DGID */
-
-                       u32 dgid_wd3;
-                       u32 dgid_wd2;
-
-                       u32 dgid_wd1;
-                       u32 dgid_wd0;
-               } grh_l;
-       };
-};
-
-/* maximum number of sg entries allowed in a WQE */
-#define MAX_WQE_SG_ENTRIES 252
-
-#define WQE_OPTYPE_SEND             0x80
-#define WQE_OPTYPE_RDMAREAD         0x40
-#define WQE_OPTYPE_RDMAWRITE        0x20
-#define WQE_OPTYPE_CMPSWAP          0x10
-#define WQE_OPTYPE_FETCHADD         0x08
-#define WQE_OPTYPE_BIND             0x04
-
-#define WQE_WRFLAG_REQ_SIGNAL_COM   0x80
-#define WQE_WRFLAG_FENCE            0x40
-#define WQE_WRFLAG_IMM_DATA_PRESENT 0x20
-#define WQE_WRFLAG_SOLIC_EVENT      0x10
-
-#define WQEF_CACHE_HINT             0x80
-#define WQEF_CACHE_HINT_RD_WR       0x40
-#define WQEF_TIMED_WQE              0x20
-#define WQEF_PURGE                  0x08
-#define WQEF_HIGH_NIBBLE            0xF0
-
-#define MW_BIND_ACCESSCTRL_R_WRITE   0x40
-#define MW_BIND_ACCESSCTRL_R_READ    0x20
-#define MW_BIND_ACCESSCTRL_R_ATOMIC  0x10
-
-struct ehca_wqe {
-       u64 work_request_id;
-       u8 optype;
-       u8 wr_flag;
-       u16 pkeyi;
-       u8 wqef;
-       u8 nr_of_data_seg;
-       u16 wqe_provided_slid;
-       u32 destination_qp_number;
-       u32 resync_psn_sqp;
-       u32 local_ee_context_qkey;
-       u32 immediate_data;
-       union {
-               struct {
-                       u64 remote_virtual_address;
-                       u32 rkey;
-                       u32 reserved;
-                       u64 atomic_1st_op_dma_len;
-                       u64 atomic_2nd_op;
-                       struct ehca_vsgentry sg_list[MAX_WQE_SG_ENTRIES];
-
-               } nud;
-               struct {
-                       u64 ehca_ud_av_ptr;
-                       u64 reserved1;
-                       u64 reserved2;
-                       u64 reserved3;
-                       struct ehca_vsgentry sg_list[MAX_WQE_SG_ENTRIES];
-               } ud_avp;
-               struct {
-                       struct ehca_ud_av ud_av;
-                       struct ehca_vsgentry sg_list[MAX_WQE_SG_ENTRIES -
-                                                    2];
-               } ud_av;
-               struct {
-                       u64 reserved0;
-                       u64 reserved1;
-                       u64 reserved2;
-                       u64 reserved3;
-                       struct ehca_vsgentry sg_list[MAX_WQE_SG_ENTRIES];
-               } all_rcv;
-
-               struct {
-                       u64 reserved;
-                       u32 rkey;
-                       u32 old_rkey;
-                       u64 reserved1;
-                       u64 reserved2;
-                       u64 virtual_address;
-                       u32 reserved3;
-                       u32 length;
-                       u32 reserved4;
-                       u16 reserved5;
-                       u8 reserved6;
-                       u8 lr_ctl;
-                       u32 lkey;
-                       u32 reserved7;
-                       u64 reserved8;
-                       u64 reserved9;
-                       u64 reserved10;
-                       u64 reserved11;
-               } bind;
-               struct {
-                       u64 reserved12;
-                       u64 reserved13;
-                       u32 size;
-                       u32 start;
-               } inline_data;
-       } u;
-
-};
-
-#define WC_SEND_RECEIVE EHCA_BMASK_IBM(0, 0)
-#define WC_IMM_DATA     EHCA_BMASK_IBM(1, 1)
-#define WC_GRH_PRESENT  EHCA_BMASK_IBM(2, 2)
-#define WC_SE_BIT       EHCA_BMASK_IBM(3, 3)
-#define WC_STATUS_ERROR_BIT 0x80000000
-#define WC_STATUS_REMOTE_ERROR_FLAGS 0x0000F800
-#define WC_STATUS_PURGE_BIT 0x10
-#define WC_SEND_RECEIVE_BIT 0x80
-
-struct ehca_cqe {
-       u64 work_request_id;
-       u8 optype;
-       u8 w_completion_flags;
-       u16 reserved1;
-       u32 nr_bytes_transferred;
-       u32 immediate_data;
-       u32 local_qp_number;
-       u8 freed_resource_count;
-       u8 service_level;
-       u16 wqe_count;
-       u32 qp_token;
-       u32 qkey_ee_token;
-       u32 remote_qp_number;
-       u16 dlid;
-       u16 rlid;
-       u16 reserved2;
-       u16 pkey_index;
-       u32 cqe_timestamp;
-       u32 wqe_timestamp;
-       u8 wqe_timestamp_valid;
-       u8 reserved3;
-       u8 reserved4;
-       u8 cqe_flags;
-       u32 status;
-};
-
-struct ehca_eqe {
-       u64 entry;
-};
-
-struct ehca_mrte {
-       u64 starting_va;
-       u64 length; /* length of memory region in bytes*/
-       u32 pd;
-       u8 key_instance;
-       u8 pagesize;
-       u8 mr_control;
-       u8 local_remote_access_ctrl;
-       u8 reserved[0x20 - 0x18];
-       u64 at_pointer[4];
-};
-#endif /*_EHCA_QES_H_*/
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
deleted file mode 100644 (file)
index 2e89356..0000000
+++ /dev/null
@@ -1,2257 +0,0 @@
-/*
- *  IBM eServer eHCA Infiniband device driver for Linux on POWER
- *
- *  QP functions
- *
- *  Authors: Joachim Fenkes <fenkes@de.ibm.com>
- *           Stefan Roscher <stefan.roscher@de.ibm.com>
- *           Waleri Fomin <fomin@de.ibm.com>
- *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
- *           Reinhard Ernst <rernst@de.ibm.com>
- *           Heiko J Schick <schickhj@de.ibm.com>
- *
- *  Copyright (c) 2005 IBM Corporation
- *
- *  All rights reserved.
- *
- *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
- *  BSD.
- *
- * OpenIB BSD License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <linux/slab.h>
-
-#include "ehca_classes.h"
-#include "ehca_tools.h"
-#include "ehca_qes.h"
-#include "ehca_iverbs.h"
-#include "hcp_if.h"
-#include "hipz_fns.h"
-
-static struct kmem_cache *qp_cache;
-
-/*
- * attributes not supported by query qp
- */
-#define QP_ATTR_QUERY_NOT_SUPPORTED (IB_QP_ACCESS_FLAGS       | \
-                                    IB_QP_EN_SQD_ASYNC_NOTIFY)
-
-/*
- * ehca (internal) qp state values
- */
-enum ehca_qp_state {
-       EHCA_QPS_RESET = 1,
-       EHCA_QPS_INIT = 2,
-       EHCA_QPS_RTR = 3,
-       EHCA_QPS_RTS = 5,
-       EHCA_QPS_SQD = 6,
-       EHCA_QPS_SQE = 8,
-       EHCA_QPS_ERR = 128
-};
-
-/*
- * qp state transitions as defined by IB Arch Rel 1.1 page 431
- */
-enum ib_qp_statetrans {
-       IB_QPST_ANY2RESET,
-       IB_QPST_ANY2ERR,
-       IB_QPST_RESET2INIT,
-       IB_QPST_INIT2RTR,
-       IB_QPST_INIT2INIT,
-       IB_QPST_RTR2RTS,
-       IB_QPST_RTS2SQD,
-       IB_QPST_RTS2RTS,
-       IB_QPST_SQD2RTS,
-       IB_QPST_SQE2RTS,
-       IB_QPST_SQD2SQD,
-       IB_QPST_MAX     /* nr of transitions, this must be last!!! */
-};
-
-/*
- * ib2ehca_qp_state maps IB to ehca qp_state
- * returns ehca qp state corresponding to given ib qp state
- */
-static inline enum ehca_qp_state ib2ehca_qp_state(enum ib_qp_state ib_qp_state)
-{
-       switch (ib_qp_state) {
-       case IB_QPS_RESET:
-               return EHCA_QPS_RESET;
-       case IB_QPS_INIT:
-               return EHCA_QPS_INIT;
-       case IB_QPS_RTR:
-               return EHCA_QPS_RTR;
-       case IB_QPS_RTS:
-               return EHCA_QPS_RTS;
-       case IB_QPS_SQD:
-               return EHCA_QPS_SQD;
-       case IB_QPS_SQE:
-               return EHCA_QPS_SQE;
-       case IB_QPS_ERR:
-               return EHCA_QPS_ERR;
-       default:
-               ehca_gen_err("invalid ib_qp_state=%x", ib_qp_state);
-               return -EINVAL;
-       }
-}
-
-/*
- * ehca2ib_qp_state maps ehca to IB qp_state
- * returns ib qp state corresponding to given ehca qp state
- */
-static inline enum ib_qp_state ehca2ib_qp_state(enum ehca_qp_state
-                                               ehca_qp_state)
-{
-       switch (ehca_qp_state) {
-       case EHCA_QPS_RESET:
-               return IB_QPS_RESET;
-       case EHCA_QPS_INIT:
-               return IB_QPS_INIT;
-       case EHCA_QPS_RTR:
-               return IB_QPS_RTR;
-       case EHCA_QPS_RTS:
-               return IB_QPS_RTS;
-       case EHCA_QPS_SQD:
-               return IB_QPS_SQD;
-       case EHCA_QPS_SQE:
-               return IB_QPS_SQE;
-       case EHCA_QPS_ERR:
-               return IB_QPS_ERR;
-       default:
-               ehca_gen_err("invalid ehca_qp_state=%x", ehca_qp_state);
-               return -EINVAL;
-       }
-}
-
-/*
- * ehca_qp_type used as index for req_attr and opt_attr of
- * struct ehca_modqp_statetrans
- */
-enum ehca_qp_type {
-       QPT_RC = 0,
-       QPT_UC = 1,
-       QPT_UD = 2,
-       QPT_SQP = 3,
-       QPT_MAX
-};
-
-/*
- * ib2ehcaqptype maps Ib to ehca qp_type
- * returns ehca qp type corresponding to ib qp type
- */
-static inline enum ehca_qp_type ib2ehcaqptype(enum ib_qp_type ibqptype)
-{
-       switch (ibqptype) {
-       case IB_QPT_SMI:
-       case IB_QPT_GSI:
-               return QPT_SQP;
-       case IB_QPT_RC:
-               return QPT_RC;
-       case IB_QPT_UC:
-               return QPT_UC;
-       case IB_QPT_UD:
-               return QPT_UD;
-       default:
-               ehca_gen_err("Invalid ibqptype=%x", ibqptype);
-               return -EINVAL;
-       }
-}
-
-static inline enum ib_qp_statetrans get_modqp_statetrans(int ib_fromstate,
-                                                        int ib_tostate)
-{
-       int index = -EINVAL;
-       switch (ib_tostate) {
-       case IB_QPS_RESET:
-               index = IB_QPST_ANY2RESET;
-               break;
-       case IB_QPS_INIT:
-               switch (ib_fromstate) {
-               case IB_QPS_RESET:
-                       index = IB_QPST_RESET2INIT;
-                       break;
-               case IB_QPS_INIT:
-                       index = IB_QPST_INIT2INIT;
-                       break;
-               }
-               break;
-       case IB_QPS_RTR:
-               if (ib_fromstate == IB_QPS_INIT)
-                       index = IB_QPST_INIT2RTR;
-               break;
-       case IB_QPS_RTS:
-               switch (ib_fromstate) {
-               case IB_QPS_RTR:
-                       index = IB_QPST_RTR2RTS;
-                       break;
-               case IB_QPS_RTS:
-                       index = IB_QPST_RTS2RTS;
-                       break;
-               case IB_QPS_SQD:
-                       index = IB_QPST_SQD2RTS;
-                       break;
-               case IB_QPS_SQE:
-                       index = IB_QPST_SQE2RTS;
-                       break;
-               }
-               break;
-       case IB_QPS_SQD:
-               if (ib_fromstate == IB_QPS_RTS)
-                       index = IB_QPST_RTS2SQD;
-               break;
-       case IB_QPS_SQE:
-               break;
-       case IB_QPS_ERR:
-               index = IB_QPST_ANY2ERR;
-               break;
-       default:
-               break;
-       }
-       return index;
-}
-
-/*
- * ibqptype2servicetype returns hcp service type corresponding to given
- * ib qp type used by create_qp()
- */
-static inline int ibqptype2servicetype(enum ib_qp_type ibqptype)
-{
-       switch (ibqptype) {
-       case IB_QPT_SMI:
-       case IB_QPT_GSI:
-               return ST_UD;
-       case IB_QPT_RC:
-               return ST_RC;
-       case IB_QPT_UC:
-               return ST_UC;
-       case IB_QPT_UD:
-               return ST_UD;
-       case IB_QPT_RAW_IPV6:
-               return -EINVAL;
-       case IB_QPT_RAW_ETHERTYPE:
-               return -EINVAL;
-       default:
-               ehca_gen_err("Invalid ibqptype=%x", ibqptype);
-               return -EINVAL;
-       }
-}
-
-/*
- * init userspace queue info from ipz_queue data
- */
-static inline void queue2resp(struct ipzu_queue_resp *resp,
-                             struct ipz_queue *queue)
-{
-       resp->qe_size = queue->qe_size;
-       resp->act_nr_of_sg = queue->act_nr_of_sg;
-       resp->queue_length = queue->queue_length;
-       resp->pagesize = queue->pagesize;
-       resp->toggle_state = queue->toggle_state;
-       resp->offset = queue->offset;
-}
-
-/*
- * init_qp_queue initializes/constructs r/squeue and registers queue pages.
- */
-static inline int init_qp_queue(struct ehca_shca *shca,
-                               struct ehca_pd *pd,
-                               struct ehca_qp *my_qp,
-                               struct ipz_queue *queue,
-                               int q_type,
-                               u64 expected_hret,
-                               struct ehca_alloc_queue_parms *parms,
-                               int wqe_size)
-{
-       int ret, cnt, ipz_rc, nr_q_pages;
-       void *vpage;
-       u64 rpage, h_ret;
-       struct ib_device *ib_dev = &shca->ib_device;
-       struct ipz_adapter_handle ipz_hca_handle = shca->ipz_hca_handle;
-
-       if (!parms->queue_size)
-               return 0;
-
-       if (parms->is_small) {
-               nr_q_pages = 1;
-               ipz_rc = ipz_queue_ctor(pd, queue, nr_q_pages,
-                                       128 << parms->page_size,
-                                       wqe_size, parms->act_nr_sges, 1);
-       } else {
-               nr_q_pages = parms->queue_size;
-               ipz_rc = ipz_queue_ctor(pd, queue, nr_q_pages,
-                                       EHCA_PAGESIZE, wqe_size,
-                                       parms->act_nr_sges, 0);
-       }
-
-       if (!ipz_rc) {
-               ehca_err(ib_dev, "Cannot allocate page for queue. ipz_rc=%i",
-                        ipz_rc);
-               return -EBUSY;
-       }
-
-       /* register queue pages */
-       for (cnt = 0; cnt < nr_q_pages; cnt++) {
-               vpage = ipz_qpageit_get_inc(queue);
-               if (!vpage) {
-                       ehca_err(ib_dev, "ipz_qpageit_get_inc() "
-                                "failed p_vpage= %p", vpage);
-                       ret = -EINVAL;
-                       goto init_qp_queue1;
-               }
-               rpage = __pa(vpage);
-
-               h_ret = hipz_h_register_rpage_qp(ipz_hca_handle,
-                                                my_qp->ipz_qp_handle,
-                                                NULL, 0, q_type,
-                                                rpage, parms->is_small ? 0 : 1,
-                                                my_qp->galpas.kernel);
-               if (cnt == (nr_q_pages - 1)) {  /* last page! */
-                       if (h_ret != expected_hret) {
-                               ehca_err(ib_dev, "hipz_qp_register_rpage() "
-                                        "h_ret=%lli", h_ret);
-                               ret = ehca2ib_return_code(h_ret);
-                               goto init_qp_queue1;
-                       }
-                       vpage = ipz_qpageit_get_inc(&my_qp->ipz_rqueue);
-                       if (vpage) {
-                               ehca_err(ib_dev, "ipz_qpageit_get_inc() "
-                                        "should not succeed vpage=%p", vpage);
-                               ret = -EINVAL;
-                               goto init_qp_queue1;
-                       }
-               } else {
-                       if (h_ret != H_PAGE_REGISTERED) {
-                               ehca_err(ib_dev, "hipz_qp_register_rpage() "
-                                        "h_ret=%lli", h_ret);
-                               ret = ehca2ib_return_code(h_ret);
-                               goto init_qp_queue1;
-                       }
-               }
-       }
-
-       ipz_qeit_reset(queue);
-
-       return 0;
-
-init_qp_queue1:
-       ipz_queue_dtor(pd, queue);
-       return ret;
-}
-
-static inline int ehca_calc_wqe_size(int act_nr_sge, int is_llqp)
-{
-       if (is_llqp)
-               return 128 << act_nr_sge;
-       else
-               return offsetof(struct ehca_wqe,
-                               u.nud.sg_list[act_nr_sge]);
-}
-
-static void ehca_determine_small_queue(struct ehca_alloc_queue_parms *queue,
-                                      int req_nr_sge, int is_llqp)
-{
-       u32 wqe_size, q_size;
-       int act_nr_sge = req_nr_sge;
-
-       if (!is_llqp)
-               /* round up #SGEs so WQE size is a power of 2 */
-               for (act_nr_sge = 4; act_nr_sge <= 252;
-                    act_nr_sge = 4 + 2 * act_nr_sge)
-                       if (act_nr_sge >= req_nr_sge)
-                               break;
-
-       wqe_size = ehca_calc_wqe_size(act_nr_sge, is_llqp);
-       q_size = wqe_size * (queue->max_wr + 1);
-
-       if (q_size <= 512)
-               queue->page_size = 2;
-       else if (q_size <= 1024)
-               queue->page_size = 3;
-       else
-               queue->page_size = 0;
-
-       queue->is_small = (queue->page_size != 0);
-}
-
-/* needs to be called with cq->spinlock held */
-void ehca_add_to_err_list(struct ehca_qp *qp, int on_sq)
-{
-       struct list_head *list, *node;
-
-       /* TODO: support low latency QPs */
-       if (qp->ext_type == EQPT_LLQP)
-               return;
-
-       if (on_sq) {
-               list = &qp->send_cq->sqp_err_list;
-               node = &qp->sq_err_node;
-       } else {
-               list = &qp->recv_cq->rqp_err_list;
-               node = &qp->rq_err_node;
-       }
-
-       if (list_empty(node))
-               list_add_tail(node, list);
-
-       return;
-}
-
-static void del_from_err_list(struct ehca_cq *cq, struct list_head *node)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&cq->spinlock, flags);
-
-       if (!list_empty(node))
-               list_del_init(node);
-
-       spin_unlock_irqrestore(&cq->spinlock, flags);
-}
-
-static void reset_queue_map(struct ehca_queue_map *qmap)
-{
-       int i;
-
-       qmap->tail = qmap->entries - 1;
-       qmap->left_to_poll = 0;
-       qmap->next_wqe_idx = 0;
-       for (i = 0; i < qmap->entries; i++) {
-               qmap->map[i].reported = 1;
-               qmap->map[i].cqe_req = 0;
-       }
-}
-
-/*
- * Create an ib_qp struct that is either a QP or an SRQ, depending on
- * the value of the is_srq parameter. If init_attr and srq_init_attr share
- * fields, the field out of init_attr is used.
- */
-static struct ehca_qp *internal_create_qp(
-       struct ib_pd *pd,
-       struct ib_qp_init_attr *init_attr,
-       struct ib_srq_init_attr *srq_init_attr,
-       struct ib_udata *udata, int is_srq)
-{
-       struct ehca_qp *my_qp, *my_srq = NULL;
-       struct ehca_pd *my_pd = container_of(pd, struct ehca_pd, ib_pd);
-       struct ehca_shca *shca = container_of(pd->device, struct ehca_shca,
-                                             ib_device);
-       struct ib_ucontext *context = NULL;
-       u64 h_ret;
-       int is_llqp = 0, has_srq = 0, is_user = 0;
-       int qp_type, max_send_sge, max_recv_sge, ret;
-
-       /* h_call's out parameters */
-       struct ehca_alloc_qp_parms parms;
-       u32 swqe_size = 0, rwqe_size = 0, ib_qp_num;
-       unsigned long flags;
-
-       if (!atomic_add_unless(&shca->num_qps, 1, shca->max_num_qps)) {
-               ehca_err(pd->device, "Unable to create QP, max number of %i "
-                        "QPs reached.", shca->max_num_qps);
-               ehca_err(pd->device, "To increase the maximum number of QPs "
-                        "use the number_of_qps module parameter.\n");
-               return ERR_PTR(-ENOSPC);
-       }
-
-       if (init_attr->create_flags) {
-               atomic_dec(&shca->num_qps);
-               return ERR_PTR(-EINVAL);
-       }
-
-       memset(&parms, 0, sizeof(parms));
-       qp_type = init_attr->qp_type;
-
-       if (init_attr->sq_sig_type != IB_SIGNAL_REQ_WR &&
-               init_attr->sq_sig_type != IB_SIGNAL_ALL_WR) {
-               ehca_err(pd->device, "init_attr->sg_sig_type=%x not allowed",
-                        init_attr->sq_sig_type);
-               atomic_dec(&shca->num_qps);
-               return ERR_PTR(-EINVAL);
-       }
-
-       /* save LLQP info */
-       if (qp_type & 0x80) {
-               is_llqp = 1;
-               parms.ext_type = EQPT_LLQP;
-               parms.ll_comp_flags = qp_type & LLQP_COMP_MASK;
-       }
-       qp_type &= 0x1F;
-       init_attr->qp_type &= 0x1F;
-
-       /* handle SRQ base QPs */
-       if (init_attr->srq) {
-               my_srq = container_of(init_attr->srq, struct ehca_qp, ib_srq);
-
-               if (qp_type == IB_QPT_UC) {
-                       ehca_err(pd->device, "UC with SRQ not supported");
-                       atomic_dec(&shca->num_qps);
-                       return ERR_PTR(-EINVAL);
-               }
-
-               has_srq = 1;
-               parms.ext_type = EQPT_SRQBASE;
-               parms.srq_qpn = my_srq->real_qp_num;
-       }
-
-       if (is_llqp && has_srq) {
-               ehca_err(pd->device, "LLQPs can't have an SRQ");
-               atomic_dec(&shca->num_qps);
-               return ERR_PTR(-EINVAL);
-       }
-
-       /* handle SRQs */
-       if (is_srq) {
-               parms.ext_type = EQPT_SRQ;
-               parms.srq_limit = srq_init_attr->attr.srq_limit;
-               if (init_attr->cap.max_recv_sge > 3) {
-                       ehca_err(pd->device, "no more than three SGEs "
-                                "supported for SRQ  pd=%p  max_sge=%x",
-                                pd, init_attr->cap.max_recv_sge);
-                       atomic_dec(&shca->num_qps);
-                       return ERR_PTR(-EINVAL);
-               }
-       }
-
-       /* check QP type */
-       if (qp_type != IB_QPT_UD &&
-           qp_type != IB_QPT_UC &&
-           qp_type != IB_QPT_RC &&
-           qp_type != IB_QPT_SMI &&
-           qp_type != IB_QPT_GSI) {
-               ehca_err(pd->device, "wrong QP Type=%x", qp_type);
-               atomic_dec(&shca->num_qps);
-               return ERR_PTR(-EINVAL);
-       }
-
-       if (is_llqp) {
-               switch (qp_type) {
-               case IB_QPT_RC:
-                       if ((init_attr->cap.max_send_wr > 255) ||
-                           (init_attr->cap.max_recv_wr > 255)) {
-                               ehca_err(pd->device,
-                                        "Invalid Number of max_sq_wr=%x "
-                                        "or max_rq_wr=%x for RC LLQP",
-                                        init_attr->cap.max_send_wr,
-                                        init_attr->cap.max_recv_wr);
-                               atomic_dec(&shca->num_qps);
-                               return ERR_PTR(-EINVAL);
-                       }
-                       break;
-               case IB_QPT_UD:
-                       if (!EHCA_BMASK_GET(HCA_CAP_UD_LL_QP, shca->hca_cap)) {
-                               ehca_err(pd->device, "UD LLQP not supported "
-                                        "by this adapter");
-                               atomic_dec(&shca->num_qps);
-                               return ERR_PTR(-ENOSYS);
-                       }
-                       if (!(init_attr->cap.max_send_sge <= 5
-                           && init_attr->cap.max_send_sge >= 1
-                           && init_attr->cap.max_recv_sge <= 5
-                           && init_attr->cap.max_recv_sge >= 1)) {
-                               ehca_err(pd->device,
-                                        "Invalid Number of max_send_sge=%x "
-                                        "or max_recv_sge=%x for UD LLQP",
-                                        init_attr->cap.max_send_sge,
-                                        init_attr->cap.max_recv_sge);
-                               atomic_dec(&shca->num_qps);
-                               return ERR_PTR(-EINVAL);
-                       } else if (init_attr->cap.max_send_wr > 255) {
-                               ehca_err(pd->device,
-                                        "Invalid Number of "
-                                        "max_send_wr=%x for UD QP_TYPE=%x",
-                                        init_attr->cap.max_send_wr, qp_type);
-                               atomic_dec(&shca->num_qps);
-                               return ERR_PTR(-EINVAL);
-                       }
-                       break;
-               default:
-                       ehca_err(pd->device, "unsupported LL QP Type=%x",
-                                qp_type);
-                       atomic_dec(&shca->num_qps);
-                       return ERR_PTR(-EINVAL);
-               }
-       } else {
-               int max_sge = (qp_type == IB_QPT_UD || qp_type == IB_QPT_SMI
-                              || qp_type == IB_QPT_GSI) ? 250 : 252;
-
-               if (init_attr->cap.max_send_sge > max_sge
-                   || init_attr->cap.max_recv_sge > max_sge) {
-                       ehca_err(pd->device, "Invalid number of SGEs requested "
-                                "send_sge=%x recv_sge=%x max_sge=%x",
-                                init_attr->cap.max_send_sge,
-                                init_attr->cap.max_recv_sge, max_sge);
-                       atomic_dec(&shca->num_qps);
-                       return ERR_PTR(-EINVAL);
-               }
-       }
-
-       my_qp = kmem_cache_zalloc(qp_cache, GFP_KERNEL);
-       if (!my_qp) {
-               ehca_err(pd->device, "pd=%p not enough memory to alloc qp", pd);
-               atomic_dec(&shca->num_qps);
-               return ERR_PTR(-ENOMEM);
-       }
-
-       if (pd->uobject && udata) {
-               is_user = 1;
-               context = pd->uobject->context;
-       }
-
-       atomic_set(&my_qp->nr_events, 0);
-       init_waitqueue_head(&my_qp->wait_completion);
-       spin_lock_init(&my_qp->spinlock_s);
-       spin_lock_init(&my_qp->spinlock_r);
-       my_qp->qp_type = qp_type;
-       my_qp->ext_type = parms.ext_type;
-       my_qp->state = IB_QPS_RESET;
-
-       if (init_attr->recv_cq)
-               my_qp->recv_cq =
-                       container_of(init_attr->recv_cq, struct ehca_cq, ib_cq);
-       if (init_attr->send_cq)
-               my_qp->send_cq =
-                       container_of(init_attr->send_cq, struct ehca_cq, ib_cq);
-
-       idr_preload(GFP_KERNEL);
-       write_lock_irqsave(&ehca_qp_idr_lock, flags);
-
-       ret = idr_alloc(&ehca_qp_idr, my_qp, 0, 0x2000000, GFP_NOWAIT);
-       if (ret >= 0)
-               my_qp->token = ret;
-
-       write_unlock_irqrestore(&ehca_qp_idr_lock, flags);
-       idr_preload_end();
-       if (ret < 0) {
-               if (ret == -ENOSPC) {
-                       ret = -EINVAL;
-                       ehca_err(pd->device, "Invalid number of qp");
-               } else {
-                       ret = -ENOMEM;
-                       ehca_err(pd->device, "Can't allocate new idr entry.");
-               }
-               goto create_qp_exit0;
-       }
-
-       if (has_srq)
-               parms.srq_token = my_qp->token;
-
-       parms.servicetype = ibqptype2servicetype(qp_type);
-       if (parms.servicetype < 0) {
-               ret = -EINVAL;
-               ehca_err(pd->device, "Invalid qp_type=%x", qp_type);
-               goto create_qp_exit1;
-       }
-
-       /* Always signal by WQE so we can hide circ. WQEs */
-       parms.sigtype = HCALL_SIGT_BY_WQE;
-
-       /* UD_AV CIRCUMVENTION */
-       max_send_sge = init_attr->cap.max_send_sge;
-       max_recv_sge = init_attr->cap.max_recv_sge;
-       if (parms.servicetype == ST_UD && !is_llqp) {
-               max_send_sge += 2;
-               max_recv_sge += 2;
-       }
-
-       parms.token = my_qp->token;
-       parms.eq_handle = shca->eq.ipz_eq_handle;
-       parms.pd = my_pd->fw_pd;
-       if (my_qp->send_cq)
-               parms.send_cq_handle = my_qp->send_cq->ipz_cq_handle;
-       if (my_qp->recv_cq)
-               parms.recv_cq_handle = my_qp->recv_cq->ipz_cq_handle;
-
-       parms.squeue.max_wr = init_attr->cap.max_send_wr;
-       parms.rqueue.max_wr = init_attr->cap.max_recv_wr;
-       parms.squeue.max_sge = max_send_sge;
-       parms.rqueue.max_sge = max_recv_sge;
-
-       /* RC QPs need one more SWQE for unsolicited ack circumvention */
-       if (qp_type == IB_QPT_RC)
-               parms.squeue.max_wr++;
-
-       if (EHCA_BMASK_GET(HCA_CAP_MINI_QP, shca->hca_cap)) {
-               if (HAS_SQ(my_qp))
-                       ehca_determine_small_queue(
-                               &parms.squeue, max_send_sge, is_llqp);
-               if (HAS_RQ(my_qp))
-                       ehca_determine_small_queue(
-                               &parms.rqueue, max_recv_sge, is_llqp);
-               parms.qp_storage =
-                       (parms.squeue.is_small || parms.rqueue.is_small);
-       }
-
-       h_ret = hipz_h_alloc_resource_qp(shca->ipz_hca_handle, &parms, is_user);
-       if (h_ret != H_SUCCESS) {
-               ehca_err(pd->device, "h_alloc_resource_qp() failed h_ret=%lli",
-                        h_ret);
-               ret = ehca2ib_return_code(h_ret);
-               goto create_qp_exit1;
-       }
-
-       ib_qp_num = my_qp->real_qp_num = parms.real_qp_num;
-       my_qp->ipz_qp_handle = parms.qp_handle;
-       my_qp->galpas = parms.galpas;
-
-       swqe_size = ehca_calc_wqe_size(parms.squeue.act_nr_sges, is_llqp);
-       rwqe_size = ehca_calc_wqe_size(parms.rqueue.act_nr_sges, is_llqp);
-
-       switch (qp_type) {
-       case IB_QPT_RC:
-               if (is_llqp) {
-                       parms.squeue.act_nr_sges = 1;
-                       parms.rqueue.act_nr_sges = 1;
-               }
-               /* hide the extra WQE */
-               parms.squeue.act_nr_wqes--;
-               break;
-       case IB_QPT_UD:
-       case IB_QPT_GSI:
-       case IB_QPT_SMI:
-               /* UD circumvention */
-               if (is_llqp) {
-                       parms.squeue.act_nr_sges = 1;
-                       parms.rqueue.act_nr_sges = 1;
-               } else {
-                       parms.squeue.act_nr_sges -= 2;
-                       parms.rqueue.act_nr_sges -= 2;
-               }
-
-               if (IB_QPT_GSI == qp_type || IB_QPT_SMI == qp_type) {
-                       parms.squeue.act_nr_wqes = init_attr->cap.max_send_wr;
-                       parms.rqueue.act_nr_wqes = init_attr->cap.max_recv_wr;
-                       parms.squeue.act_nr_sges = init_attr->cap.max_send_sge;
-                       parms.rqueue.act_nr_sges = init_attr->cap.max_recv_sge;
-                       ib_qp_num = (qp_type == IB_QPT_SMI) ? 0 : 1;
-               }
-
-               break;
-
-       default:
-               break;
-       }
-
-       /* initialize r/squeue and register queue pages */
-       if (HAS_SQ(my_qp)) {
-               ret = init_qp_queue(
-                       shca, my_pd, my_qp, &my_qp->ipz_squeue, 0,
-                       HAS_RQ(my_qp) ? H_PAGE_REGISTERED : H_SUCCESS,
-                       &parms.squeue, swqe_size);
-               if (ret) {
-                       ehca_err(pd->device, "Couldn't initialize squeue "
-                                "and pages ret=%i", ret);
-                       goto create_qp_exit2;
-               }
-
-               if (!is_user) {
-                       my_qp->sq_map.entries = my_qp->ipz_squeue.queue_length /
-                               my_qp->ipz_squeue.qe_size;
-                       my_qp->sq_map.map = vmalloc(my_qp->sq_map.entries *
-                                                   sizeof(struct ehca_qmap_entry));
-                       if (!my_qp->sq_map.map) {
-                               ehca_err(pd->device, "Couldn't allocate squeue "
-                                        "map ret=%i", ret);
-                               goto create_qp_exit3;
-                       }
-                       INIT_LIST_HEAD(&my_qp->sq_err_node);
-                       /* to avoid the generation of bogus flush CQEs */
-                       reset_queue_map(&my_qp->sq_map);
-               }
-       }
-
-       if (HAS_RQ(my_qp)) {
-               ret = init_qp_queue(
-                       shca, my_pd, my_qp, &my_qp->ipz_rqueue, 1,
-                       H_SUCCESS, &parms.rqueue, rwqe_size);
-               if (ret) {
-                       ehca_err(pd->device, "Couldn't initialize rqueue "
-                                "and pages ret=%i", ret);
-                       goto create_qp_exit4;
-               }
-               if (!is_user) {
-                       my_qp->rq_map.entries = my_qp->ipz_rqueue.queue_length /
-                               my_qp->ipz_rqueue.qe_size;
-                       my_qp->rq_map.map = vmalloc(my_qp->rq_map.entries *
-                                                   sizeof(struct ehca_qmap_entry));
-                       if (!my_qp->rq_map.map) {
-                               ehca_err(pd->device, "Couldn't allocate squeue "
-                                        "map ret=%i", ret);
-                               goto create_qp_exit5;
-                       }
-                       INIT_LIST_HEAD(&my_qp->rq_err_node);
-                       /* to avoid the generation of bogus flush CQEs */
-                       reset_queue_map(&my_qp->rq_map);
-               }
-       } else if (init_attr->srq && !is_user) {
-               /* this is a base QP, use the queue map of the SRQ */
-               my_qp->rq_map = my_srq->rq_map;
-               INIT_LIST_HEAD(&my_qp->rq_err_node);
-
-               my_qp->ipz_rqueue = my_srq->ipz_rqueue;
-       }
-
-       if (is_srq) {
-               my_qp->ib_srq.pd = &my_pd->ib_pd;
-               my_qp->ib_srq.device = my_pd->ib_pd.device;
-
-               my_qp->ib_srq.srq_context = init_attr->qp_context;
-               my_qp->ib_srq.event_handler = init_attr->event_handler;
-       } else {
-               my_qp->ib_qp.qp_num = ib_qp_num;
-               my_qp->ib_qp.pd = &my_pd->ib_pd;
-               my_qp->ib_qp.device = my_pd->ib_pd.device;
-
-               my_qp->ib_qp.recv_cq = init_attr->recv_cq;
-               my_qp->ib_qp.send_cq = init_attr->send_cq;
-
-               my_qp->ib_qp.qp_type = qp_type;
-               my_qp->ib_qp.srq = init_attr->srq;
-
-               my_qp->ib_qp.qp_context = init_attr->qp_context;
-               my_qp->ib_qp.event_handler = init_attr->event_handler;
-       }
-
-       init_attr->cap.max_inline_data = 0; /* not supported yet */
-       init_attr->cap.max_recv_sge = parms.rqueue.act_nr_sges;
-       init_attr->cap.max_recv_wr = parms.rqueue.act_nr_wqes;
-       init_attr->cap.max_send_sge = parms.squeue.act_nr_sges;
-       init_attr->cap.max_send_wr = parms.squeue.act_nr_wqes;
-       my_qp->init_attr = *init_attr;
-
-       if (qp_type == IB_QPT_SMI || qp_type == IB_QPT_GSI) {
-               shca->sport[init_attr->port_num - 1].ibqp_sqp[qp_type] =
-                       &my_qp->ib_qp;
-               if (ehca_nr_ports < 0) {
-                       /* alloc array to cache subsequent modify qp parms
-                        * for autodetect mode
-                        */
-                       my_qp->mod_qp_parm =
-                               kzalloc(EHCA_MOD_QP_PARM_MAX *
-                                       sizeof(*my_qp->mod_qp_parm),
-                                       GFP_KERNEL);
-                       if (!my_qp->mod_qp_parm) {
-                               ehca_err(pd->device,
-                                        "Could not alloc mod_qp_parm");
-                               goto create_qp_exit5;
-                       }
-               }
-       }
-
-       /* NOTE: define_apq0() not supported yet */
-       if (qp_type == IB_QPT_GSI) {
-               h_ret = ehca_define_sqp(shca, my_qp, init_attr);
-               if (h_ret != H_SUCCESS) {
-                       kfree(my_qp->mod_qp_parm);
-                       my_qp->mod_qp_parm = NULL;
-                       /* the QP pointer is no longer valid */
-                       shca->sport[init_attr->port_num - 1].ibqp_sqp[qp_type] =
-                               NULL;
-                       ret = ehca2ib_return_code(h_ret);
-                       goto create_qp_exit6;
-               }
-       }
-
-       if (my_qp->send_cq) {
-               ret = ehca_cq_assign_qp(my_qp->send_cq, my_qp);
-               if (ret) {
-                       ehca_err(pd->device,
-                                "Couldn't assign qp to send_cq ret=%i", ret);
-                       goto create_qp_exit7;
-               }
-       }
-
-       /* copy queues, galpa data to user space */
-       if (context && udata) {
-               struct ehca_create_qp_resp resp;
-               memset(&resp, 0, sizeof(resp));
-
-               resp.qp_num = my_qp->real_qp_num;
-               resp.token = my_qp->token;
-               resp.qp_type = my_qp->qp_type;
-               resp.ext_type = my_qp->ext_type;
-               resp.qkey = my_qp->qkey;
-               resp.real_qp_num = my_qp->real_qp_num;
-
-               if (HAS_SQ(my_qp))
-                       queue2resp(&resp.ipz_squeue, &my_qp->ipz_squeue);
-               if (HAS_RQ(my_qp))
-                       queue2resp(&resp.ipz_rqueue, &my_qp->ipz_rqueue);
-               resp.fw_handle_ofs = (u32)
-                       (my_qp->galpas.user.fw_handle & (PAGE_SIZE - 1));
-
-               if (ib_copy_to_udata(udata, &resp, sizeof resp)) {
-                       ehca_err(pd->device, "Copy to udata failed");
-                       ret = -EINVAL;
-                       goto create_qp_exit8;
-               }
-       }
-
-       return my_qp;
-
-create_qp_exit8:
-       ehca_cq_unassign_qp(my_qp->send_cq, my_qp->real_qp_num);
-
-create_qp_exit7:
-       kfree(my_qp->mod_qp_parm);
-
-create_qp_exit6:
-       if (HAS_RQ(my_qp) && !is_user)
-               vfree(my_qp->rq_map.map);
-
-create_qp_exit5:
-       if (HAS_RQ(my_qp))
-               ipz_queue_dtor(my_pd, &my_qp->ipz_rqueue);
-
-create_qp_exit4:
-       if (HAS_SQ(my_qp) && !is_user)
-               vfree(my_qp->sq_map.map);
-
-create_qp_exit3:
-       if (HAS_SQ(my_qp))
-               ipz_queue_dtor(my_pd, &my_qp->ipz_squeue);
-
-create_qp_exit2:
-       hipz_h_destroy_qp(shca->ipz_hca_handle, my_qp);
-
-create_qp_exit1:
-       write_lock_irqsave(&ehca_qp_idr_lock, flags);
-       idr_remove(&ehca_qp_idr, my_qp->token);
-       write_unlock_irqrestore(&ehca_qp_idr_lock, flags);
-
-create_qp_exit0:
-       kmem_cache_free(qp_cache, my_qp);
-       atomic_dec(&shca->num_qps);
-       return ERR_PTR(ret);
-}
-
-struct ib_qp *ehca_create_qp(struct ib_pd *pd,
-                            struct ib_qp_init_attr *qp_init_attr,
-                            struct ib_udata *udata)
-{
-       struct ehca_qp *ret;
-
-       ret = internal_create_qp(pd, qp_init_attr, NULL, udata, 0);
-       return IS_ERR(ret) ? (struct ib_qp *)ret : &ret->ib_qp;
-}
-
-static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
-                              struct ib_uobject *uobject);
-
-struct ib_srq *ehca_create_srq(struct ib_pd *pd,
-                              struct ib_srq_init_attr *srq_init_attr,
-                              struct ib_udata *udata)
-{
-       struct ib_qp_init_attr qp_init_attr;
-       struct ehca_qp *my_qp;
-       struct ib_srq *ret;
-       struct ehca_shca *shca = container_of(pd->device, struct ehca_shca,
-                                             ib_device);
-       struct hcp_modify_qp_control_block *mqpcb;
-       u64 hret, update_mask;
-
-       if (srq_init_attr->srq_type != IB_SRQT_BASIC)
-               return ERR_PTR(-ENOSYS);
-
-       /* For common attributes, internal_create_qp() takes its info
-        * out of qp_init_attr, so copy all common attrs there.
-        */
-       memset(&qp_init_attr, 0, sizeof(qp_init_attr));
-       qp_init_attr.event_handler = srq_init_attr->event_handler;
-       qp_init_attr.qp_context = srq_init_attr->srq_context;
-       qp_init_attr.sq_sig_type = IB_SIGNAL_ALL_WR;
-       qp_init_attr.qp_type = IB_QPT_RC;
-       qp_init_attr.cap.max_recv_wr = srq_init_attr->attr.max_wr;
-       qp_init_attr.cap.max_recv_sge = srq_init_attr->attr.max_sge;
-
-       my_qp = internal_create_qp(pd, &qp_init_attr, srq_init_attr, udata, 1);
-       if (IS_ERR(my_qp))
-               return (struct ib_srq *)my_qp;
-
-       /* copy back return values */
-       srq_init_attr->attr.max_wr = qp_init_attr.cap.max_recv_wr;
-       srq_init_attr->attr.max_sge = 3;
-
-       /* drive SRQ into RTR state */
-       mqpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
-       if (!mqpcb) {
-               ehca_err(pd->device, "Could not get zeroed page for mqpcb "
-                        "ehca_qp=%p qp_num=%x ", my_qp, my_qp->real_qp_num);
-               ret = ERR_PTR(-ENOMEM);
-               goto create_srq1;
-       }
-
-       mqpcb->qp_state = EHCA_QPS_INIT;
-       mqpcb->prim_phys_port = 1;
-       update_mask = EHCA_BMASK_SET(MQPCB_MASK_QP_STATE, 1);
-       hret = hipz_h_modify_qp(shca->ipz_hca_handle,
-                               my_qp->ipz_qp_handle,
-                               &my_qp->pf,
-                               update_mask,
-                               mqpcb, my_qp->galpas.kernel);
-       if (hret != H_SUCCESS) {
-               ehca_err(pd->device, "Could not modify SRQ to INIT "
-                        "ehca_qp=%p qp_num=%x h_ret=%lli",
-                        my_qp, my_qp->real_qp_num, hret);
-               goto create_srq2;
-       }
-
-       mqpcb->qp_enable = 1;
-       update_mask = EHCA_BMASK_SET(MQPCB_MASK_QP_ENABLE, 1);
-       hret = hipz_h_modify_qp(shca->ipz_hca_handle,
-                               my_qp->ipz_qp_handle,
-                               &my_qp->pf,
-                               update_mask,
-                               mqpcb, my_qp->galpas.kernel);
-       if (hret != H_SUCCESS) {
-               ehca_err(pd->device, "Could not enable SRQ "
-                        "ehca_qp=%p qp_num=%x h_ret=%lli",
-                        my_qp, my_qp->real_qp_num, hret);
-               goto create_srq2;
-       }
-
-       mqpcb->qp_state  = EHCA_QPS_RTR;
-       update_mask = EHCA_BMASK_SET(MQPCB_MASK_QP_STATE, 1);
-       hret = hipz_h_modify_qp(shca->ipz_hca_handle,
-                               my_qp->ipz_qp_handle,
-                               &my_qp->pf,
-                               update_mask,
-                               mqpcb, my_qp->galpas.kernel);
-       if (hret != H_SUCCESS) {
-               ehca_err(pd->device, "Could not modify SRQ to RTR "
-                        "ehca_qp=%p qp_num=%x h_ret=%lli",
-                        my_qp, my_qp->real_qp_num, hret);
-               goto create_srq2;
-       }
-
-       ehca_free_fw_ctrlblock(mqpcb);
-
-       return &my_qp->ib_srq;
-
-create_srq2:
-       ret = ERR_PTR(ehca2ib_return_code(hret));
-       ehca_free_fw_ctrlblock(mqpcb);
-
-create_srq1:
-       internal_destroy_qp(pd->device, my_qp, my_qp->ib_srq.uobject);
-
-       return ret;
-}
-
-/*
- * prepare_sqe_rts called by internal_modify_qp() at trans sqe -> rts
- * set purge bit of bad wqe and subsequent wqes to avoid reentering sqe
- * returns total number of bad wqes in bad_wqe_cnt
- */
-static int prepare_sqe_rts(struct ehca_qp *my_qp, struct ehca_shca *shca,
-                          int *bad_wqe_cnt)
-{
-       u64 h_ret;
-       struct ipz_queue *squeue;
-       void *bad_send_wqe_p, *bad_send_wqe_v;
-       u64 q_ofs;
-       struct ehca_wqe *wqe;
-       int qp_num = my_qp->ib_qp.qp_num;
-
-       /* get send wqe pointer */
-       h_ret = hipz_h_disable_and_get_wqe(shca->ipz_hca_handle,
-                                          my_qp->ipz_qp_handle, &my_qp->pf,
-                                          &bad_send_wqe_p, NULL, 2);
-       if (h_ret != H_SUCCESS) {
-               ehca_err(&shca->ib_device, "hipz_h_disable_and_get_wqe() failed"
-                        " ehca_qp=%p qp_num=%x h_ret=%lli",
-                        my_qp, qp_num, h_ret);
-               return ehca2ib_return_code(h_ret);
-       }
-       bad_send_wqe_p = (void *)((u64)bad_send_wqe_p & (~(1L << 63)));
-       ehca_dbg(&shca->ib_device, "qp_num=%x bad_send_wqe_p=%p",
-                qp_num, bad_send_wqe_p);
-       /* convert wqe pointer to vadr */
-       bad_send_wqe_v = __va((u64)bad_send_wqe_p);
-       if (ehca_debug_level >= 2)
-               ehca_dmp(bad_send_wqe_v, 32, "qp_num=%x bad_wqe", qp_num);
-       squeue = &my_qp->ipz_squeue;
-       if (ipz_queue_abs_to_offset(squeue, (u64)bad_send_wqe_p, &q_ofs)) {
-               ehca_err(&shca->ib_device, "failed to get wqe offset qp_num=%x"
-                        " bad_send_wqe_p=%p", qp_num, bad_send_wqe_p);
-               return -EFAULT;
-       }
-
-       /* loop sets wqe's purge bit */
-       wqe = (struct ehca_wqe *)ipz_qeit_calc(squeue, q_ofs);
-       *bad_wqe_cnt = 0;
-       while (wqe->optype != 0xff && wqe->wqef != 0xff) {
-               if (ehca_debug_level >= 2)
-                       ehca_dmp(wqe, 32, "qp_num=%x wqe", qp_num);
-               wqe->nr_of_data_seg = 0; /* suppress data access */
-               wqe->wqef = WQEF_PURGE; /* WQE to be purged */
-               q_ofs = ipz_queue_advance_offset(squeue, q_ofs);
-               wqe = (struct ehca_wqe *)ipz_qeit_calc(squeue, q_ofs);
-               *bad_wqe_cnt = (*bad_wqe_cnt)+1;
-       }
-       /*
-        * bad wqe will be reprocessed and ignored when pol_cq() is called,
-        *  i.e. nr of wqes with flush error status is one less
-        */
-       ehca_dbg(&shca->ib_device, "qp_num=%x flusherr_wqe_cnt=%x",
-                qp_num, (*bad_wqe_cnt)-1);
-       wqe->wqef = 0;
-
-       return 0;
-}
-
-static int calc_left_cqes(u64 wqe_p, struct ipz_queue *ipz_queue,
-                         struct ehca_queue_map *qmap)
-{
-       void *wqe_v;
-       u64 q_ofs;
-       u32 wqe_idx;
-       unsigned int tail_idx;
-
-       /* convert real to abs address */
-       wqe_p = wqe_p & (~(1UL << 63));
-
-       wqe_v = __va(wqe_p);
-
-       if (ipz_queue_abs_to_offset(ipz_queue, wqe_p, &q_ofs)) {
-               ehca_gen_err("Invalid offset for calculating left cqes "
-                               "wqe_p=%#llx wqe_v=%p\n", wqe_p, wqe_v);
-               return -EFAULT;
-       }
-
-       tail_idx = next_index(qmap->tail, qmap->entries);
-       wqe_idx = q_ofs / ipz_queue->qe_size;
-
-       /* check all processed wqes, whether a cqe is requested or not */
-       while (tail_idx != wqe_idx) {
-               if (qmap->map[tail_idx].cqe_req)
-                       qmap->left_to_poll++;
-               tail_idx = next_index(tail_idx, qmap->entries);
-       }
-       /* save index in queue, where we have to start flushing */
-       qmap->next_wqe_idx = wqe_idx;
-       return 0;
-}
-
-static int check_for_left_cqes(struct ehca_qp *my_qp, struct ehca_shca *shca)
-{
-       u64 h_ret;
-       void *send_wqe_p, *recv_wqe_p;
-       int ret;
-       unsigned long flags;
-       int qp_num = my_qp->ib_qp.qp_num;
-
-       /* this hcall is not supported on base QPs */
-       if (my_qp->ext_type != EQPT_SRQBASE) {
-               /* get send and receive wqe pointer */
-               h_ret = hipz_h_disable_and_get_wqe(shca->ipz_hca_handle,
-                               my_qp->ipz_qp_handle, &my_qp->pf,
-                               &send_wqe_p, &recv_wqe_p, 4);
-               if (h_ret != H_SUCCESS) {
-                       ehca_err(&shca->ib_device, "disable_and_get_wqe() "
-                                "failed ehca_qp=%p qp_num=%x h_ret=%lli",
-                                my_qp, qp_num, h_ret);
-                       return ehca2ib_return_code(h_ret);
-               }
-
-               /*
-                * acquire lock to ensure that nobody is polling the cq which
-                * could mean that the qmap->tail pointer is in an
-                * inconsistent state.
-                */
-               spin_lock_irqsave(&my_qp->send_cq->spinlock, flags);
-               ret = calc_left_cqes((u64)send_wqe_p, &my_qp->ipz_squeue,
-                               &my_qp->sq_map);
-               spin_unlock_irqrestore(&my_qp->send_cq->spinlock, flags);
-               if (ret)
-                       return ret;
-
-
-               spin_lock_irqsave(&my_qp->recv_cq->spinlock, flags);
-               ret = calc_left_cqes((u64)recv_wqe_p, &my_qp->ipz_rqueue,
-                               &my_qp->rq_map);
-               spin_unlock_irqrestore(&my_qp->recv_cq->spinlock, flags);
-               if (ret)
-                       return ret;
-       } else {
-               spin_lock_irqsave(&my_qp->send_cq->spinlock, flags);
-               my_qp->sq_map.left_to_poll = 0;
-               my_qp->sq_map.next_wqe_idx = next_index(my_qp->sq_map.tail,
-                                                       my_qp->sq_map.entries);
-               spin_unlock_irqrestore(&my_qp->send_cq->spinlock, flags);
-
-               spin_lock_irqsave(&my_qp->recv_cq->spinlock, flags);
-               my_qp->rq_map.left_to_poll = 0;
-               my_qp->rq_map.next_wqe_idx = next_index(my_qp->rq_map.tail,
-                                                       my_qp->rq_map.entries);
-               spin_unlock_irqrestore(&my_qp->recv_cq->spinlock, flags);
-       }
-
-       /* this assures flush cqes being generated only for pending wqes */
-       if ((my_qp->sq_map.left_to_poll == 0) &&
-                               (my_qp->rq_map.left_to_poll == 0)) {
-               spin_lock_irqsave(&my_qp->send_cq->spinlock, flags);
-               ehca_add_to_err_list(my_qp, 1);
-               spin_unlock_irqrestore(&my_qp->send_cq->spinlock, flags);
-
-               if (HAS_RQ(my_qp)) {
-                       spin_lock_irqsave(&my_qp->recv_cq->spinlock, flags);
-                       ehca_add_to_err_list(my_qp, 0);
-                       spin_unlock_irqrestore(&my_qp->recv_cq->spinlock,
-                                       flags);
-               }
-       }
-
-       return 0;
-}
-
-/*
- * internal_modify_qp with circumvention to handle aqp0 properly
- * smi_reset2init indicates if this is an internal reset-to-init-call for
- * smi. This flag must always be zero if called from ehca_modify_qp()!
- * This internal func was intorduced to avoid recursion of ehca_modify_qp()!
- */
-static int internal_modify_qp(struct ib_qp *ibqp,
-                             struct ib_qp_attr *attr,
-                             int attr_mask, int smi_reset2init)
-{
-       enum ib_qp_state qp_cur_state, qp_new_state;
-       int cnt, qp_attr_idx, ret = 0;
-       enum ib_qp_statetrans statetrans;
-       struct hcp_modify_qp_control_block *mqpcb;
-       struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp);
-       struct ehca_shca *shca =
-               container_of(ibqp->pd->device, struct ehca_shca, ib_device);
-       u64 update_mask;
-       u64 h_ret;
-       int bad_wqe_cnt = 0;
-       int is_user = 0;
-       int squeue_locked = 0;
-       unsigned long flags = 0;
-
-       /* do query_qp to obtain current attr values */
-       mqpcb = ehca_alloc_fw_ctrlblock(GFP_ATOMIC);
-       if (!mqpcb) {
-               ehca_err(ibqp->device, "Could not get zeroed page for mqpcb "
-                        "ehca_qp=%p qp_num=%x ", my_qp, ibqp->qp_num);
-               return -ENOMEM;
-       }
-
-       h_ret = hipz_h_query_qp(shca->ipz_hca_handle,
-                               my_qp->ipz_qp_handle,
-                               &my_qp->pf,
-                               mqpcb, my_qp->galpas.kernel);
-       if (h_ret != H_SUCCESS) {
-               ehca_err(ibqp->device, "hipz_h_query_qp() failed "
-                        "ehca_qp=%p qp_num=%x h_ret=%lli",
-                        my_qp, ibqp->qp_num, h_ret);
-               ret = ehca2ib_return_code(h_ret);
-               goto modify_qp_exit1;
-       }
-       if (ibqp->uobject)
-               is_user = 1;
-
-       qp_cur_state = ehca2ib_qp_state(mqpcb->qp_state);
-
-       if (qp_cur_state == -EINVAL) {  /* invalid qp state */
-               ret = -EINVAL;
-               ehca_err(ibqp->device, "Invalid current ehca_qp_state=%x "
-                        "ehca_qp=%p qp_num=%x",
-                        mqpcb->qp_state, my_qp, ibqp->qp_num);
-               goto modify_qp_exit1;
-       }
-       /*
-        * circumvention to set aqp0 initial state to init
-        * as expected by IB spec
-        */
-       if (smi_reset2init == 0 &&
-           ibqp->qp_type == IB_QPT_SMI &&
-           qp_cur_state == IB_QPS_RESET &&
-           (attr_mask & IB_QP_STATE) &&
-           attr->qp_state == IB_QPS_INIT) { /* RESET -> INIT */
-               struct ib_qp_attr smiqp_attr = {
-                       .qp_state = IB_QPS_INIT,
-                       .port_num = my_qp->init_attr.port_num,
-                       .pkey_index = 0,
-                       .qkey = 0
-               };
-               int smiqp_attr_mask = IB_QP_STATE | IB_QP_PORT |
-                       IB_QP_PKEY_INDEX | IB_QP_QKEY;
-               int smirc = internal_modify_qp(
-                       ibqp, &smiqp_attr, smiqp_attr_mask, 1);
-               if (smirc) {
-                       ehca_err(ibqp->device, "SMI RESET -> INIT failed. "
-                                "ehca_modify_qp() rc=%i", smirc);
-                       ret = H_PARAMETER;
-                       goto modify_qp_exit1;
-               }
-               qp_cur_state = IB_QPS_INIT;
-               ehca_dbg(ibqp->device, "SMI RESET -> INIT succeeded");
-       }
-       /* is transmitted current state  equal to "real" current state */
-       if ((attr_mask & IB_QP_CUR_STATE) &&
-           qp_cur_state != attr->cur_qp_state) {
-               ret = -EINVAL;
-               ehca_err(ibqp->device,
-                        "Invalid IB_QP_CUR_STATE attr->curr_qp_state=%x <>"
-                        " actual cur_qp_state=%x. ehca_qp=%p qp_num=%x",
-                        attr->cur_qp_state, qp_cur_state, my_qp, ibqp->qp_num);
-               goto modify_qp_exit1;
-       }
-
-       ehca_dbg(ibqp->device, "ehca_qp=%p qp_num=%x current qp_state=%x "
-                "new qp_state=%x attribute_mask=%x",
-                my_qp, ibqp->qp_num, qp_cur_state, attr->qp_state, attr_mask);
-
-       qp_new_state = attr_mask & IB_QP_STATE ? attr->qp_state : qp_cur_state;
-       if (!smi_reset2init &&
-           !ib_modify_qp_is_ok(qp_cur_state, qp_new_state, ibqp->qp_type,
-                               attr_mask, IB_LINK_LAYER_UNSPECIFIED)) {
-               ret = -EINVAL;
-               ehca_err(ibqp->device,
-                        "Invalid qp transition new_state=%x cur_state=%x "
-                        "ehca_qp=%p qp_num=%x attr_mask=%x", qp_new_state,
-                        qp_cur_state, my_qp, ibqp->qp_num, attr_mask);
-               goto modify_qp_exit1;
-       }
-
-       mqpcb->qp_state = ib2ehca_qp_state(qp_new_state);
-       if (mqpcb->qp_state)
-               update_mask = EHCA_BMASK_SET(MQPCB_MASK_QP_STATE, 1);
-       else {
-               ret = -EINVAL;
-               ehca_err(ibqp->device, "Invalid new qp state=%x "
-                        "ehca_qp=%p qp_num=%x",
-                        qp_new_state, my_qp, ibqp->qp_num);
-               goto modify_qp_exit1;
-       }
-
-       /* retrieve state transition struct to get req and opt attrs */
-       statetrans = get_modqp_statetrans(qp_cur_state, qp_new_state);
-       if (statetrans < 0) {
-               ret = -EINVAL;
-               ehca_err(ibqp->device, "<INVALID STATE CHANGE> qp_cur_state=%x "
-                        "new_qp_state=%x State_xsition=%x ehca_qp=%p "
-                        "qp_num=%x", qp_cur_state, qp_new_state,
-                        statetrans, my_qp, ibqp->qp_num);
-               goto modify_qp_exit1;
-       }
-
-       qp_attr_idx = ib2ehcaqptype(ibqp->qp_type);
-
-       if (qp_attr_idx < 0) {
-               ret = qp_attr_idx;
-               ehca_err(ibqp->device,
-                        "Invalid QP type=%x ehca_qp=%p qp_num=%x",
-                        ibqp->qp_type, my_qp, ibqp->qp_num);
-               goto modify_qp_exit1;
-       }
-
-       ehca_dbg(ibqp->device,
-                "ehca_qp=%p qp_num=%x <VALID STATE CHANGE> qp_state_xsit=%x",
-                my_qp, ibqp->qp_num, statetrans);
-
-       /* eHCA2 rev2 and higher require the SEND_GRH_FLAG to be set
-        * in non-LL UD QPs.
-        */
-       if ((my_qp->qp_type == IB_QPT_UD) &&
-           (my_qp->ext_type != EQPT_LLQP) &&
-           (statetrans == IB_QPST_INIT2RTR) &&
-           (shca->hw_level >= 0x22)) {
-               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SEND_GRH_FLAG, 1);
-               mqpcb->send_grh_flag = 1;
-       }
-
-       /* sqe -> rts: set purge bit of bad wqe before actual trans */
-       if ((my_qp->qp_type == IB_QPT_UD ||
-            my_qp->qp_type == IB_QPT_GSI ||
-            my_qp->qp_type == IB_QPT_SMI) &&
-           statetrans == IB_QPST_SQE2RTS) {
-               /* mark next free wqe if kernel */
-               if (!ibqp->uobject) {
-                       struct ehca_wqe *wqe;
-                       /* lock send queue */
-                       spin_lock_irqsave(&my_qp->spinlock_s, flags);
-                       squeue_locked = 1;
-                       /* mark next free wqe */
-                       wqe = (struct ehca_wqe *)
-                               ipz_qeit_get(&my_qp->ipz_squeue);
-                       wqe->optype = wqe->wqef = 0xff;
-                       ehca_dbg(ibqp->device, "qp_num=%x next_free_wqe=%p",
-                                ibqp->qp_num, wqe);
-               }
-               ret = prepare_sqe_rts(my_qp, shca, &bad_wqe_cnt);
-               if (ret) {
-                       ehca_err(ibqp->device, "prepare_sqe_rts() failed "
-                                "ehca_qp=%p qp_num=%x ret=%i",
-                                my_qp, ibqp->qp_num, ret);
-                       goto modify_qp_exit2;
-               }
-       }
-
-       /*
-        * enable RDMA_Atomic_Control if reset->init und reliable con
-        * this is necessary since gen2 does not provide that flag,
-        * but pHyp requires it
-        */
-       if (statetrans == IB_QPST_RESET2INIT &&
-           (ibqp->qp_type == IB_QPT_RC || ibqp->qp_type == IB_QPT_UC)) {
-               mqpcb->rdma_atomic_ctrl = 3;
-               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_RDMA_ATOMIC_CTRL, 1);
-       }
-       /* circ. pHyp requires #RDMA/Atomic Resp Res for UC INIT -> RTR */
-       if (statetrans == IB_QPST_INIT2RTR &&
-           (ibqp->qp_type == IB_QPT_UC) &&
-           !(attr_mask & IB_QP_MAX_DEST_RD_ATOMIC)) {
-               mqpcb->rdma_nr_atomic_resp_res = 1; /* default to 1 */
-               update_mask |=
-                       EHCA_BMASK_SET(MQPCB_MASK_RDMA_NR_ATOMIC_RESP_RES, 1);
-       }
-
-       if (attr_mask & IB_QP_PKEY_INDEX) {
-               if (attr->pkey_index >= 16) {
-                       ret = -EINVAL;
-                       ehca_err(ibqp->device, "Invalid pkey_index=%x. "
-                                "ehca_qp=%p qp_num=%x max_pkey_index=f",
-                                attr->pkey_index, my_qp, ibqp->qp_num);
-                       goto modify_qp_exit2;
-               }
-               mqpcb->prim_p_key_idx = attr->pkey_index;
-               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_PRIM_P_KEY_IDX, 1);
-       }
-       if (attr_mask & IB_QP_PORT) {
-               struct ehca_sport *sport;
-               struct ehca_qp *aqp1;
-               if (attr->port_num < 1 || attr->port_num > shca->num_ports) {
-                       ret = -EINVAL;
-                       ehca_err(ibqp->device, "Invalid port=%x. "
-                                "ehca_qp=%p qp_num=%x num_ports=%x",
-                                attr->port_num, my_qp, ibqp->qp_num,
-                                shca->num_ports);
-                       goto modify_qp_exit2;
-               }
-               sport = &shca->sport[attr->port_num - 1];
-               if (!sport->ibqp_sqp[IB_QPT_GSI]) {
-                       /* should not occur */
-                       ret = -EFAULT;
-                       ehca_err(ibqp->device, "AQP1 was not created for "
-                                "port=%x", attr->port_num);
-                       goto modify_qp_exit2;
-               }
-               aqp1 = container_of(sport->ibqp_sqp[IB_QPT_GSI],
-                                   struct ehca_qp, ib_qp);
-               if (ibqp->qp_type != IB_QPT_GSI &&
-                   ibqp->qp_type != IB_QPT_SMI &&
-                   aqp1->mod_qp_parm) {
-                       /*
-                        * firmware will reject this modify_qp() because
-                        * port is not activated/initialized fully
-                        */
-                       ret = -EFAULT;
-                       ehca_warn(ibqp->device, "Couldn't modify qp port=%x: "
-                                 "either port is being activated (try again) "
-                                 "or cabling issue", attr->port_num);
-                       goto modify_qp_exit2;
-               }
-               mqpcb->prim_phys_port = attr->port_num;
-               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_PRIM_PHYS_PORT, 1);
-       }
-       if (attr_mask & IB_QP_QKEY) {
-               mqpcb->qkey = attr->qkey;
-               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_QKEY, 1);
-       }
-       if (attr_mask & IB_QP_AV) {
-               mqpcb->dlid = attr->ah_attr.dlid;
-               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_DLID, 1);
-               mqpcb->source_path_bits = attr->ah_attr.src_path_bits;
-               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SOURCE_PATH_BITS, 1);
-               mqpcb->service_level = attr->ah_attr.sl;
-               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SERVICE_LEVEL, 1);
-
-               if (ehca_calc_ipd(shca, mqpcb->prim_phys_port,
-                                 attr->ah_attr.static_rate,
-                                 &mqpcb->max_static_rate)) {
-                       ret = -EINVAL;
-                       goto modify_qp_exit2;
-               }
-               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_MAX_STATIC_RATE, 1);
-
-               /*
-                * Always supply the GRH flag, even if it's zero, to give the
-                * hypervisor a clear "yes" or "no" instead of a "perhaps"
-                */
-               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SEND_GRH_FLAG, 1);
-
-               /*
-                * only if GRH is TRUE we might consider SOURCE_GID_IDX
-                * and DEST_GID otherwise phype will return H_ATTR_PARM!!!
-                */
-               if (attr->ah_attr.ah_flags == IB_AH_GRH) {
-                       mqpcb->send_grh_flag = 1;
-
-                       mqpcb->source_gid_idx = attr->ah_attr.grh.sgid_index;
-                       update_mask |=
-                               EHCA_BMASK_SET(MQPCB_MASK_SOURCE_GID_IDX, 1);
-
-                       for (cnt = 0; cnt < 16; cnt++)
-                               mqpcb->dest_gid.byte[cnt] =
-                                       attr->ah_attr.grh.dgid.raw[cnt];
-
-                       update_mask |= EHCA_BMASK_SET(MQPCB_MASK_DEST_GID, 1);
-                       mqpcb->flow_label = attr->ah_attr.grh.flow_label;
-                       update_mask |= EHCA_BMASK_SET(MQPCB_MASK_FLOW_LABEL, 1);
-                       mqpcb->hop_limit = attr->ah_attr.grh.hop_limit;
-                       update_mask |= EHCA_BMASK_SET(MQPCB_MASK_HOP_LIMIT, 1);
-                       mqpcb->traffic_class = attr->ah_attr.grh.traffic_class;
-                       update_mask |=
-                               EHCA_BMASK_SET(MQPCB_MASK_TRAFFIC_CLASS, 1);
-               }
-       }
-
-       if (attr_mask & IB_QP_PATH_MTU) {
-               /* store ld(MTU) */
-               my_qp->mtu_shift = attr->path_mtu + 7;
-               mqpcb->path_mtu = attr->path_mtu;
-               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_PATH_MTU, 1);
-       }
-       if (attr_mask & IB_QP_TIMEOUT) {
-               mqpcb->timeout = attr->timeout;
-               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_TIMEOUT, 1);
-       }
-       if (attr_mask & IB_QP_RETRY_CNT) {
-               mqpcb->retry_count = attr->retry_cnt;
-               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_RETRY_COUNT, 1);
-       }
-       if (attr_mask & IB_QP_RNR_RETRY) {
-               mqpcb->rnr_retry_count = attr->rnr_retry;
-               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_RNR_RETRY_COUNT, 1);
-       }
-       if (attr_mask & IB_QP_RQ_PSN) {
-               mqpcb->receive_psn = attr->rq_psn;
-               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_RECEIVE_PSN, 1);
-       }
-       if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) {
-               mqpcb->rdma_nr_atomic_resp_res = attr->max_dest_rd_atomic < 3 ?
-                       attr->max_dest_rd_atomic : 2;
-               update_mask |=
-                       EHCA_BMASK_SET(MQPCB_MASK_RDMA_NR_ATOMIC_RESP_RES, 1);
-       }
-       if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC) {
-               mqpcb->rdma_atomic_outst_dest_qp = attr->max_rd_atomic < 3 ?
-                       attr->max_rd_atomic : 2;
-               update_mask |=
-                       EHCA_BMASK_SET
-                       (MQPCB_MASK_RDMA_ATOMIC_OUTST_DEST_QP, 1);
-       }
-       if (attr_mask & IB_QP_ALT_PATH) {
-               if (attr->alt_port_num < 1
-                   || attr->alt_port_num > shca->num_ports) {
-                       ret = -EINVAL;
-                       ehca_err(ibqp->device, "Invalid alt_port=%x. "
-                                "ehca_qp=%p qp_num=%x num_ports=%x",
-                                attr->alt_port_num, my_qp, ibqp->qp_num,
-                                shca->num_ports);
-                       goto modify_qp_exit2;
-               }
-               mqpcb->alt_phys_port = attr->alt_port_num;
-
-               if (attr->alt_pkey_index >= 16) {
-                       ret = -EINVAL;
-                       ehca_err(ibqp->device, "Invalid alt_pkey_index=%x. "
-                                "ehca_qp=%p qp_num=%x max_pkey_index=f",
-                                attr->pkey_index, my_qp, ibqp->qp_num);
-                       goto modify_qp_exit2;
-               }
-               mqpcb->alt_p_key_idx = attr->alt_pkey_index;
-
-               mqpcb->timeout_al = attr->alt_timeout;
-               mqpcb->dlid_al = attr->alt_ah_attr.dlid;
-               mqpcb->source_path_bits_al = attr->alt_ah_attr.src_path_bits;
-               mqpcb->service_level_al = attr->alt_ah_attr.sl;
-
-               if (ehca_calc_ipd(shca, mqpcb->alt_phys_port,
-                                 attr->alt_ah_attr.static_rate,
-                                 &mqpcb->max_static_rate_al)) {
-                       ret = -EINVAL;
-                       goto modify_qp_exit2;
-               }
-
-               /* OpenIB doesn't support alternate retry counts - copy them */
-               mqpcb->retry_count_al = mqpcb->retry_count;
-               mqpcb->rnr_retry_count_al = mqpcb->rnr_retry_count;
-
-               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_ALT_PHYS_PORT, 1)
-                       | EHCA_BMASK_SET(MQPCB_MASK_ALT_P_KEY_IDX, 1)
-                       | EHCA_BMASK_SET(MQPCB_MASK_TIMEOUT_AL, 1)
-                       | EHCA_BMASK_SET(MQPCB_MASK_DLID_AL, 1)
-                       | EHCA_BMASK_SET(MQPCB_MASK_SOURCE_PATH_BITS_AL, 1)
-                       | EHCA_BMASK_SET(MQPCB_MASK_SERVICE_LEVEL_AL, 1)
-                       | EHCA_BMASK_SET(MQPCB_MASK_MAX_STATIC_RATE_AL, 1)
-                       | EHCA_BMASK_SET(MQPCB_MASK_RETRY_COUNT_AL, 1)
-                       | EHCA_BMASK_SET(MQPCB_MASK_RNR_RETRY_COUNT_AL, 1);
-
-               /*
-                * Always supply the GRH flag, even if it's zero, to give the
-                * hypervisor a clear "yes" or "no" instead of a "perhaps"
-                */
-               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SEND_GRH_FLAG_AL, 1);
-
-               /*
-                * only if GRH is TRUE we might consider SOURCE_GID_IDX
-                * and DEST_GID otherwise phype will return H_ATTR_PARM!!!
-                */
-               if (attr->alt_ah_attr.ah_flags == IB_AH_GRH) {
-                       mqpcb->send_grh_flag_al = 1;
-
-                       for (cnt = 0; cnt < 16; cnt++)
-                               mqpcb->dest_gid_al.byte[cnt] =
-                                       attr->alt_ah_attr.grh.dgid.raw[cnt];
-                       mqpcb->source_gid_idx_al =
-                               attr->alt_ah_attr.grh.sgid_index;
-                       mqpcb->flow_label_al = attr->alt_ah_attr.grh.flow_label;
-                       mqpcb->hop_limit_al = attr->alt_ah_attr.grh.hop_limit;
-                       mqpcb->traffic_class_al =
-                               attr->alt_ah_attr.grh.traffic_class;
-
-                       update_mask |=
-                               EHCA_BMASK_SET(MQPCB_MASK_SOURCE_GID_IDX_AL, 1)
-                               | EHCA_BMASK_SET(MQPCB_MASK_DEST_GID_AL, 1)
-                               | EHCA_BMASK_SET(MQPCB_MASK_FLOW_LABEL_AL, 1)
-                               | EHCA_BMASK_SET(MQPCB_MASK_HOP_LIMIT_AL, 1) |
-                               EHCA_BMASK_SET(MQPCB_MASK_TRAFFIC_CLASS_AL, 1);
-               }
-       }
-
-       if (attr_mask & IB_QP_MIN_RNR_TIMER) {
-               mqpcb->min_rnr_nak_timer_field = attr->min_rnr_timer;
-               update_mask |=
-                       EHCA_BMASK_SET(MQPCB_MASK_MIN_RNR_NAK_TIMER_FIELD, 1);
-       }
-
-       if (attr_mask & IB_QP_SQ_PSN) {
-               mqpcb->send_psn = attr->sq_psn;
-               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SEND_PSN, 1);
-       }
-
-       if (attr_mask & IB_QP_DEST_QPN) {
-               mqpcb->dest_qp_nr = attr->dest_qp_num;
-               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_DEST_QP_NR, 1);
-       }
-
-       if (attr_mask & IB_QP_PATH_MIG_STATE) {
-               if (attr->path_mig_state != IB_MIG_REARM
-                   && attr->path_mig_state != IB_MIG_MIGRATED) {
-                       ret = -EINVAL;
-                       ehca_err(ibqp->device, "Invalid mig_state=%x",
-                                attr->path_mig_state);
-                       goto modify_qp_exit2;
-               }
-               mqpcb->path_migration_state = attr->path_mig_state + 1;
-               if (attr->path_mig_state == IB_MIG_REARM)
-                       my_qp->mig_armed = 1;
-               update_mask |=
-                       EHCA_BMASK_SET(MQPCB_MASK_PATH_MIGRATION_STATE, 1);
-       }
-
-       if (attr_mask & IB_QP_CAP) {
-               mqpcb->max_nr_outst_send_wr = attr->cap.max_send_wr+1;
-               update_mask |=
-                       EHCA_BMASK_SET(MQPCB_MASK_MAX_NR_OUTST_SEND_WR, 1);
-               mqpcb->max_nr_outst_recv_wr = attr->cap.max_recv_wr+1;
-               update_mask |=
-                       EHCA_BMASK_SET(MQPCB_MASK_MAX_NR_OUTST_RECV_WR, 1);
-               /* no support for max_send/recv_sge yet */
-       }
-
-       if (ehca_debug_level >= 2)
-               ehca_dmp(mqpcb, 4*70, "qp_num=%x", ibqp->qp_num);
-
-       h_ret = hipz_h_modify_qp(shca->ipz_hca_handle,
-                                my_qp->ipz_qp_handle,
-                                &my_qp->pf,
-                                update_mask,
-                                mqpcb, my_qp->galpas.kernel);
-
-       if (h_ret != H_SUCCESS) {
-               ret = ehca2ib_return_code(h_ret);
-               ehca_err(ibqp->device, "hipz_h_modify_qp() failed h_ret=%lli "
-                        "ehca_qp=%p qp_num=%x", h_ret, my_qp, ibqp->qp_num);
-               goto modify_qp_exit2;
-       }
-
-       if ((my_qp->qp_type == IB_QPT_UD ||
-            my_qp->qp_type == IB_QPT_GSI ||
-            my_qp->qp_type == IB_QPT_SMI) &&
-           statetrans == IB_QPST_SQE2RTS) {
-               /* doorbell to reprocessing wqes */
-               iosync(); /* serialize GAL register access */
-               hipz_update_sqa(my_qp, bad_wqe_cnt-1);
-               ehca_gen_dbg("doorbell for %x wqes", bad_wqe_cnt);
-       }
-
-       if (statetrans == IB_QPST_RESET2INIT ||
-           statetrans == IB_QPST_INIT2INIT) {
-               mqpcb->qp_enable = 1;
-               mqpcb->qp_state = EHCA_QPS_INIT;
-               update_mask = 0;
-               update_mask = EHCA_BMASK_SET(MQPCB_MASK_QP_ENABLE, 1);
-
-               h_ret = hipz_h_modify_qp(shca->ipz_hca_handle,
-                                        my_qp->ipz_qp_handle,
-                                        &my_qp->pf,
-                                        update_mask,
-                                        mqpcb,
-                                        my_qp->galpas.kernel);
-
-               if (h_ret != H_SUCCESS) {
-                       ret = ehca2ib_return_code(h_ret);
-                       ehca_err(ibqp->device, "ENABLE in context of "
-                                "RESET_2_INIT failed! Maybe you didn't get "
-                                "a LID h_ret=%lli ehca_qp=%p qp_num=%x",
-                                h_ret, my_qp, ibqp->qp_num);
-                       goto modify_qp_exit2;
-               }
-       }
-       if ((qp_new_state == IB_QPS_ERR) && (qp_cur_state != IB_QPS_ERR)
-           && !is_user) {
-               ret = check_for_left_cqes(my_qp, shca);
-               if (ret)
-                       goto modify_qp_exit2;
-       }
-
-       if (statetrans == IB_QPST_ANY2RESET) {
-               ipz_qeit_reset(&my_qp->ipz_rqueue);
-               ipz_qeit_reset(&my_qp->ipz_squeue);
-
-               if (qp_cur_state == IB_QPS_ERR && !is_user) {
-                       del_from_err_list(my_qp->send_cq, &my_qp->sq_err_node);
-
-                       if (HAS_RQ(my_qp))
-                               del_from_err_list(my_qp->recv_cq,
-                                                 &my_qp->rq_err_node);
-               }
-               if (!is_user)
-                       reset_queue_map(&my_qp->sq_map);
-
-               if (HAS_RQ(my_qp) && !is_user)
-                       reset_queue_map(&my_qp->rq_map);
-       }
-
-       if (attr_mask & IB_QP_QKEY)
-               my_qp->qkey = attr->qkey;
-
-modify_qp_exit2:
-       if (squeue_locked) { /* this means: sqe -> rts */
-               spin_unlock_irqrestore(&my_qp->spinlock_s, flags);
-               my_qp->sqerr_purgeflag = 1;
-       }
-
-modify_qp_exit1:
-       ehca_free_fw_ctrlblock(mqpcb);
-
-       return ret;
-}
-
-int ehca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
-                  struct ib_udata *udata)
-{
-       int ret = 0;
-
-       struct ehca_shca *shca = container_of(ibqp->device, struct ehca_shca,
-                                             ib_device);
-       struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp);
-
-       /* The if-block below caches qp_attr to be modified for GSI and SMI
-        * qps during the initialization by ib_mad. When the respective port
-        * is activated, ie we got an event PORT_ACTIVE, we'll replay the
-        * cached modify calls sequence, see ehca_recover_sqs() below.
-        * Why that is required:
-        * 1) If one port is connected, older code requires that port one
-        *    to be connected and module option nr_ports=1 to be given by
-        *    user, which is very inconvenient for end user.
-        * 2) Firmware accepts modify_qp() only if respective port has become
-        *    active. Older code had a wait loop of 30sec create_qp()/
-        *    define_aqp1(), which is not appropriate in practice. This
-        *    code now removes that wait loop, see define_aqp1(), and always
-        *    reports all ports to ib_mad resp. users. Only activated ports
-        *    will then usable for the users.
-        */
-       if (ibqp->qp_type == IB_QPT_GSI || ibqp->qp_type == IB_QPT_SMI) {
-               int port = my_qp->init_attr.port_num;
-               struct ehca_sport *sport = &shca->sport[port - 1];
-               unsigned long flags;
-               spin_lock_irqsave(&sport->mod_sqp_lock, flags);
-               /* cache qp_attr only during init */
-               if (my_qp->mod_qp_parm) {
-                       struct ehca_mod_qp_parm *p;
-                       if (my_qp->mod_qp_parm_idx >= EHCA_MOD_QP_PARM_MAX) {
-                               ehca_err(&shca->ib_device,
-                                        "mod_qp_parm overflow state=%x port=%x"
-                                        " type=%x", attr->qp_state,
-                                        my_qp->init_attr.port_num,
-                                        ibqp->qp_type);
-                               spin_unlock_irqrestore(&sport->mod_sqp_lock,
-                                                      flags);
-                               return -EINVAL;
-                       }
-                       p = &my_qp->mod_qp_parm[my_qp->mod_qp_parm_idx];
-                       p->mask = attr_mask;
-                       p->attr = *attr;
-                       my_qp->mod_qp_parm_idx++;
-                       ehca_dbg(&shca->ib_device,
-                                "Saved qp_attr for state=%x port=%x type=%x",
-                                attr->qp_state, my_qp->init_attr.port_num,
-                                ibqp->qp_type);
-                       spin_unlock_irqrestore(&sport->mod_sqp_lock, flags);
-                       goto out;
-               }
-               spin_unlock_irqrestore(&sport->mod_sqp_lock, flags);
-       }
-
-       ret = internal_modify_qp(ibqp, attr, attr_mask, 0);
-
-out:
-       if ((ret == 0) && (attr_mask & IB_QP_STATE))
-               my_qp->state = attr->qp_state;
-
-       return ret;
-}
-
-void ehca_recover_sqp(struct ib_qp *sqp)
-{
-       struct ehca_qp *my_sqp = container_of(sqp, struct ehca_qp, ib_qp);
-       int port = my_sqp->init_attr.port_num;
-       struct ib_qp_attr attr;
-       struct ehca_mod_qp_parm *qp_parm;
-       int i, qp_parm_idx, ret;
-       unsigned long flags, wr_cnt;
-
-       if (!my_sqp->mod_qp_parm)
-               return;
-       ehca_dbg(sqp->device, "SQP port=%x qp_num=%x", port, sqp->qp_num);
-
-       qp_parm = my_sqp->mod_qp_parm;
-       qp_parm_idx = my_sqp->mod_qp_parm_idx;
-       for (i = 0; i < qp_parm_idx; i++) {
-               attr = qp_parm[i].attr;
-               ret = internal_modify_qp(sqp, &attr, qp_parm[i].mask, 0);
-               if (ret) {
-                       ehca_err(sqp->device, "Could not modify SQP port=%x "
-                                "qp_num=%x ret=%x", port, sqp->qp_num, ret);
-                       goto free_qp_parm;
-               }
-               ehca_dbg(sqp->device, "SQP port=%x qp_num=%x in state=%x",
-                        port, sqp->qp_num, attr.qp_state);
-       }
-
-       /* re-trigger posted recv wrs */
-       wr_cnt =  my_sqp->ipz_rqueue.current_q_offset /
-               my_sqp->ipz_rqueue.qe_size;
-       if (wr_cnt) {
-               spin_lock_irqsave(&my_sqp->spinlock_r, flags);
-               hipz_update_rqa(my_sqp, wr_cnt);
-               spin_unlock_irqrestore(&my_sqp->spinlock_r, flags);
-               ehca_dbg(sqp->device, "doorbell port=%x qp_num=%x wr_cnt=%lx",
-                        port, sqp->qp_num, wr_cnt);
-       }
-
-free_qp_parm:
-       kfree(qp_parm);
-       /* this prevents subsequent calls to modify_qp() to cache qp_attr */
-       my_sqp->mod_qp_parm = NULL;
-}
-
-int ehca_query_qp(struct ib_qp *qp,
-                 struct ib_qp_attr *qp_attr,
-                 int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr)
-{
-       struct ehca_qp *my_qp = container_of(qp, struct ehca_qp, ib_qp);
-       struct ehca_shca *shca = container_of(qp->device, struct ehca_shca,
-                                             ib_device);
-       struct ipz_adapter_handle adapter_handle = shca->ipz_hca_handle;
-       struct hcp_modify_qp_control_block *qpcb;
-       int cnt, ret = 0;
-       u64 h_ret;
-
-       if (qp_attr_mask & QP_ATTR_QUERY_NOT_SUPPORTED) {
-               ehca_err(qp->device, "Invalid attribute mask "
-                        "ehca_qp=%p qp_num=%x qp_attr_mask=%x ",
-                        my_qp, qp->qp_num, qp_attr_mask);
-               return -EINVAL;
-       }
-
-       qpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
-       if (!qpcb) {
-               ehca_err(qp->device, "Out of memory for qpcb "
-                        "ehca_qp=%p qp_num=%x", my_qp, qp->qp_num);
-               return -ENOMEM;
-       }
-
-       h_ret = hipz_h_query_qp(adapter_handle,
-                               my_qp->ipz_qp_handle,
-                               &my_qp->pf,
-                               qpcb, my_qp->galpas.kernel);
-
-       if (h_ret != H_SUCCESS) {
-               ret = ehca2ib_return_code(h_ret);
-               ehca_err(qp->device, "hipz_h_query_qp() failed "
-                        "ehca_qp=%p qp_num=%x h_ret=%lli",
-                        my_qp, qp->qp_num, h_ret);
-               goto query_qp_exit1;
-       }
-
-       qp_attr->cur_qp_state = ehca2ib_qp_state(qpcb->qp_state);
-       qp_attr->qp_state = qp_attr->cur_qp_state;
-
-       if (qp_attr->cur_qp_state == -EINVAL) {
-               ret = -EINVAL;
-               ehca_err(qp->device, "Got invalid ehca_qp_state=%x "
-                        "ehca_qp=%p qp_num=%x",
-                        qpcb->qp_state, my_qp, qp->qp_num);
-               goto query_qp_exit1;
-       }
-
-       if (qp_attr->qp_state == IB_QPS_SQD)
-               qp_attr->sq_draining = 1;
-
-       qp_attr->qkey = qpcb->qkey;
-       qp_attr->path_mtu = qpcb->path_mtu;
-       qp_attr->path_mig_state = qpcb->path_migration_state - 1;
-       qp_attr->rq_psn = qpcb->receive_psn;
-       qp_attr->sq_psn = qpcb->send_psn;
-       qp_attr->min_rnr_timer = qpcb->min_rnr_nak_timer_field;
-       qp_attr->cap.max_send_wr = qpcb->max_nr_outst_send_wr-1;
-       qp_attr->cap.max_recv_wr = qpcb->max_nr_outst_recv_wr-1;
-       /* UD_AV CIRCUMVENTION */
-       if (my_qp->qp_type == IB_QPT_UD) {
-               qp_attr->cap.max_send_sge =
-                       qpcb->actual_nr_sges_in_sq_wqe - 2;
-               qp_attr->cap.max_recv_sge =
-                       qpcb->actual_nr_sges_in_rq_wqe - 2;
-       } else {
-               qp_attr->cap.max_send_sge =
-                       qpcb->actual_nr_sges_in_sq_wqe;
-               qp_attr->cap.max_recv_sge =
-                       qpcb->actual_nr_sges_in_rq_wqe;
-       }
-
-       qp_attr->cap.max_inline_data = my_qp->sq_max_inline_data_size;
-       qp_attr->dest_qp_num = qpcb->dest_qp_nr;
-
-       qp_attr->pkey_index = qpcb->prim_p_key_idx;
-       qp_attr->port_num = qpcb->prim_phys_port;
-       qp_attr->timeout = qpcb->timeout;
-       qp_attr->retry_cnt = qpcb->retry_count;
-       qp_attr->rnr_retry = qpcb->rnr_retry_count;
-
-       qp_attr->alt_pkey_index = qpcb->alt_p_key_idx;
-       qp_attr->alt_port_num = qpcb->alt_phys_port;
-       qp_attr->alt_timeout = qpcb->timeout_al;
-
-       qp_attr->max_dest_rd_atomic = qpcb->rdma_nr_atomic_resp_res;
-       qp_attr->max_rd_atomic = qpcb->rdma_atomic_outst_dest_qp;
-
-       /* primary av */
-       qp_attr->ah_attr.sl = qpcb->service_level;
-
-       if (qpcb->send_grh_flag) {
-               qp_attr->ah_attr.ah_flags = IB_AH_GRH;
-       }
-
-       qp_attr->ah_attr.static_rate = qpcb->max_static_rate;
-       qp_attr->ah_attr.dlid = qpcb->dlid;
-       qp_attr->ah_attr.src_path_bits = qpcb->source_path_bits;
-       qp_attr->ah_attr.port_num = qp_attr->port_num;
-
-       /* primary GRH */
-       qp_attr->ah_attr.grh.traffic_class = qpcb->traffic_class;
-       qp_attr->ah_attr.grh.hop_limit = qpcb->hop_limit;
-       qp_attr->ah_attr.grh.sgid_index = qpcb->source_gid_idx;
-       qp_attr->ah_attr.grh.flow_label = qpcb->flow_label;
-
-       for (cnt = 0; cnt < 16; cnt++)
-               qp_attr->ah_attr.grh.dgid.raw[cnt] =
-                       qpcb->dest_gid.byte[cnt];
-
-       /* alternate AV */
-       qp_attr->alt_ah_attr.sl = qpcb->service_level_al;
-       if (qpcb->send_grh_flag_al) {
-               qp_attr->alt_ah_attr.ah_flags = IB_AH_GRH;
-       }
-
-       qp_attr->alt_ah_attr.static_rate = qpcb->max_static_rate_al;
-       qp_attr->alt_ah_attr.dlid = qpcb->dlid_al;
-       qp_attr->alt_ah_attr.src_path_bits = qpcb->source_path_bits_al;
-
-       /* alternate GRH */
-       qp_attr->alt_ah_attr.grh.traffic_class = qpcb->traffic_class_al;
-       qp_attr->alt_ah_attr.grh.hop_limit = qpcb->hop_limit_al;
-       qp_attr->alt_ah_attr.grh.sgid_index = qpcb->source_gid_idx_al;
-       qp_attr->alt_ah_attr.grh.flow_label = qpcb->flow_label_al;
-
-       for (cnt = 0; cnt < 16; cnt++)
-               qp_attr->alt_ah_attr.grh.dgid.raw[cnt] =
-                       qpcb->dest_gid_al.byte[cnt];
-
-       /* return init attributes given in ehca_create_qp */
-       if (qp_init_attr)
-               *qp_init_attr = my_qp->init_attr;
-
-       if (ehca_debug_level >= 2)
-               ehca_dmp(qpcb, 4*70, "qp_num=%x", qp->qp_num);
-
-query_qp_exit1:
-       ehca_free_fw_ctrlblock(qpcb);
-
-       return ret;
-}
-
-int ehca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
-                   enum ib_srq_attr_mask attr_mask, struct ib_udata *udata)
-{
-       struct ehca_qp *my_qp =
-               container_of(ibsrq, struct ehca_qp, ib_srq);
-       struct ehca_shca *shca =
-               container_of(ibsrq->pd->device, struct ehca_shca, ib_device);
-       struct hcp_modify_qp_control_block *mqpcb;
-       u64 update_mask;
-       u64 h_ret;
-       int ret = 0;
-
-       mqpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
-       if (!mqpcb) {
-               ehca_err(ibsrq->device, "Could not get zeroed page for mqpcb "
-                        "ehca_qp=%p qp_num=%x ", my_qp, my_qp->real_qp_num);
-               return -ENOMEM;
-       }
-
-       update_mask = 0;
-       if (attr_mask & IB_SRQ_LIMIT) {
-               attr_mask &= ~IB_SRQ_LIMIT;
-               update_mask |=
-                       EHCA_BMASK_SET(MQPCB_MASK_CURR_SRQ_LIMIT, 1)
-                       | EHCA_BMASK_SET(MQPCB_MASK_QP_AFF_ASYN_EV_LOG_REG, 1);
-               mqpcb->curr_srq_limit = attr->srq_limit;
-               mqpcb->qp_aff_asyn_ev_log_reg =
-                       EHCA_BMASK_SET(QPX_AAELOG_RESET_SRQ_LIMIT, 1);
-       }
-
-       /* by now, all bits in attr_mask should have been cleared */
-       if (attr_mask) {
-               ehca_err(ibsrq->device, "invalid attribute mask bits set  "
-                        "attr_mask=%x", attr_mask);
-               ret = -EINVAL;
-               goto modify_srq_exit0;
-       }
-
-       if (ehca_debug_level >= 2)
-               ehca_dmp(mqpcb, 4*70, "qp_num=%x", my_qp->real_qp_num);
-
-       h_ret = hipz_h_modify_qp(shca->ipz_hca_handle, my_qp->ipz_qp_handle,
-                                NULL, update_mask, mqpcb,
-                                my_qp->galpas.kernel);
-
-       if (h_ret != H_SUCCESS) {
-               ret = ehca2ib_return_code(h_ret);
-               ehca_err(ibsrq->device, "hipz_h_modify_qp() failed h_ret=%lli "
-                        "ehca_qp=%p qp_num=%x",
-                        h_ret, my_qp, my_qp->real_qp_num);
-       }
-
-modify_srq_exit0:
-       ehca_free_fw_ctrlblock(mqpcb);
-
-       return ret;
-}
-
-int ehca_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr)
-{
-       struct ehca_qp *my_qp = container_of(srq, struct ehca_qp, ib_srq);
-       struct ehca_shca *shca = container_of(srq->device, struct ehca_shca,
-                                             ib_device);
-       struct ipz_adapter_handle adapter_handle = shca->ipz_hca_handle;
-       struct hcp_modify_qp_control_block *qpcb;
-       int ret = 0;
-       u64 h_ret;
-
-       qpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
-       if (!qpcb) {
-               ehca_err(srq->device, "Out of memory for qpcb "
-                        "ehca_qp=%p qp_num=%x", my_qp, my_qp->real_qp_num);
-               return -ENOMEM;
-       }
-
-       h_ret = hipz_h_query_qp(adapter_handle, my_qp->ipz_qp_handle,
-                               NULL, qpcb, my_qp->galpas.kernel);
-
-       if (h_ret != H_SUCCESS) {
-               ret = ehca2ib_return_code(h_ret);
-               ehca_err(srq->device, "hipz_h_query_qp() failed "
-                        "ehca_qp=%p qp_num=%x h_ret=%lli",
-                        my_qp, my_qp->real_qp_num, h_ret);
-               goto query_srq_exit1;
-       }
-
-       srq_attr->max_wr = qpcb->max_nr_outst_recv_wr - 1;
-       srq_attr->max_sge = 3;
-       srq_attr->srq_limit = qpcb->curr_srq_limit;
-
-       if (ehca_debug_level >= 2)
-               ehca_dmp(qpcb, 4*70, "qp_num=%x", my_qp->real_qp_num);
-
-query_srq_exit1:
-       ehca_free_fw_ctrlblock(qpcb);
-
-       return ret;
-}
-
-static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
-                              struct ib_uobject *uobject)
-{
-       struct ehca_shca *shca = container_of(dev, struct ehca_shca, ib_device);
-       struct ehca_pd *my_pd = container_of(my_qp->ib_qp.pd, struct ehca_pd,
-                                            ib_pd);
-       struct ehca_sport *sport = &shca->sport[my_qp->init_attr.port_num - 1];
-       u32 qp_num = my_qp->real_qp_num;
-       int ret;
-       u64 h_ret;
-       u8 port_num;
-       int is_user = 0;
-       enum ib_qp_type qp_type;
-       unsigned long flags;
-
-       if (uobject) {
-               is_user = 1;
-               if (my_qp->mm_count_galpa ||
-                   my_qp->mm_count_rqueue || my_qp->mm_count_squeue) {
-                       ehca_err(dev, "Resources still referenced in "
-                                "user space qp_num=%x", qp_num);
-                       return -EINVAL;
-               }
-       }
-
-       if (my_qp->send_cq) {
-               ret = ehca_cq_unassign_qp(my_qp->send_cq, qp_num);
-               if (ret) {
-                       ehca_err(dev, "Couldn't unassign qp from "
-                                "send_cq ret=%i qp_num=%x cq_num=%x", ret,
-                                qp_num, my_qp->send_cq->cq_number);
-                       return ret;
-               }
-       }
-
-       write_lock_irqsave(&ehca_qp_idr_lock, flags);
-       idr_remove(&ehca_qp_idr, my_qp->token);
-       write_unlock_irqrestore(&ehca_qp_idr_lock, flags);
-
-       /*
-        * SRQs will never get into an error list and do not have a recv_cq,
-        * so we need to skip them here.
-        */
-       if (HAS_RQ(my_qp) && !IS_SRQ(my_qp) && !is_user)
-               del_from_err_list(my_qp->recv_cq, &my_qp->rq_err_node);
-
-       if (HAS_SQ(my_qp) && !is_user)
-               del_from_err_list(my_qp->send_cq, &my_qp->sq_err_node);
-
-       /* now wait until all pending events have completed */
-       wait_event(my_qp->wait_completion, !atomic_read(&my_qp->nr_events));
-
-       h_ret = hipz_h_destroy_qp(shca->ipz_hca_handle, my_qp);
-       if (h_ret != H_SUCCESS) {
-               ehca_err(dev, "hipz_h_destroy_qp() failed h_ret=%lli "
-                        "ehca_qp=%p qp_num=%x", h_ret, my_qp, qp_num);
-               return ehca2ib_return_code(h_ret);
-       }
-
-       port_num = my_qp->init_attr.port_num;
-       qp_type  = my_qp->init_attr.qp_type;
-
-       if (qp_type == IB_QPT_SMI || qp_type == IB_QPT_GSI) {
-               spin_lock_irqsave(&sport->mod_sqp_lock, flags);
-               kfree(my_qp->mod_qp_parm);
-               my_qp->mod_qp_parm = NULL;
-               shca->sport[port_num - 1].ibqp_sqp[qp_type] = NULL;
-               spin_unlock_irqrestore(&sport->mod_sqp_lock, flags);
-       }
-
-       /* no support for IB_QPT_SMI yet */
-       if (qp_type == IB_QPT_GSI) {
-               struct ib_event event;
-               ehca_info(dev, "device %s: port %x is inactive.",
-                               shca->ib_device.name, port_num);
-               event.device = &shca->ib_device;
-               event.event = IB_EVENT_PORT_ERR;
-               event.element.port_num = port_num;
-               shca->sport[port_num - 1].port_state = IB_PORT_DOWN;
-               ib_dispatch_event(&event);
-       }
-
-       if (HAS_RQ(my_qp)) {
-               ipz_queue_dtor(my_pd, &my_qp->ipz_rqueue);
-               if (!is_user)
-                       vfree(my_qp->rq_map.map);
-       }
-       if (HAS_SQ(my_qp)) {
-               ipz_queue_dtor(my_pd, &my_qp->ipz_squeue);
-               if (!is_user)
-                       vfree(my_qp->sq_map.map);
-       }
-       kmem_cache_free(qp_cache, my_qp);
-       atomic_dec(&shca->num_qps);
-       return 0;
-}
-
-int ehca_destroy_qp(struct ib_qp *qp)
-{
-       return internal_destroy_qp(qp->device,
-                                  container_of(qp, struct ehca_qp, ib_qp),
-                                  qp->uobject);
-}
-
-int ehca_destroy_srq(struct ib_srq *srq)
-{
-       return internal_destroy_qp(srq->device,
-                                  container_of(srq, struct ehca_qp, ib_srq),
-                                  srq->uobject);
-}
-
-int ehca_init_qp_cache(void)
-{
-       qp_cache = kmem_cache_create("ehca_cache_qp",
-                                    sizeof(struct ehca_qp), 0,
-                                    SLAB_HWCACHE_ALIGN,
-                                    NULL);
-       if (!qp_cache)
-               return -ENOMEM;
-       return 0;
-}
-
-void ehca_cleanup_qp_cache(void)
-{
-       if (qp_cache)
-               kmem_cache_destroy(qp_cache);
-}
diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c b/drivers/infiniband/hw/ehca/ehca_reqs.c
deleted file mode 100644 (file)
index 47f9498..0000000
+++ /dev/null
@@ -1,953 +0,0 @@
-/*
- *  IBM eServer eHCA Infiniband device driver for Linux on POWER
- *
- *  post_send/recv, poll_cq, req_notify
- *
- *  Authors: Hoang-Nam Nguyen <hnguyen@de.ibm.com>
- *           Waleri Fomin <fomin@de.ibm.com>
- *           Joachim Fenkes <fenkes@de.ibm.com>
- *           Reinhard Ernst <rernst@de.ibm.com>
- *
- *  Copyright (c) 2005 IBM Corporation
- *
- *  All rights reserved.
- *
- *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
- *  BSD.
- *
- * OpenIB BSD License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#include "ehca_classes.h"
-#include "ehca_tools.h"
-#include "ehca_qes.h"
-#include "ehca_iverbs.h"
-#include "hcp_if.h"
-#include "hipz_fns.h"
-
-/* in RC traffic, insert an empty RDMA READ every this many packets */
-#define ACK_CIRC_THRESHOLD 2000000
-
-static u64 replace_wr_id(u64 wr_id, u16 idx)
-{
-       u64 ret;
-
-       ret = wr_id & ~QMAP_IDX_MASK;
-       ret |= idx & QMAP_IDX_MASK;
-
-       return ret;
-}
-
-static u16 get_app_wr_id(u64 wr_id)
-{
-       return wr_id & QMAP_IDX_MASK;
-}
-
-static inline int ehca_write_rwqe(struct ipz_queue *ipz_rqueue,
-                                 struct ehca_wqe *wqe_p,
-                                 struct ib_recv_wr *recv_wr,
-                                 u32 rq_map_idx)
-{
-       u8 cnt_ds;
-       if (unlikely((recv_wr->num_sge < 0) ||
-                    (recv_wr->num_sge > ipz_rqueue->act_nr_of_sg))) {
-               ehca_gen_err("Invalid number of WQE SGE. "
-                        "num_sqe=%x max_nr_of_sg=%x",
-                        recv_wr->num_sge, ipz_rqueue->act_nr_of_sg);
-               return -EINVAL; /* invalid SG list length */
-       }
-
-       /* clear wqe header until sglist */
-       memset(wqe_p, 0, offsetof(struct ehca_wqe, u.ud_av.sg_list));
-
-       wqe_p->work_request_id = replace_wr_id(recv_wr->wr_id, rq_map_idx);
-       wqe_p->nr_of_data_seg = recv_wr->num_sge;
-
-       for (cnt_ds = 0; cnt_ds < recv_wr->num_sge; cnt_ds++) {
-               wqe_p->u.all_rcv.sg_list[cnt_ds].vaddr =
-                       recv_wr->sg_list[cnt_ds].addr;
-               wqe_p->u.all_rcv.sg_list[cnt_ds].lkey =
-                       recv_wr->sg_list[cnt_ds].lkey;
-               wqe_p->u.all_rcv.sg_list[cnt_ds].length =
-                       recv_wr->sg_list[cnt_ds].length;
-       }
-
-       if (ehca_debug_level >= 3) {
-               ehca_gen_dbg("RECEIVE WQE written into ipz_rqueue=%p",
-                            ipz_rqueue);
-               ehca_dmp(wqe_p, 16*(6 + wqe_p->nr_of_data_seg), "recv wqe");
-       }
-
-       return 0;
-}
-
-#if defined(DEBUG_GSI_SEND_WR)
-
-/* need ib_mad struct */
-#include <rdma/ib_mad.h>
-
-static void trace_send_wr_ud(const struct ib_send_wr *send_wr)
-{
-       int idx;
-       int j;
-       while (send_wr) {
-               struct ib_mad_hdr *mad_hdr = send_wr->wr.ud.mad_hdr;
-               struct ib_sge *sge = send_wr->sg_list;
-               ehca_gen_dbg("send_wr#%x wr_id=%lx num_sge=%x "
-                            "send_flags=%x opcode=%x", idx, send_wr->wr_id,
-                            send_wr->num_sge, send_wr->send_flags,
-                            send_wr->opcode);
-               if (mad_hdr) {
-                       ehca_gen_dbg("send_wr#%x mad_hdr base_version=%x "
-                                    "mgmt_class=%x class_version=%x method=%x "
-                                    "status=%x class_specific=%x tid=%lx "
-                                    "attr_id=%x resv=%x attr_mod=%x",
-                                    idx, mad_hdr->base_version,
-                                    mad_hdr->mgmt_class,
-                                    mad_hdr->class_version, mad_hdr->method,
-                                    mad_hdr->status, mad_hdr->class_specific,
-                                    mad_hdr->tid, mad_hdr->attr_id,
-                                    mad_hdr->resv,
-                                    mad_hdr->attr_mod);
-               }
-               for (j = 0; j < send_wr->num_sge; j++) {
-                       u8 *data = __va(sge->addr);
-                       ehca_gen_dbg("send_wr#%x sge#%x addr=%p length=%x "
-                                    "lkey=%x",
-                                    idx, j, data, sge->length, sge->lkey);
-                       /* assume length is n*16 */
-                       ehca_dmp(data, sge->length, "send_wr#%x sge#%x",
-                                idx, j);
-                       sge++;
-               } /* eof for j */
-               idx++;
-               send_wr = send_wr->next;
-       } /* eof while send_wr */
-}
-
-#endif /* DEBUG_GSI_SEND_WR */
-
-static inline int ehca_write_swqe(struct ehca_qp *qp,
-                                 struct ehca_wqe *wqe_p,
-                                 const struct ib_send_wr *send_wr,
-                                 u32 sq_map_idx,
-                                 int hidden)
-{
-       u32 idx;
-       u64 dma_length;
-       struct ehca_av *my_av;
-       u32 remote_qkey = send_wr->wr.ud.remote_qkey;
-       struct ehca_qmap_entry *qmap_entry = &qp->sq_map.map[sq_map_idx];
-
-       if (unlikely((send_wr->num_sge < 0) ||
-                    (send_wr->num_sge > qp->ipz_squeue.act_nr_of_sg))) {
-               ehca_gen_err("Invalid number of WQE SGE. "
-                        "num_sqe=%x max_nr_of_sg=%x",
-                        send_wr->num_sge, qp->ipz_squeue.act_nr_of_sg);
-               return -EINVAL; /* invalid SG list length */
-       }
-
-       /* clear wqe header until sglist */
-       memset(wqe_p, 0, offsetof(struct ehca_wqe, u.ud_av.sg_list));
-
-       wqe_p->work_request_id = replace_wr_id(send_wr->wr_id, sq_map_idx);
-
-       qmap_entry->app_wr_id = get_app_wr_id(send_wr->wr_id);
-       qmap_entry->reported = 0;
-       qmap_entry->cqe_req = 0;
-
-       switch (send_wr->opcode) {
-       case IB_WR_SEND:
-       case IB_WR_SEND_WITH_IMM:
-               wqe_p->optype = WQE_OPTYPE_SEND;
-               break;
-       case IB_WR_RDMA_WRITE:
-       case IB_WR_RDMA_WRITE_WITH_IMM:
-               wqe_p->optype = WQE_OPTYPE_RDMAWRITE;
-               break;
-       case IB_WR_RDMA_READ:
-               wqe_p->optype = WQE_OPTYPE_RDMAREAD;
-               break;
-       default:
-               ehca_gen_err("Invalid opcode=%x", send_wr->opcode);
-               return -EINVAL; /* invalid opcode */
-       }
-
-       wqe_p->wqef = (send_wr->opcode) & WQEF_HIGH_NIBBLE;
-
-       wqe_p->wr_flag = 0;
-
-       if ((send_wr->send_flags & IB_SEND_SIGNALED ||
-           qp->init_attr.sq_sig_type == IB_SIGNAL_ALL_WR)
-           && !hidden) {
-               wqe_p->wr_flag |= WQE_WRFLAG_REQ_SIGNAL_COM;
-               qmap_entry->cqe_req = 1;
-       }
-
-       if (send_wr->opcode == IB_WR_SEND_WITH_IMM ||
-           send_wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM) {
-               /* this might not work as long as HW does not support it */
-               wqe_p->immediate_data = be32_to_cpu(send_wr->ex.imm_data);
-               wqe_p->wr_flag |= WQE_WRFLAG_IMM_DATA_PRESENT;
-       }
-
-       wqe_p->nr_of_data_seg = send_wr->num_sge;
-
-       switch (qp->qp_type) {
-       case IB_QPT_SMI:
-       case IB_QPT_GSI:
-               /* no break is intential here */
-       case IB_QPT_UD:
-               /* IB 1.2 spec C10-15 compliance */
-               if (send_wr->wr.ud.remote_qkey & 0x80000000)
-                       remote_qkey = qp->qkey;
-
-               wqe_p->destination_qp_number = send_wr->wr.ud.remote_qpn << 8;
-               wqe_p->local_ee_context_qkey = remote_qkey;
-               if (unlikely(!send_wr->wr.ud.ah)) {
-                       ehca_gen_err("wr.ud.ah is NULL. qp=%p", qp);
-                       return -EINVAL;
-               }
-               if (unlikely(send_wr->wr.ud.remote_qpn == 0)) {
-                       ehca_gen_err("dest QP# is 0. qp=%x", qp->real_qp_num);
-                       return -EINVAL;
-               }
-               my_av = container_of(send_wr->wr.ud.ah, struct ehca_av, ib_ah);
-               wqe_p->u.ud_av.ud_av = my_av->av;
-
-               /*
-                * omitted check of IB_SEND_INLINE
-                * since HW does not support it
-                */
-               for (idx = 0; idx < send_wr->num_sge; idx++) {
-                       wqe_p->u.ud_av.sg_list[idx].vaddr =
-                               send_wr->sg_list[idx].addr;
-                       wqe_p->u.ud_av.sg_list[idx].lkey =
-                               send_wr->sg_list[idx].lkey;
-                       wqe_p->u.ud_av.sg_list[idx].length =
-                               send_wr->sg_list[idx].length;
-               } /* eof for idx */
-               if (qp->qp_type == IB_QPT_SMI ||
-                   qp->qp_type == IB_QPT_GSI)
-                       wqe_p->u.ud_av.ud_av.pmtu = 1;
-               if (qp->qp_type == IB_QPT_GSI) {
-                       wqe_p->pkeyi = send_wr->wr.ud.pkey_index;
-#ifdef DEBUG_GSI_SEND_WR
-                       trace_send_wr_ud(send_wr);
-#endif /* DEBUG_GSI_SEND_WR */
-               }
-               break;
-
-       case IB_QPT_UC:
-               if (send_wr->send_flags & IB_SEND_FENCE)
-                       wqe_p->wr_flag |= WQE_WRFLAG_FENCE;
-               /* no break is intentional here */
-       case IB_QPT_RC:
-               /* TODO: atomic not implemented */
-               wqe_p->u.nud.remote_virtual_address =
-                       send_wr->wr.rdma.remote_addr;
-               wqe_p->u.nud.rkey = send_wr->wr.rdma.rkey;
-
-               /*
-                * omitted checking of IB_SEND_INLINE
-                * since HW does not support it
-                */
-               dma_length = 0;
-               for (idx = 0; idx < send_wr->num_sge; idx++) {
-                       wqe_p->u.nud.sg_list[idx].vaddr =
-                               send_wr->sg_list[idx].addr;
-                       wqe_p->u.nud.sg_list[idx].lkey =
-                               send_wr->sg_list[idx].lkey;
-                       wqe_p->u.nud.sg_list[idx].length =
-                               send_wr->sg_list[idx].length;
-                       dma_length += send_wr->sg_list[idx].length;
-               } /* eof idx */
-               wqe_p->u.nud.atomic_1st_op_dma_len = dma_length;
-
-               /* unsolicited ack circumvention */
-               if (send_wr->opcode == IB_WR_RDMA_READ) {
-                       /* on RDMA read, switch on and reset counters */
-                       qp->message_count = qp->packet_count = 0;
-                       qp->unsol_ack_circ = 1;
-               } else
-                       /* else estimate #packets */
-                       qp->packet_count += (dma_length >> qp->mtu_shift) + 1;
-
-               break;
-
-       default:
-               ehca_gen_err("Invalid qptype=%x", qp->qp_type);
-               return -EINVAL;
-       }
-
-       if (ehca_debug_level >= 3) {
-               ehca_gen_dbg("SEND WQE written into queue qp=%p ", qp);
-               ehca_dmp( wqe_p, 16*(6 + wqe_p->nr_of_data_seg), "send wqe");
-       }
-       return 0;
-}
-
-/* map_ib_wc_status converts raw cqe_status to ib_wc_status */
-static inline void map_ib_wc_status(u32 cqe_status,
-                                   enum ib_wc_status *wc_status)
-{
-       if (unlikely(cqe_status & WC_STATUS_ERROR_BIT)) {
-               switch (cqe_status & 0x3F) {
-               case 0x01:
-               case 0x21:
-                       *wc_status = IB_WC_LOC_LEN_ERR;
-                       break;
-               case 0x02:
-               case 0x22:
-                       *wc_status = IB_WC_LOC_QP_OP_ERR;
-                       break;
-               case 0x03:
-               case 0x23:
-                       *wc_status = IB_WC_LOC_EEC_OP_ERR;
-                       break;
-               case 0x04:
-               case 0x24:
-                       *wc_status = IB_WC_LOC_PROT_ERR;
-                       break;
-               case 0x05:
-               case 0x25:
-                       *wc_status = IB_WC_WR_FLUSH_ERR;
-                       break;
-               case 0x06:
-                       *wc_status = IB_WC_MW_BIND_ERR;
-                       break;
-               case 0x07: /* remote error - look into bits 20:24 */
-                       switch ((cqe_status
-                                & WC_STATUS_REMOTE_ERROR_FLAGS) >> 11) {
-                       case 0x0:
-                               /*
-                                * PSN Sequence Error!
-                                * couldn't find a matching status!
-                                */
-                               *wc_status = IB_WC_GENERAL_ERR;
-                               break;
-                       case 0x1:
-                               *wc_status = IB_WC_REM_INV_REQ_ERR;
-                               break;
-                       case 0x2:
-                               *wc_status = IB_WC_REM_ACCESS_ERR;
-                               break;
-                       case 0x3:
-                               *wc_status = IB_WC_REM_OP_ERR;
-                               break;
-                       case 0x4:
-                               *wc_status = IB_WC_REM_INV_RD_REQ_ERR;
-                               break;
-                       }
-                       break;
-               case 0x08:
-                       *wc_status = IB_WC_RETRY_EXC_ERR;
-                       break;
-               case 0x09:
-                       *wc_status = IB_WC_RNR_RETRY_EXC_ERR;
-                       break;
-               case 0x0A:
-               case 0x2D:
-                       *wc_status = IB_WC_REM_ABORT_ERR;
-                       break;
-               case 0x0B:
-               case 0x2E:
-                       *wc_status = IB_WC_INV_EECN_ERR;
-                       break;
-               case 0x0C:
-               case 0x2F:
-                       *wc_status = IB_WC_INV_EEC_STATE_ERR;
-                       break;
-               case 0x0D:
-                       *wc_status = IB_WC_BAD_RESP_ERR;
-                       break;
-               case 0x10:
-                       /* WQE purged */
-                       *wc_status = IB_WC_WR_FLUSH_ERR;
-                       break;
-               default:
-                       *wc_status = IB_WC_FATAL_ERR;
-
-               }
-       } else
-               *wc_status = IB_WC_SUCCESS;
-}
-
-static inline int post_one_send(struct ehca_qp *my_qp,
-                        struct ib_send_wr *cur_send_wr,
-                        int hidden)
-{
-       struct ehca_wqe *wqe_p;
-       int ret;
-       u32 sq_map_idx;
-       u64 start_offset = my_qp->ipz_squeue.current_q_offset;
-
-       /* get pointer next to free WQE */
-       wqe_p = ipz_qeit_get_inc(&my_qp->ipz_squeue);
-       if (unlikely(!wqe_p)) {
-               /* too many posted work requests: queue overflow */
-               ehca_err(my_qp->ib_qp.device, "Too many posted WQEs "
-                        "qp_num=%x", my_qp->ib_qp.qp_num);
-               return -ENOMEM;
-       }
-
-       /*
-        * Get the index of the WQE in the send queue. The same index is used
-        * for writing into the sq_map.
-        */
-       sq_map_idx = start_offset / my_qp->ipz_squeue.qe_size;
-
-       /* write a SEND WQE into the QUEUE */
-       ret = ehca_write_swqe(my_qp, wqe_p, cur_send_wr, sq_map_idx, hidden);
-       /*
-        * if something failed,
-        * reset the free entry pointer to the start value
-        */
-       if (unlikely(ret)) {
-               my_qp->ipz_squeue.current_q_offset = start_offset;
-               ehca_err(my_qp->ib_qp.device, "Could not write WQE "
-                        "qp_num=%x", my_qp->ib_qp.qp_num);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-int ehca_post_send(struct ib_qp *qp,
-                  struct ib_send_wr *send_wr,
-                  struct ib_send_wr **bad_send_wr)
-{
-       struct ehca_qp *my_qp = container_of(qp, struct ehca_qp, ib_qp);
-       int wqe_cnt = 0;
-       int ret = 0;
-       unsigned long flags;
-
-       /* Reject WR if QP is in RESET, INIT or RTR state */
-       if (unlikely(my_qp->state < IB_QPS_RTS)) {
-               ehca_err(qp->device, "Invalid QP state  qp_state=%d qpn=%x",
-                        my_qp->state, qp->qp_num);
-               ret = -EINVAL;
-               goto out;
-       }
-
-       /* LOCK the QUEUE */
-       spin_lock_irqsave(&my_qp->spinlock_s, flags);
-
-       /* Send an empty extra RDMA read if:
-        *  1) there has been an RDMA read on this connection before
-        *  2) no RDMA read occurred for ACK_CIRC_THRESHOLD link packets
-        *  3) we can be sure that any previous extra RDMA read has been
-        *     processed so we don't overflow the SQ
-        */
-       if (unlikely(my_qp->unsol_ack_circ &&
-                    my_qp->packet_count > ACK_CIRC_THRESHOLD &&
-                    my_qp->message_count > my_qp->init_attr.cap.max_send_wr)) {
-               /* insert an empty RDMA READ to fix up the remote QP state */
-               struct ib_send_wr circ_wr;
-               memset(&circ_wr, 0, sizeof(circ_wr));
-               circ_wr.opcode = IB_WR_RDMA_READ;
-               post_one_send(my_qp, &circ_wr, 1); /* ignore retcode */
-               wqe_cnt++;
-               ehca_dbg(qp->device, "posted circ wr  qp_num=%x", qp->qp_num);
-               my_qp->message_count = my_qp->packet_count = 0;
-       }
-
-       /* loop processes list of send reqs */
-       while (send_wr) {
-               ret = post_one_send(my_qp, send_wr, 0);
-               if (unlikely(ret)) {
-                       goto post_send_exit0;
-               }
-               wqe_cnt++;
-               send_wr = send_wr->next;
-       }
-
-post_send_exit0:
-       iosync(); /* serialize GAL register access */
-       hipz_update_sqa(my_qp, wqe_cnt);
-       if (unlikely(ret || ehca_debug_level >= 2))
-               ehca_dbg(qp->device, "ehca_qp=%p qp_num=%x wqe_cnt=%d ret=%i",
-                        my_qp, qp->qp_num, wqe_cnt, ret);
-       my_qp->message_count += wqe_cnt;
-       spin_unlock_irqrestore(&my_qp->spinlock_s, flags);
-
-out:
-       if (ret)
-               *bad_send_wr = send_wr;
-       return ret;
-}
-
-static int internal_post_recv(struct ehca_qp *my_qp,
-                             struct ib_device *dev,
-                             struct ib_recv_wr *recv_wr,
-                             struct ib_recv_wr **bad_recv_wr)
-{
-       struct ehca_wqe *wqe_p;
-       int wqe_cnt = 0;
-       int ret = 0;
-       u32 rq_map_idx;
-       unsigned long flags;
-       struct ehca_qmap_entry *qmap_entry;
-
-       if (unlikely(!HAS_RQ(my_qp))) {
-               ehca_err(dev, "QP has no RQ  ehca_qp=%p qp_num=%x ext_type=%d",
-                        my_qp, my_qp->real_qp_num, my_qp->ext_type);
-               ret = -ENODEV;
-               goto out;
-       }
-
-       /* LOCK the QUEUE */
-       spin_lock_irqsave(&my_qp->spinlock_r, flags);
-
-       /* loop processes list of recv reqs */
-       while (recv_wr) {
-               u64 start_offset = my_qp->ipz_rqueue.current_q_offset;
-               /* get pointer next to free WQE */
-               wqe_p = ipz_qeit_get_inc(&my_qp->ipz_rqueue);
-               if (unlikely(!wqe_p)) {
-                       /* too many posted work requests: queue overflow */
-                       ret = -ENOMEM;
-                       ehca_err(dev, "Too many posted WQEs "
-                               "qp_num=%x", my_qp->real_qp_num);
-                       goto post_recv_exit0;
-               }
-               /*
-                * Get the index of the WQE in the recv queue. The same index
-                * is used for writing into the rq_map.
-                */
-               rq_map_idx = start_offset / my_qp->ipz_rqueue.qe_size;
-
-               /* write a RECV WQE into the QUEUE */
-               ret = ehca_write_rwqe(&my_qp->ipz_rqueue, wqe_p, recv_wr,
-                               rq_map_idx);
-               /*
-                * if something failed,
-                * reset the free entry pointer to the start value
-                */
-               if (unlikely(ret)) {
-                       my_qp->ipz_rqueue.current_q_offset = start_offset;
-                       ret = -EINVAL;
-                       ehca_err(dev, "Could not write WQE "
-                               "qp_num=%x", my_qp->real_qp_num);
-                       goto post_recv_exit0;
-               }
-
-               qmap_entry = &my_qp->rq_map.map[rq_map_idx];
-               qmap_entry->app_wr_id = get_app_wr_id(recv_wr->wr_id);
-               qmap_entry->reported = 0;
-               qmap_entry->cqe_req = 1;
-
-               wqe_cnt++;
-               recv_wr = recv_wr->next;
-       } /* eof for recv_wr */
-
-post_recv_exit0:
-       iosync(); /* serialize GAL register access */
-       hipz_update_rqa(my_qp, wqe_cnt);
-       if (unlikely(ret || ehca_debug_level >= 2))
-           ehca_dbg(dev, "ehca_qp=%p qp_num=%x wqe_cnt=%d ret=%i",
-                    my_qp, my_qp->real_qp_num, wqe_cnt, ret);
-       spin_unlock_irqrestore(&my_qp->spinlock_r, flags);
-
-out:
-       if (ret)
-               *bad_recv_wr = recv_wr;
-
-       return ret;
-}
-
-int ehca_post_recv(struct ib_qp *qp,
-                  struct ib_recv_wr *recv_wr,
-                  struct ib_recv_wr **bad_recv_wr)
-{
-       struct ehca_qp *my_qp = container_of(qp, struct ehca_qp, ib_qp);
-
-       /* Reject WR if QP is in RESET state */
-       if (unlikely(my_qp->state == IB_QPS_RESET)) {
-               ehca_err(qp->device, "Invalid QP state  qp_state=%d qpn=%x",
-                        my_qp->state, qp->qp_num);
-               *bad_recv_wr = recv_wr;
-               return -EINVAL;
-       }
-
-       return internal_post_recv(my_qp, qp->device, recv_wr, bad_recv_wr);
-}
-
-int ehca_post_srq_recv(struct ib_srq *srq,
-                      struct ib_recv_wr *recv_wr,
-                      struct ib_recv_wr **bad_recv_wr)
-{
-       return internal_post_recv(container_of(srq, struct ehca_qp, ib_srq),
-                                 srq->device, recv_wr, bad_recv_wr);
-}
-
-/*
- * ib_wc_opcode table converts ehca wc opcode to ib
- * Since we use zero to indicate invalid opcode, the actual ib opcode must
- * be decremented!!!
- */
-static const u8 ib_wc_opcode[255] = {
-       [0x01] = IB_WC_RECV+1,
-       [0x02] = IB_WC_RECV_RDMA_WITH_IMM+1,
-       [0x04] = IB_WC_BIND_MW+1,
-       [0x08] = IB_WC_FETCH_ADD+1,
-       [0x10] = IB_WC_COMP_SWAP+1,
-       [0x20] = IB_WC_RDMA_WRITE+1,
-       [0x40] = IB_WC_RDMA_READ+1,
-       [0x80] = IB_WC_SEND+1
-};
-
-/* internal function to poll one entry of cq */
-static inline int ehca_poll_cq_one(struct ib_cq *cq, struct ib_wc *wc)
-{
-       int ret = 0, qmap_tail_idx;
-       struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq);
-       struct ehca_cqe *cqe;
-       struct ehca_qp *my_qp;
-       struct ehca_qmap_entry *qmap_entry;
-       struct ehca_queue_map *qmap;
-       int cqe_count = 0, is_error;
-
-repoll:
-       cqe = (struct ehca_cqe *)
-               ipz_qeit_get_inc_valid(&my_cq->ipz_queue);
-       if (!cqe) {
-               ret = -EAGAIN;
-               if (ehca_debug_level >= 3)
-                       ehca_dbg(cq->device, "Completion queue is empty  "
-                                "my_cq=%p cq_num=%x", my_cq, my_cq->cq_number);
-               goto poll_cq_one_exit0;
-       }
-
-       /* prevents loads being reordered across this point */
-       rmb();
-
-       cqe_count++;
-       if (unlikely(cqe->status & WC_STATUS_PURGE_BIT)) {
-               struct ehca_qp *qp;
-               int purgeflag;
-               unsigned long flags;
-
-               qp = ehca_cq_get_qp(my_cq, cqe->local_qp_number);
-               if (!qp) {
-                       ehca_err(cq->device, "cq_num=%x qp_num=%x "
-                                "could not find qp -> ignore cqe",
-                                my_cq->cq_number, cqe->local_qp_number);
-                       ehca_dmp(cqe, 64, "cq_num=%x qp_num=%x",
-                                my_cq->cq_number, cqe->local_qp_number);
-                       /* ignore this purged cqe */
-                       goto repoll;
-               }
-               spin_lock_irqsave(&qp->spinlock_s, flags);
-               purgeflag = qp->sqerr_purgeflag;
-               spin_unlock_irqrestore(&qp->spinlock_s, flags);
-
-               if (purgeflag) {
-                       ehca_dbg(cq->device,
-                                "Got CQE with purged bit qp_num=%x src_qp=%x",
-                                cqe->local_qp_number, cqe->remote_qp_number);
-                       if (ehca_debug_level >= 2)
-                               ehca_dmp(cqe, 64, "qp_num=%x src_qp=%x",
-                                        cqe->local_qp_number,
-                                        cqe->remote_qp_number);
-                       /*
-                        * ignore this to avoid double cqes of bad wqe
-                        * that caused sqe and turn off purge flag
-                        */
-                       qp->sqerr_purgeflag = 0;
-                       goto repoll;
-               }
-       }
-
-       is_error = cqe->status & WC_STATUS_ERROR_BIT;
-
-       /* trace error CQEs if debug_level >= 1, trace all CQEs if >= 3 */
-       if (unlikely(ehca_debug_level >= 3 || (ehca_debug_level && is_error))) {
-               ehca_dbg(cq->device,
-                        "Received %sCOMPLETION ehca_cq=%p cq_num=%x -----",
-                        is_error ? "ERROR " : "", my_cq, my_cq->cq_number);
-               ehca_dmp(cqe, 64, "ehca_cq=%p cq_num=%x",
-                        my_cq, my_cq->cq_number);
-               ehca_dbg(cq->device,
-                        "ehca_cq=%p cq_num=%x -------------------------",
-                        my_cq, my_cq->cq_number);
-       }
-
-       read_lock(&ehca_qp_idr_lock);
-       my_qp = idr_find(&ehca_qp_idr, cqe->qp_token);
-       read_unlock(&ehca_qp_idr_lock);
-       if (!my_qp)
-               goto repoll;
-       wc->qp = &my_qp->ib_qp;
-
-       qmap_tail_idx = get_app_wr_id(cqe->work_request_id);
-       if (!(cqe->w_completion_flags & WC_SEND_RECEIVE_BIT))
-               /* We got a send completion. */
-               qmap = &my_qp->sq_map;
-       else
-               /* We got a receive completion. */
-               qmap = &my_qp->rq_map;
-
-       /* advance the tail pointer */
-       qmap->tail = qmap_tail_idx;
-
-       if (is_error) {
-               /*
-                * set left_to_poll to 0 because in error state, we will not
-                * get any additional CQEs
-                */
-               my_qp->sq_map.next_wqe_idx = next_index(my_qp->sq_map.tail,
-                                                       my_qp->sq_map.entries);
-               my_qp->sq_map.left_to_poll = 0;
-               ehca_add_to_err_list(my_qp, 1);
-
-               my_qp->rq_map.next_wqe_idx = next_index(my_qp->rq_map.tail,
-                                                       my_qp->rq_map.entries);
-               my_qp->rq_map.left_to_poll = 0;
-               if (HAS_RQ(my_qp))
-                       ehca_add_to_err_list(my_qp, 0);
-       }
-
-       qmap_entry = &qmap->map[qmap_tail_idx];
-       if (qmap_entry->reported) {
-               ehca_warn(cq->device, "Double cqe on qp_num=%#x",
-                               my_qp->real_qp_num);
-               /* found a double cqe, discard it and read next one */
-               goto repoll;
-       }
-
-       wc->wr_id = replace_wr_id(cqe->work_request_id, qmap_entry->app_wr_id);
-       qmap_entry->reported = 1;
-
-       /* if left_to_poll is decremented to 0, add the QP to the error list */
-       if (qmap->left_to_poll > 0) {
-               qmap->left_to_poll--;
-               if ((my_qp->sq_map.left_to_poll == 0) &&
-                               (my_qp->rq_map.left_to_poll == 0)) {
-                       ehca_add_to_err_list(my_qp, 1);
-                       if (HAS_RQ(my_qp))
-                               ehca_add_to_err_list(my_qp, 0);
-               }
-       }
-
-       /* eval ib_wc_opcode */
-       wc->opcode = ib_wc_opcode[cqe->optype]-1;
-       if (unlikely(wc->opcode == -1)) {
-               ehca_err(cq->device, "Invalid cqe->OPType=%x cqe->status=%x "
-                        "ehca_cq=%p cq_num=%x",
-                        cqe->optype, cqe->status, my_cq, my_cq->cq_number);
-               /* dump cqe for other infos */
-               ehca_dmp(cqe, 64, "ehca_cq=%p cq_num=%x",
-                        my_cq, my_cq->cq_number);
-               /* update also queue adder to throw away this entry!!! */
-               goto repoll;
-       }
-
-       /* eval ib_wc_status */
-       if (unlikely(is_error)) {
-               /* complete with errors */
-               map_ib_wc_status(cqe->status, &wc->status);
-               wc->vendor_err = wc->status;
-       } else
-               wc->status = IB_WC_SUCCESS;
-
-       wc->byte_len = cqe->nr_bytes_transferred;
-       wc->pkey_index = cqe->pkey_index;
-       wc->slid = cqe->rlid;
-       wc->dlid_path_bits = cqe->dlid;
-       wc->src_qp = cqe->remote_qp_number;
-       /*
-        * HW has "Immed data present" and "GRH present" in bits 6 and 5.
-        * SW defines those in bits 1 and 0, so we can just shift and mask.
-        */
-       wc->wc_flags = (cqe->w_completion_flags >> 5) & 3;
-       wc->ex.imm_data = cpu_to_be32(cqe->immediate_data);
-       wc->sl = cqe->service_level;
-
-poll_cq_one_exit0:
-       if (cqe_count > 0)
-               hipz_update_feca(my_cq, cqe_count);
-
-       return ret;
-}
-
-static int generate_flush_cqes(struct ehca_qp *my_qp, struct ib_cq *cq,
-                              struct ib_wc *wc, int num_entries,
-                              struct ipz_queue *ipz_queue, int on_sq)
-{
-       int nr = 0;
-       struct ehca_wqe *wqe;
-       u64 offset;
-       struct ehca_queue_map *qmap;
-       struct ehca_qmap_entry *qmap_entry;
-
-       if (on_sq)
-               qmap = &my_qp->sq_map;
-       else
-               qmap = &my_qp->rq_map;
-
-       qmap_entry = &qmap->map[qmap->next_wqe_idx];
-
-       while ((nr < num_entries) && (qmap_entry->reported == 0)) {
-               /* generate flush CQE */
-
-               memset(wc, 0, sizeof(*wc));
-
-               offset = qmap->next_wqe_idx * ipz_queue->qe_size;
-               wqe = (struct ehca_wqe *)ipz_qeit_calc(ipz_queue, offset);
-               if (!wqe) {
-                       ehca_err(cq->device, "Invalid wqe offset=%#llx on "
-                                "qp_num=%#x", offset, my_qp->real_qp_num);
-                       return nr;
-               }
-
-               wc->wr_id = replace_wr_id(wqe->work_request_id,
-                                         qmap_entry->app_wr_id);
-
-               if (on_sq) {
-                       switch (wqe->optype) {
-                       case WQE_OPTYPE_SEND:
-                               wc->opcode = IB_WC_SEND;
-                               break;
-                       case WQE_OPTYPE_RDMAWRITE:
-                               wc->opcode = IB_WC_RDMA_WRITE;
-                               break;
-                       case WQE_OPTYPE_RDMAREAD:
-                               wc->opcode = IB_WC_RDMA_READ;
-                               break;
-                       default:
-                               ehca_err(cq->device, "Invalid optype=%x",
-                                               wqe->optype);
-                               return nr;
-                       }
-               } else
-                       wc->opcode = IB_WC_RECV;
-
-               if (wqe->wr_flag & WQE_WRFLAG_IMM_DATA_PRESENT) {
-                       wc->ex.imm_data = wqe->immediate_data;
-                       wc->wc_flags |= IB_WC_WITH_IMM;
-               }
-
-               wc->status = IB_WC_WR_FLUSH_ERR;
-
-               wc->qp = &my_qp->ib_qp;
-
-               /* mark as reported and advance next_wqe pointer */
-               qmap_entry->reported = 1;
-               qmap->next_wqe_idx = next_index(qmap->next_wqe_idx,
-                                               qmap->entries);
-               qmap_entry = &qmap->map[qmap->next_wqe_idx];
-
-               wc++; nr++;
-       }
-
-       return nr;
-
-}
-
-int ehca_poll_cq(struct ib_cq *cq, int num_entries, struct ib_wc *wc)
-{
-       struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq);
-       int nr;
-       struct ehca_qp *err_qp;
-       struct ib_wc *current_wc = wc;
-       int ret = 0;
-       unsigned long flags;
-       int entries_left = num_entries;
-
-       if (num_entries < 1) {
-               ehca_err(cq->device, "Invalid num_entries=%d ehca_cq=%p "
-                        "cq_num=%x", num_entries, my_cq, my_cq->cq_number);
-               ret = -EINVAL;
-               goto poll_cq_exit0;
-       }
-
-       spin_lock_irqsave(&my_cq->spinlock, flags);
-
-       /* generate flush cqes for send queues */
-       list_for_each_entry(err_qp, &my_cq->sqp_err_list, sq_err_node) {
-               nr = generate_flush_cqes(err_qp, cq, current_wc, entries_left,
-                               &err_qp->ipz_squeue, 1);
-               entries_left -= nr;
-               current_wc += nr;
-
-               if (entries_left == 0)
-                       break;
-       }
-
-       /* generate flush cqes for receive queues */
-       list_for_each_entry(err_qp, &my_cq->rqp_err_list, rq_err_node) {
-               nr = generate_flush_cqes(err_qp, cq, current_wc, entries_left,
-                               &err_qp->ipz_rqueue, 0);
-               entries_left -= nr;
-               current_wc += nr;
-
-               if (entries_left == 0)
-                       break;
-       }
-
-       for (nr = 0; nr < entries_left; nr++) {
-               ret = ehca_poll_cq_one(cq, current_wc);
-               if (ret)
-                       break;
-               current_wc++;
-       } /* eof for nr */
-       entries_left -= nr;
-
-       spin_unlock_irqrestore(&my_cq->spinlock, flags);
-       if (ret == -EAGAIN  || !ret)
-               ret = num_entries - entries_left;
-
-poll_cq_exit0:
-       return ret;
-}
-
-int ehca_req_notify_cq(struct ib_cq *cq, enum ib_cq_notify_flags notify_flags)
-{
-       struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq);
-       int ret = 0;
-
-       switch (notify_flags & IB_CQ_SOLICITED_MASK) {
-       case IB_CQ_SOLICITED:
-               hipz_set_cqx_n0(my_cq, 1);
-               break;
-       case IB_CQ_NEXT_COMP:
-               hipz_set_cqx_n1(my_cq, 1);
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       if (notify_flags & IB_CQ_REPORT_MISSED_EVENTS) {
-               unsigned long spl_flags;
-               spin_lock_irqsave(&my_cq->spinlock, spl_flags);
-               ret = ipz_qeit_is_valid(&my_cq->ipz_queue);
-               spin_unlock_irqrestore(&my_cq->spinlock, spl_flags);
-       }
-
-       return ret;
-}
diff --git a/drivers/infiniband/hw/ehca/ehca_sqp.c b/drivers/infiniband/hw/ehca/ehca_sqp.c
deleted file mode 100644 (file)
index 376b031..0000000
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- *  IBM eServer eHCA Infiniband device driver for Linux on POWER
- *
- *  SQP functions
- *
- *  Authors: Khadija Souissi <souissi@de.ibm.com>
- *           Heiko J Schick <schickhj@de.ibm.com>
- *
- *  Copyright (c) 2005 IBM Corporation
- *
- *  All rights reserved.
- *
- *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
- *  BSD.
- *
- * OpenIB BSD License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <rdma/ib_mad.h>
-
-#include "ehca_classes.h"
-#include "ehca_tools.h"
-#include "ehca_iverbs.h"
-#include "hcp_if.h"
-
-#define IB_MAD_STATUS_REDIRECT         cpu_to_be16(0x0002)
-#define IB_MAD_STATUS_UNSUP_VERSION    cpu_to_be16(0x0004)
-#define IB_MAD_STATUS_UNSUP_METHOD     cpu_to_be16(0x0008)
-
-#define IB_PMA_CLASS_PORT_INFO         cpu_to_be16(0x0001)
-
-/**
- * ehca_define_sqp - Defines special queue pair 1 (GSI QP). When special queue
- * pair is created successfully, the corresponding port gets active.
- *
- * Define Special Queue pair 0 (SMI QP) is still not supported.
- *
- * @qp_init_attr: Queue pair init attributes with port and queue pair type
- */
-
-u64 ehca_define_sqp(struct ehca_shca *shca,
-                   struct ehca_qp *ehca_qp,
-                   struct ib_qp_init_attr *qp_init_attr)
-{
-       u32 pma_qp_nr, bma_qp_nr;
-       u64 ret;
-       u8 port = qp_init_attr->port_num;
-       int counter;
-
-       shca->sport[port - 1].port_state = IB_PORT_DOWN;
-
-       switch (qp_init_attr->qp_type) {
-       case IB_QPT_SMI:
-               /* function not supported yet */
-               break;
-       case IB_QPT_GSI:
-               ret = hipz_h_define_aqp1(shca->ipz_hca_handle,
-                                        ehca_qp->ipz_qp_handle,
-                                        ehca_qp->galpas.kernel,
-                                        (u32) qp_init_attr->port_num,
-                                        &pma_qp_nr, &bma_qp_nr);
-
-               if (ret != H_SUCCESS) {
-                       ehca_err(&shca->ib_device,
-                                "Can't define AQP1 for port %x. h_ret=%lli",
-                                port, ret);
-                       return ret;
-               }
-               shca->sport[port - 1].pma_qp_nr = pma_qp_nr;
-               ehca_dbg(&shca->ib_device, "port=%x pma_qp_nr=%x",
-                        port, pma_qp_nr);
-               break;
-       default:
-               ehca_err(&shca->ib_device, "invalid qp_type=%x",
-                        qp_init_attr->qp_type);
-               return H_PARAMETER;
-       }
-
-       if (ehca_nr_ports < 0) /* autodetect mode */
-               return H_SUCCESS;
-
-       for (counter = 0;
-            shca->sport[port - 1].port_state != IB_PORT_ACTIVE &&
-                    counter < ehca_port_act_time;
-            counter++) {
-               ehca_dbg(&shca->ib_device, "... wait until port %x is active",
-                        port);
-               msleep_interruptible(1000);
-       }
-
-       if (counter == ehca_port_act_time) {
-               ehca_err(&shca->ib_device, "Port %x is not active.", port);
-               return H_HARDWARE;
-       }
-
-       return H_SUCCESS;
-}
-
-struct ib_perf {
-       struct ib_mad_hdr mad_hdr;
-       u8 reserved[40];
-       u8 data[192];
-} __attribute__ ((packed));
-
-/* TC/SL/FL packed into 32 bits, as in ClassPortInfo */
-struct tcslfl {
-       u32 tc:8;
-       u32 sl:4;
-       u32 fl:20;
-} __attribute__ ((packed));
-
-/* IP Version/TC/FL packed into 32 bits, as in GRH */
-struct vertcfl {
-       u32 ver:4;
-       u32 tc:8;
-       u32 fl:20;
-} __attribute__ ((packed));
-
-static int ehca_process_perf(struct ib_device *ibdev, u8 port_num,
-                            const struct ib_wc *in_wc, const struct ib_grh *in_grh,
-                            const struct ib_mad *in_mad, struct ib_mad *out_mad)
-{
-       const struct ib_perf *in_perf = (const struct ib_perf *)in_mad;
-       struct ib_perf *out_perf = (struct ib_perf *)out_mad;
-       struct ib_class_port_info *poi =
-               (struct ib_class_port_info *)out_perf->data;
-       struct tcslfl *tcslfl =
-               (struct tcslfl *)&poi->redirect_tcslfl;
-       struct ehca_shca *shca =
-               container_of(ibdev, struct ehca_shca, ib_device);
-       struct ehca_sport *sport = &shca->sport[port_num - 1];
-
-       ehca_dbg(ibdev, "method=%x", in_perf->mad_hdr.method);
-
-       *out_mad = *in_mad;
-
-       if (in_perf->mad_hdr.class_version != 1) {
-               ehca_warn(ibdev, "Unsupported class_version=%x",
-                         in_perf->mad_hdr.class_version);
-               out_perf->mad_hdr.status = IB_MAD_STATUS_UNSUP_VERSION;
-               goto perf_reply;
-       }
-
-       switch (in_perf->mad_hdr.method) {
-       case IB_MGMT_METHOD_GET:
-       case IB_MGMT_METHOD_SET:
-               /* set class port info for redirection */
-               out_perf->mad_hdr.attr_id = IB_PMA_CLASS_PORT_INFO;
-               out_perf->mad_hdr.status = IB_MAD_STATUS_REDIRECT;
-               memset(poi, 0, sizeof(*poi));
-               poi->base_version = 1;
-               poi->class_version = 1;
-               poi->resp_time_value = 18;
-
-               /* copy local routing information from WC where applicable */
-               tcslfl->sl         = in_wc->sl;
-               poi->redirect_lid  =
-                       sport->saved_attr.lid | in_wc->dlid_path_bits;
-               poi->redirect_qp   = sport->pma_qp_nr;
-               poi->redirect_qkey = IB_QP1_QKEY;
-
-               ehca_query_pkey(ibdev, port_num, in_wc->pkey_index,
-                               &poi->redirect_pkey);
-
-               /* if request was globally routed, copy route info */
-               if (in_grh) {
-                       const struct vertcfl *vertcfl =
-                               (const struct vertcfl *)&in_grh->version_tclass_flow;
-                       memcpy(poi->redirect_gid, in_grh->dgid.raw,
-                              sizeof(poi->redirect_gid));
-                       tcslfl->tc        = vertcfl->tc;
-                       tcslfl->fl        = vertcfl->fl;
-               } else
-                       /* else only fill in default GID */
-                       ehca_query_gid(ibdev, port_num, 0,
-                                      (union ib_gid *)&poi->redirect_gid);
-
-               ehca_dbg(ibdev, "ehca_pma_lid=%x ehca_pma_qp=%x",
-                        sport->saved_attr.lid, sport->pma_qp_nr);
-               break;
-
-       case IB_MGMT_METHOD_GET_RESP:
-               return IB_MAD_RESULT_FAILURE;
-
-       default:
-               out_perf->mad_hdr.status = IB_MAD_STATUS_UNSUP_METHOD;
-               break;
-       }
-
-perf_reply:
-       out_perf->mad_hdr.method = IB_MGMT_METHOD_GET_RESP;
-
-       return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY;
-}
-
-int ehca_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
-                    const struct ib_wc *in_wc, const struct ib_grh *in_grh,
-                    const struct ib_mad_hdr *in, size_t in_mad_size,
-                    struct ib_mad_hdr *out, size_t *out_mad_size,
-                    u16 *out_mad_pkey_index)
-{
-       int ret;
-       const struct ib_mad *in_mad = (const struct ib_mad *)in;
-       struct ib_mad *out_mad = (struct ib_mad *)out;
-
-       if (WARN_ON_ONCE(in_mad_size != sizeof(*in_mad) ||
-                        *out_mad_size != sizeof(*out_mad)))
-               return IB_MAD_RESULT_FAILURE;
-
-       if (!port_num || port_num > ibdev->phys_port_cnt || !in_wc)
-               return IB_MAD_RESULT_FAILURE;
-
-       /* accept only pma request */
-       if (in_mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_PERF_MGMT)
-               return IB_MAD_RESULT_SUCCESS;
-
-       ehca_dbg(ibdev, "port_num=%x src_qp=%x", port_num, in_wc->src_qp);
-       ret = ehca_process_perf(ibdev, port_num, in_wc, in_grh,
-                               in_mad, out_mad);
-
-       return ret;
-}
diff --git a/drivers/infiniband/hw/ehca/ehca_tools.h b/drivers/infiniband/hw/ehca/ehca_tools.h
deleted file mode 100644 (file)
index d280b12..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- *  IBM eServer eHCA Infiniband device driver for Linux on POWER
- *
- *  auxiliary functions
- *
- *  Authors: Christoph Raisch <raisch@de.ibm.com>
- *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
- *           Khadija Souissi <souissik@de.ibm.com>
- *           Waleri Fomin <fomin@de.ibm.com>
- *           Heiko J Schick <schickhj@de.ibm.com>
- *
- *  Copyright (c) 2005 IBM Corporation
- *
- *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
- *  BSD.
- *
- * OpenIB BSD License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef EHCA_TOOLS_H
-#define EHCA_TOOLS_H
-
-#include <linux/kernel.h>
-#include <linux/spinlock.h>
-#include <linux/delay.h>
-#include <linux/idr.h>
-#include <linux/kthread.h>
-#include <linux/mm.h>
-#include <linux/mman.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/vmalloc.h>
-#include <linux/notifier.h>
-#include <linux/cpu.h>
-#include <linux/device.h>
-
-#include <linux/atomic.h>
-#include <asm/ibmebus.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/hvcall.h>
-
-extern int ehca_debug_level;
-
-#define ehca_dbg(ib_dev, format, arg...) \
-       do { \
-               if (unlikely(ehca_debug_level)) \
-                       dev_printk(KERN_DEBUG, (ib_dev)->dma_device, \
-                                  "PU%04x EHCA_DBG:%s " format "\n", \
-                                  raw_smp_processor_id(), __func__, \
-                                  ## arg); \
-       } while (0)
-
-#define ehca_info(ib_dev, format, arg...) \
-       dev_info((ib_dev)->dma_device, "PU%04x EHCA_INFO:%s " format "\n", \
-                raw_smp_processor_id(), __func__, ## arg)
-
-#define ehca_warn(ib_dev, format, arg...) \
-       dev_warn((ib_dev)->dma_device, "PU%04x EHCA_WARN:%s " format "\n", \
-                raw_smp_processor_id(), __func__, ## arg)
-
-#define ehca_err(ib_dev, format, arg...) \
-       dev_err((ib_dev)->dma_device, "PU%04x EHCA_ERR:%s " format "\n", \
-               raw_smp_processor_id(), __func__, ## arg)
-
-/* use this one only if no ib_dev available */
-#define ehca_gen_dbg(format, arg...) \
-       do { \
-               if (unlikely(ehca_debug_level)) \
-                       printk(KERN_DEBUG "PU%04x EHCA_DBG:%s " format "\n", \
-                              raw_smp_processor_id(), __func__, ## arg); \
-       } while (0)
-
-#define ehca_gen_warn(format, arg...) \
-       printk(KERN_INFO "PU%04x EHCA_WARN:%s " format "\n", \
-              raw_smp_processor_id(), __func__, ## arg)
-
-#define ehca_gen_err(format, arg...) \
-       printk(KERN_ERR "PU%04x EHCA_ERR:%s " format "\n", \
-              raw_smp_processor_id(), __func__, ## arg)
-
-/**
- * ehca_dmp - printk a memory block, whose length is n*8 bytes.
- * Each line has the following layout:
- * <format string> adr=X ofs=Y <8 bytes hex> <8 bytes hex>
- */
-#define ehca_dmp(adr, len, format, args...) \
-       do { \
-               unsigned int x; \
-               unsigned int l = (unsigned int)(len); \
-               unsigned char *deb = (unsigned char *)(adr); \
-               for (x = 0; x < l; x += 16) { \
-                       printk(KERN_INFO "EHCA_DMP:%s " format \
-                              " adr=%p ofs=%04x %016llx %016llx\n", \
-                              __func__, ##args, deb, x, \
-                              *((u64 *)&deb[0]), *((u64 *)&deb[8])); \
-                       deb += 16; \
-               } \
-       } while (0)
-
-/* define a bitmask, little endian version */
-#define EHCA_BMASK(pos, length) (((pos) << 16) + (length))
-
-/* define a bitmask, the ibm way... */
-#define EHCA_BMASK_IBM(from, to) (((63 - to) << 16) + ((to) - (from) + 1))
-
-/* internal function, don't use */
-#define EHCA_BMASK_SHIFTPOS(mask) (((mask) >> 16) & 0xffff)
-
-/* internal function, don't use */
-#define EHCA_BMASK_MASK(mask) (~0ULL >> ((64 - (mask)) & 0xffff))
-
-/**
- * EHCA_BMASK_SET - return value shifted and masked by mask
- * variable|=EHCA_BMASK_SET(MY_MASK,0x4711) ORs the bits in variable
- * variable&=~EHCA_BMASK_SET(MY_MASK,-1) clears the bits from the mask
- * in variable
- */
-#define EHCA_BMASK_SET(mask, value) \
-       ((EHCA_BMASK_MASK(mask) & ((u64)(value))) << EHCA_BMASK_SHIFTPOS(mask))
-
-/**
- * EHCA_BMASK_GET - extract a parameter from value by mask
- */
-#define EHCA_BMASK_GET(mask, value) \
-       (EHCA_BMASK_MASK(mask) & (((u64)(value)) >> EHCA_BMASK_SHIFTPOS(mask)))
-
-/* Converts ehca to ib return code */
-int ehca2ib_return_code(u64 ehca_rc);
-
-#endif /* EHCA_TOOLS_H */
diff --git a/drivers/infiniband/hw/ehca/ehca_uverbs.c b/drivers/infiniband/hw/ehca/ehca_uverbs.c
deleted file mode 100644 (file)
index 1a1d5d9..0000000
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
- *  IBM eServer eHCA Infiniband device driver for Linux on POWER
- *
- *  userspace support verbs
- *
- *  Authors: Christoph Raisch <raisch@de.ibm.com>
- *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
- *           Heiko J Schick <schickhj@de.ibm.com>
- *
- *  Copyright (c) 2005 IBM Corporation
- *
- *  All rights reserved.
- *
- *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
- *  BSD.
- *
- * OpenIB BSD License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <linux/slab.h>
-
-#include "ehca_classes.h"
-#include "ehca_iverbs.h"
-#include "ehca_mrmw.h"
-#include "ehca_tools.h"
-#include "hcp_if.h"
-
-struct ib_ucontext *ehca_alloc_ucontext(struct ib_device *device,
-                                       struct ib_udata *udata)
-{
-       struct ehca_ucontext *my_context;
-
-       my_context = kzalloc(sizeof *my_context, GFP_KERNEL);
-       if (!my_context) {
-               ehca_err(device, "Out of memory device=%p", device);
-               return ERR_PTR(-ENOMEM);
-       }
-
-       return &my_context->ib_ucontext;
-}
-
-int ehca_dealloc_ucontext(struct ib_ucontext *context)
-{
-       kfree(container_of(context, struct ehca_ucontext, ib_ucontext));
-       return 0;
-}
-
-static void ehca_mm_open(struct vm_area_struct *vma)
-{
-       u32 *count = (u32 *)vma->vm_private_data;
-       if (!count) {
-               ehca_gen_err("Invalid vma struct vm_start=%lx vm_end=%lx",
-                            vma->vm_start, vma->vm_end);
-               return;
-       }
-       (*count)++;
-       if (!(*count))
-               ehca_gen_err("Use count overflow vm_start=%lx vm_end=%lx",
-                            vma->vm_start, vma->vm_end);
-       ehca_gen_dbg("vm_start=%lx vm_end=%lx count=%x",
-                    vma->vm_start, vma->vm_end, *count);
-}
-
-static void ehca_mm_close(struct vm_area_struct *vma)
-{
-       u32 *count = (u32 *)vma->vm_private_data;
-       if (!count) {
-               ehca_gen_err("Invalid vma struct vm_start=%lx vm_end=%lx",
-                            vma->vm_start, vma->vm_end);
-               return;
-       }
-       (*count)--;
-       ehca_gen_dbg("vm_start=%lx vm_end=%lx count=%x",
-                    vma->vm_start, vma->vm_end, *count);
-}
-
-static const struct vm_operations_struct vm_ops = {
-       .open = ehca_mm_open,
-       .close = ehca_mm_close,
-};
-
-static int ehca_mmap_fw(struct vm_area_struct *vma, struct h_galpas *galpas,
-                       u32 *mm_count)
-{
-       int ret;
-       u64 vsize, physical;
-
-       vsize = vma->vm_end - vma->vm_start;
-       if (vsize < EHCA_PAGESIZE) {
-               ehca_gen_err("invalid vsize=%lx", vma->vm_end - vma->vm_start);
-               return -EINVAL;
-       }
-
-       physical = galpas->user.fw_handle;
-       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-       ehca_gen_dbg("vsize=%llx physical=%llx", vsize, physical);
-       /* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */
-       ret = remap_4k_pfn(vma, vma->vm_start, physical >> EHCA_PAGESHIFT,
-                          vma->vm_page_prot);
-       if (unlikely(ret)) {
-               ehca_gen_err("remap_pfn_range() failed ret=%i", ret);
-               return -ENOMEM;
-       }
-
-       vma->vm_private_data = mm_count;
-       (*mm_count)++;
-       vma->vm_ops = &vm_ops;
-
-       return 0;
-}
-
-static int ehca_mmap_queue(struct vm_area_struct *vma, struct ipz_queue *queue,
-                          u32 *mm_count)
-{
-       int ret;
-       u64 start, ofs;
-       struct page *page;
-
-       vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
-       start = vma->vm_start;
-       for (ofs = 0; ofs < queue->queue_length; ofs += PAGE_SIZE) {
-               u64 virt_addr = (u64)ipz_qeit_calc(queue, ofs);
-               page = virt_to_page(virt_addr);
-               ret = vm_insert_page(vma, start, page);
-               if (unlikely(ret)) {
-                       ehca_gen_err("vm_insert_page() failed rc=%i", ret);
-                       return ret;
-               }
-               start += PAGE_SIZE;
-       }
-       vma->vm_private_data = mm_count;
-       (*mm_count)++;
-       vma->vm_ops = &vm_ops;
-
-       return 0;
-}
-
-static int ehca_mmap_cq(struct vm_area_struct *vma, struct ehca_cq *cq,
-                       u32 rsrc_type)
-{
-       int ret;
-
-       switch (rsrc_type) {
-       case 0: /* galpa fw handle */
-               ehca_dbg(cq->ib_cq.device, "cq_num=%x fw", cq->cq_number);
-               ret = ehca_mmap_fw(vma, &cq->galpas, &cq->mm_count_galpa);
-               if (unlikely(ret)) {
-                       ehca_err(cq->ib_cq.device,
-                                "ehca_mmap_fw() failed rc=%i cq_num=%x",
-                                ret, cq->cq_number);
-                       return ret;
-               }
-               break;
-
-       case 1: /* cq queue_addr */
-               ehca_dbg(cq->ib_cq.device, "cq_num=%x queue", cq->cq_number);
-               ret = ehca_mmap_queue(vma, &cq->ipz_queue, &cq->mm_count_queue);
-               if (unlikely(ret)) {
-                       ehca_err(cq->ib_cq.device,
-                                "ehca_mmap_queue() failed rc=%i cq_num=%x",
-                                ret, cq->cq_number);
-                       return ret;
-               }
-               break;
-
-       default:
-               ehca_err(cq->ib_cq.device, "bad resource type=%x cq_num=%x",
-                        rsrc_type, cq->cq_number);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int ehca_mmap_qp(struct vm_area_struct *vma, struct ehca_qp *qp,
-                       u32 rsrc_type)
-{
-       int ret;
-
-       switch (rsrc_type) {
-       case 0: /* galpa fw handle */
-               ehca_dbg(qp->ib_qp.device, "qp_num=%x fw", qp->ib_qp.qp_num);
-               ret = ehca_mmap_fw(vma, &qp->galpas, &qp->mm_count_galpa);
-               if (unlikely(ret)) {
-                       ehca_err(qp->ib_qp.device,
-                                "remap_pfn_range() failed ret=%i qp_num=%x",
-                                ret, qp->ib_qp.qp_num);
-                       return -ENOMEM;
-               }
-               break;
-
-       case 1: /* qp rqueue_addr */
-               ehca_dbg(qp->ib_qp.device, "qp_num=%x rq", qp->ib_qp.qp_num);
-               ret = ehca_mmap_queue(vma, &qp->ipz_rqueue,
-                                     &qp->mm_count_rqueue);
-               if (unlikely(ret)) {
-                       ehca_err(qp->ib_qp.device,
-                                "ehca_mmap_queue(rq) failed rc=%i qp_num=%x",
-                                ret, qp->ib_qp.qp_num);
-                       return ret;
-               }
-               break;
-
-       case 2: /* qp squeue_addr */
-               ehca_dbg(qp->ib_qp.device, "qp_num=%x sq", qp->ib_qp.qp_num);
-               ret = ehca_mmap_queue(vma, &qp->ipz_squeue,
-                                     &qp->mm_count_squeue);
-               if (unlikely(ret)) {
-                       ehca_err(qp->ib_qp.device,
-                                "ehca_mmap_queue(sq) failed rc=%i qp_num=%x",
-                                ret, qp->ib_qp.qp_num);
-                       return ret;
-               }
-               break;
-
-       default:
-               ehca_err(qp->ib_qp.device, "bad resource type=%x qp=num=%x",
-                        rsrc_type, qp->ib_qp.qp_num);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
-{
-       u64 fileoffset = vma->vm_pgoff;
-       u32 idr_handle = fileoffset & 0x1FFFFFF;
-       u32 q_type = (fileoffset >> 27) & 0x1;    /* CQ, QP,...        */
-       u32 rsrc_type = (fileoffset >> 25) & 0x3; /* sq,rq,cmnd_window */
-       u32 ret;
-       struct ehca_cq *cq;
-       struct ehca_qp *qp;
-       struct ib_uobject *uobject;
-
-       switch (q_type) {
-       case  0: /* CQ */
-               read_lock(&ehca_cq_idr_lock);
-               cq = idr_find(&ehca_cq_idr, idr_handle);
-               read_unlock(&ehca_cq_idr_lock);
-
-               /* make sure this mmap really belongs to the authorized user */
-               if (!cq)
-                       return -EINVAL;
-
-               if (!cq->ib_cq.uobject || cq->ib_cq.uobject->context != context)
-                       return -EINVAL;
-
-               ret = ehca_mmap_cq(vma, cq, rsrc_type);
-               if (unlikely(ret)) {
-                       ehca_err(cq->ib_cq.device,
-                                "ehca_mmap_cq() failed rc=%i cq_num=%x",
-                                ret, cq->cq_number);
-                       return ret;
-               }
-               break;
-
-       case 1: /* QP */
-               read_lock(&ehca_qp_idr_lock);
-               qp = idr_find(&ehca_qp_idr, idr_handle);
-               read_unlock(&ehca_qp_idr_lock);
-
-               /* make sure this mmap really belongs to the authorized user */
-               if (!qp)
-                       return -EINVAL;
-
-               uobject = IS_SRQ(qp) ? qp->ib_srq.uobject : qp->ib_qp.uobject;
-               if (!uobject || uobject->context != context)
-                       return -EINVAL;
-
-               ret = ehca_mmap_qp(vma, qp, rsrc_type);
-               if (unlikely(ret)) {
-                       ehca_err(qp->ib_qp.device,
-                                "ehca_mmap_qp() failed rc=%i qp_num=%x",
-                                ret, qp->ib_qp.qp_num);
-                       return ret;
-               }
-               break;
-
-       default:
-               ehca_gen_err("bad queue type %x", q_type);
-               return -EINVAL;
-       }
-
-       return 0;
-}
diff --git a/drivers/infiniband/hw/ehca/hcp_if.c b/drivers/infiniband/hw/ehca/hcp_if.c
deleted file mode 100644 (file)
index 89517ff..0000000
+++ /dev/null
@@ -1,949 +0,0 @@
-/*
- *  IBM eServer eHCA Infiniband device driver for Linux on POWER
- *
- *  Firmware Infiniband Interface code for POWER
- *
- *  Authors: Christoph Raisch <raisch@de.ibm.com>
- *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
- *           Joachim Fenkes <fenkes@de.ibm.com>
- *           Gerd Bayer <gerd.bayer@de.ibm.com>
- *           Waleri Fomin <fomin@de.ibm.com>
- *
- *  Copyright (c) 2005 IBM Corporation
- *
- *  All rights reserved.
- *
- *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
- *  BSD.
- *
- * OpenIB BSD License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <asm/hvcall.h>
-#include "ehca_tools.h"
-#include "hcp_if.h"
-#include "hcp_phyp.h"
-#include "hipz_fns.h"
-#include "ipz_pt_fn.h"
-
-#define H_ALL_RES_QP_ENHANCED_OPS       EHCA_BMASK_IBM(9, 11)
-#define H_ALL_RES_QP_PTE_PIN            EHCA_BMASK_IBM(12, 12)
-#define H_ALL_RES_QP_SERVICE_TYPE       EHCA_BMASK_IBM(13, 15)
-#define H_ALL_RES_QP_STORAGE            EHCA_BMASK_IBM(16, 17)
-#define H_ALL_RES_QP_LL_RQ_CQE_POSTING  EHCA_BMASK_IBM(18, 18)
-#define H_ALL_RES_QP_LL_SQ_CQE_POSTING  EHCA_BMASK_IBM(19, 21)
-#define H_ALL_RES_QP_SIGNALING_TYPE     EHCA_BMASK_IBM(22, 23)
-#define H_ALL_RES_QP_UD_AV_LKEY_CTRL    EHCA_BMASK_IBM(31, 31)
-#define H_ALL_RES_QP_SMALL_SQ_PAGE_SIZE EHCA_BMASK_IBM(32, 35)
-#define H_ALL_RES_QP_SMALL_RQ_PAGE_SIZE EHCA_BMASK_IBM(36, 39)
-#define H_ALL_RES_QP_RESOURCE_TYPE      EHCA_BMASK_IBM(56, 63)
-
-#define H_ALL_RES_QP_MAX_OUTST_SEND_WR  EHCA_BMASK_IBM(0, 15)
-#define H_ALL_RES_QP_MAX_OUTST_RECV_WR  EHCA_BMASK_IBM(16, 31)
-#define H_ALL_RES_QP_MAX_SEND_SGE       EHCA_BMASK_IBM(32, 39)
-#define H_ALL_RES_QP_MAX_RECV_SGE       EHCA_BMASK_IBM(40, 47)
-
-#define H_ALL_RES_QP_UD_AV_LKEY         EHCA_BMASK_IBM(32, 63)
-#define H_ALL_RES_QP_SRQ_QP_TOKEN       EHCA_BMASK_IBM(0, 31)
-#define H_ALL_RES_QP_SRQ_QP_HANDLE      EHCA_BMASK_IBM(0, 64)
-#define H_ALL_RES_QP_SRQ_LIMIT          EHCA_BMASK_IBM(48, 63)
-#define H_ALL_RES_QP_SRQ_QPN            EHCA_BMASK_IBM(40, 63)
-
-#define H_ALL_RES_QP_ACT_OUTST_SEND_WR  EHCA_BMASK_IBM(16, 31)
-#define H_ALL_RES_QP_ACT_OUTST_RECV_WR  EHCA_BMASK_IBM(48, 63)
-#define H_ALL_RES_QP_ACT_SEND_SGE       EHCA_BMASK_IBM(8, 15)
-#define H_ALL_RES_QP_ACT_RECV_SGE       EHCA_BMASK_IBM(24, 31)
-
-#define H_ALL_RES_QP_SQUEUE_SIZE_PAGES  EHCA_BMASK_IBM(0, 31)
-#define H_ALL_RES_QP_RQUEUE_SIZE_PAGES  EHCA_BMASK_IBM(32, 63)
-
-#define H_MP_INIT_TYPE                  EHCA_BMASK_IBM(44, 47)
-#define H_MP_SHUTDOWN                   EHCA_BMASK_IBM(48, 48)
-#define H_MP_RESET_QKEY_CTR             EHCA_BMASK_IBM(49, 49)
-
-#define HCALL4_REGS_FORMAT "r4=%lx r5=%lx r6=%lx r7=%lx"
-#define HCALL7_REGS_FORMAT HCALL4_REGS_FORMAT " r8=%lx r9=%lx r10=%lx"
-#define HCALL9_REGS_FORMAT HCALL7_REGS_FORMAT " r11=%lx r12=%lx"
-
-static DEFINE_SPINLOCK(hcall_lock);
-
-static long ehca_plpar_hcall_norets(unsigned long opcode,
-                                   unsigned long arg1,
-                                   unsigned long arg2,
-                                   unsigned long arg3,
-                                   unsigned long arg4,
-                                   unsigned long arg5,
-                                   unsigned long arg6,
-                                   unsigned long arg7)
-{
-       long ret;
-       int i, sleep_msecs;
-       unsigned long flags = 0;
-
-       if (unlikely(ehca_debug_level >= 2))
-               ehca_gen_dbg("opcode=%lx " HCALL7_REGS_FORMAT,
-                            opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
-
-       for (i = 0; i < 5; i++) {
-               /* serialize hCalls to work around firmware issue */
-               if (ehca_lock_hcalls)
-                       spin_lock_irqsave(&hcall_lock, flags);
-
-               ret = plpar_hcall_norets(opcode, arg1, arg2, arg3, arg4,
-                                        arg5, arg6, arg7);
-
-               if (ehca_lock_hcalls)
-                       spin_unlock_irqrestore(&hcall_lock, flags);
-
-               if (H_IS_LONG_BUSY(ret)) {
-                       sleep_msecs = get_longbusy_msecs(ret);
-                       msleep_interruptible(sleep_msecs);
-                       continue;
-               }
-
-               if (ret < H_SUCCESS)
-                       ehca_gen_err("opcode=%lx ret=%li " HCALL7_REGS_FORMAT,
-                                    opcode, ret, arg1, arg2, arg3,
-                                    arg4, arg5, arg6, arg7);
-               else
-                       if (unlikely(ehca_debug_level >= 2))
-                               ehca_gen_dbg("opcode=%lx ret=%li", opcode, ret);
-
-               return ret;
-       }
-
-       return H_BUSY;
-}
-
-static long ehca_plpar_hcall9(unsigned long opcode,
-                             unsigned long *outs, /* array of 9 outputs */
-                             unsigned long arg1,
-                             unsigned long arg2,
-                             unsigned long arg3,
-                             unsigned long arg4,
-                             unsigned long arg5,
-                             unsigned long arg6,
-                             unsigned long arg7,
-                             unsigned long arg8,
-                             unsigned long arg9)
-{
-       long ret;
-       int i, sleep_msecs;
-       unsigned long flags = 0;
-
-       if (unlikely(ehca_debug_level >= 2))
-               ehca_gen_dbg("INPUT -- opcode=%lx " HCALL9_REGS_FORMAT, opcode,
-                            arg1, arg2, arg3, arg4, arg5,
-                            arg6, arg7, arg8, arg9);
-
-       for (i = 0; i < 5; i++) {
-               /* serialize hCalls to work around firmware issue */
-               if (ehca_lock_hcalls)
-                       spin_lock_irqsave(&hcall_lock, flags);
-
-               ret = plpar_hcall9(opcode, outs,
-                                  arg1, arg2, arg3, arg4, arg5,
-                                  arg6, arg7, arg8, arg9);
-
-               if (ehca_lock_hcalls)
-                       spin_unlock_irqrestore(&hcall_lock, flags);
-
-               if (H_IS_LONG_BUSY(ret)) {
-                       sleep_msecs = get_longbusy_msecs(ret);
-                       msleep_interruptible(sleep_msecs);
-                       continue;
-               }
-
-               if (ret < H_SUCCESS) {
-                       ehca_gen_err("INPUT -- opcode=%lx " HCALL9_REGS_FORMAT,
-                                    opcode, arg1, arg2, arg3, arg4, arg5,
-                                    arg6, arg7, arg8, arg9);
-                       ehca_gen_err("OUTPUT -- ret=%li " HCALL9_REGS_FORMAT,
-                                    ret, outs[0], outs[1], outs[2], outs[3],
-                                    outs[4], outs[5], outs[6], outs[7],
-                                    outs[8]);
-               } else if (unlikely(ehca_debug_level >= 2))
-                       ehca_gen_dbg("OUTPUT -- ret=%li " HCALL9_REGS_FORMAT,
-                                    ret, outs[0], outs[1], outs[2], outs[3],
-                                    outs[4], outs[5], outs[6], outs[7],
-                                    outs[8]);
-               return ret;
-       }
-
-       return H_BUSY;
-}
-
-u64 hipz_h_alloc_resource_eq(const struct ipz_adapter_handle adapter_handle,
-                            struct ehca_pfeq *pfeq,
-                            const u32 neq_control,
-                            const u32 number_of_entries,
-                            struct ipz_eq_handle *eq_handle,
-                            u32 *act_nr_of_entries,
-                            u32 *act_pages,
-                            u32 *eq_ist)
-{
-       u64 ret;
-       unsigned long outs[PLPAR_HCALL9_BUFSIZE];
-       u64 allocate_controls;
-
-       /* resource type */
-       allocate_controls = 3ULL;
-
-       /* ISN is associated */
-       if (neq_control != 1)
-               allocate_controls = (1ULL << (63 - 7)) | allocate_controls;
-       else /* notification event queue */
-               allocate_controls = (1ULL << 63) | allocate_controls;
-
-       ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
-                               adapter_handle.handle,  /* r4 */
-                               allocate_controls,      /* r5 */
-                               number_of_entries,      /* r6 */
-                               0, 0, 0, 0, 0, 0);
-       eq_handle->handle = outs[0];
-       *act_nr_of_entries = (u32)outs[3];
-       *act_pages = (u32)outs[4];
-       *eq_ist = (u32)outs[5];
-
-       if (ret == H_NOT_ENOUGH_RESOURCES)
-               ehca_gen_err("Not enough resource - ret=%lli ", ret);
-
-       return ret;
-}
-
-u64 hipz_h_reset_event(const struct ipz_adapter_handle adapter_handle,
-                      struct ipz_eq_handle eq_handle,
-                      const u64 event_mask)
-{
-       return ehca_plpar_hcall_norets(H_RESET_EVENTS,
-                                      adapter_handle.handle, /* r4 */
-                                      eq_handle.handle,      /* r5 */
-                                      event_mask,            /* r6 */
-                                      0, 0, 0, 0);
-}
-
-u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle,
-                            struct ehca_cq *cq,
-                            struct ehca_alloc_cq_parms *param)
-{
-       int rc;
-       u64 ret;
-       unsigned long outs[PLPAR_HCALL9_BUFSIZE];
-
-       ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
-                               adapter_handle.handle,   /* r4  */
-                               2,                       /* r5  */
-                               param->eq_handle.handle, /* r6  */
-                               cq->token,               /* r7  */
-                               param->nr_cqe,           /* r8  */
-                               0, 0, 0, 0);
-       cq->ipz_cq_handle.handle = outs[0];
-       param->act_nr_of_entries = (u32)outs[3];
-       param->act_pages = (u32)outs[4];
-
-       if (ret == H_SUCCESS) {
-               rc = hcp_galpas_ctor(&cq->galpas, 0, outs[5], outs[6]);
-               if (rc) {
-                       ehca_gen_err("Could not establish HW access. rc=%d paddr=%#lx",
-                                    rc, outs[5]);
-
-                       ehca_plpar_hcall_norets(H_FREE_RESOURCE,
-                                               adapter_handle.handle,     /* r4 */
-                                               cq->ipz_cq_handle.handle,  /* r5 */
-                                               0, 0, 0, 0, 0);
-                       ret = H_NO_MEM;
-               }
-       }
-
-       if (ret == H_NOT_ENOUGH_RESOURCES)
-               ehca_gen_err("Not enough resources. ret=%lli", ret);
-
-       return ret;
-}
-
-u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle,
-                            struct ehca_alloc_qp_parms *parms, int is_user)
-{
-       int rc;
-       u64 ret;
-       u64 allocate_controls, max_r10_reg, r11, r12;
-       unsigned long outs[PLPAR_HCALL9_BUFSIZE];
-
-       allocate_controls =
-               EHCA_BMASK_SET(H_ALL_RES_QP_ENHANCED_OPS, parms->ext_type)
-               | EHCA_BMASK_SET(H_ALL_RES_QP_PTE_PIN, 0)
-               | EHCA_BMASK_SET(H_ALL_RES_QP_SERVICE_TYPE, parms->servicetype)
-               | EHCA_BMASK_SET(H_ALL_RES_QP_SIGNALING_TYPE, parms->sigtype)
-               | EHCA_BMASK_SET(H_ALL_RES_QP_STORAGE, parms->qp_storage)
-               | EHCA_BMASK_SET(H_ALL_RES_QP_SMALL_SQ_PAGE_SIZE,
-                                parms->squeue.page_size)
-               | EHCA_BMASK_SET(H_ALL_RES_QP_SMALL_RQ_PAGE_SIZE,
-                                parms->rqueue.page_size)
-               | EHCA_BMASK_SET(H_ALL_RES_QP_LL_RQ_CQE_POSTING,
-                                !!(parms->ll_comp_flags & LLQP_RECV_COMP))
-               | EHCA_BMASK_SET(H_ALL_RES_QP_LL_SQ_CQE_POSTING,
-                                !!(parms->ll_comp_flags & LLQP_SEND_COMP))
-               | EHCA_BMASK_SET(H_ALL_RES_QP_UD_AV_LKEY_CTRL,
-                                parms->ud_av_l_key_ctl)
-               | EHCA_BMASK_SET(H_ALL_RES_QP_RESOURCE_TYPE, 1);
-
-       max_r10_reg =
-               EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_SEND_WR,
-                              parms->squeue.max_wr + 1)
-               | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_RECV_WR,
-                                parms->rqueue.max_wr + 1)
-               | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_SEND_SGE,
-                                parms->squeue.max_sge)
-               | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_RECV_SGE,
-                                parms->rqueue.max_sge);
-
-       r11 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_QP_TOKEN, parms->srq_token);
-
-       if (parms->ext_type == EQPT_SRQ)
-               r12 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_LIMIT, parms->srq_limit);
-       else
-               r12 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_QPN, parms->srq_qpn);
-
-       ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
-                               adapter_handle.handle,             /* r4  */
-                               allocate_controls,                 /* r5  */
-                               parms->send_cq_handle.handle,
-                               parms->recv_cq_handle.handle,
-                               parms->eq_handle.handle,
-                               ((u64)parms->token << 32) | parms->pd.value,
-                               max_r10_reg, r11, r12);
-
-       parms->qp_handle.handle = outs[0];
-       parms->real_qp_num = (u32)outs[1];
-       parms->squeue.act_nr_wqes =
-               (u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_SEND_WR, outs[2]);
-       parms->rqueue.act_nr_wqes =
-               (u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_RECV_WR, outs[2]);
-       parms->squeue.act_nr_sges =
-               (u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_SEND_SGE, outs[3]);
-       parms->rqueue.act_nr_sges =
-               (u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_RECV_SGE, outs[3]);
-       parms->squeue.queue_size =
-               (u32)EHCA_BMASK_GET(H_ALL_RES_QP_SQUEUE_SIZE_PAGES, outs[4]);
-       parms->rqueue.queue_size =
-               (u32)EHCA_BMASK_GET(H_ALL_RES_QP_RQUEUE_SIZE_PAGES, outs[4]);
-
-       if (ret == H_SUCCESS) {
-               rc = hcp_galpas_ctor(&parms->galpas, is_user, outs[6], outs[6]);
-               if (rc) {
-                       ehca_gen_err("Could not establish HW access. rc=%d paddr=%#lx",
-                                    rc, outs[6]);
-
-                       ehca_plpar_hcall_norets(H_FREE_RESOURCE,
-                                               adapter_handle.handle,     /* r4 */
-                                               parms->qp_handle.handle,  /* r5 */
-                                               0, 0, 0, 0, 0);
-                       ret = H_NO_MEM;
-               }
-       }
-
-       if (ret == H_NOT_ENOUGH_RESOURCES)
-               ehca_gen_err("Not enough resources. ret=%lli", ret);
-
-       return ret;
-}
-
-u64 hipz_h_query_port(const struct ipz_adapter_handle adapter_handle,
-                     const u8 port_id,
-                     struct hipz_query_port *query_port_response_block)
-{
-       u64 ret;
-       u64 r_cb = __pa(query_port_response_block);
-
-       if (r_cb & (EHCA_PAGESIZE-1)) {
-               ehca_gen_err("response block not page aligned");
-               return H_PARAMETER;
-       }
-
-       ret = ehca_plpar_hcall_norets(H_QUERY_PORT,
-                                     adapter_handle.handle, /* r4 */
-                                     port_id,               /* r5 */
-                                     r_cb,                  /* r6 */
-                                     0, 0, 0, 0);
-
-       if (ehca_debug_level >= 2)
-               ehca_dmp(query_port_response_block, 64, "response_block");
-
-       return ret;
-}
-
-u64 hipz_h_modify_port(const struct ipz_adapter_handle adapter_handle,
-                      const u8 port_id, const u32 port_cap,
-                      const u8 init_type, const int modify_mask)
-{
-       u64 port_attributes = port_cap;
-
-       if (modify_mask & IB_PORT_SHUTDOWN)
-               port_attributes |= EHCA_BMASK_SET(H_MP_SHUTDOWN, 1);
-       if (modify_mask & IB_PORT_INIT_TYPE)
-               port_attributes |= EHCA_BMASK_SET(H_MP_INIT_TYPE, init_type);
-       if (modify_mask & IB_PORT_RESET_QKEY_CNTR)
-               port_attributes |= EHCA_BMASK_SET(H_MP_RESET_QKEY_CTR, 1);
-
-       return ehca_plpar_hcall_norets(H_MODIFY_PORT,
-                                      adapter_handle.handle, /* r4 */
-                                      port_id,               /* r5 */
-                                      port_attributes,       /* r6 */
-                                      0, 0, 0, 0);
-}
-
-u64 hipz_h_query_hca(const struct ipz_adapter_handle adapter_handle,
-                    struct hipz_query_hca *query_hca_rblock)
-{
-       u64 r_cb = __pa(query_hca_rblock);
-
-       if (r_cb & (EHCA_PAGESIZE-1)) {
-               ehca_gen_err("response_block=%p not page aligned",
-                            query_hca_rblock);
-               return H_PARAMETER;
-       }
-
-       return ehca_plpar_hcall_norets(H_QUERY_HCA,
-                                      adapter_handle.handle, /* r4 */
-                                      r_cb,                  /* r5 */
-                                      0, 0, 0, 0, 0);
-}
-
-u64 hipz_h_register_rpage(const struct ipz_adapter_handle adapter_handle,
-                         const u8 pagesize,
-                         const u8 queue_type,
-                         const u64 resource_handle,
-                         const u64 logical_address_of_page,
-                         u64 count)
-{
-       return ehca_plpar_hcall_norets(H_REGISTER_RPAGES,
-                                      adapter_handle.handle,      /* r4  */
-                                      (u64)queue_type | ((u64)pagesize) << 8,
-                                      /* r5  */
-                                      resource_handle,            /* r6  */
-                                      logical_address_of_page,    /* r7  */
-                                      count,                      /* r8  */
-                                      0, 0);
-}
-
-u64 hipz_h_register_rpage_eq(const struct ipz_adapter_handle adapter_handle,
-                            const struct ipz_eq_handle eq_handle,
-                            struct ehca_pfeq *pfeq,
-                            const u8 pagesize,
-                            const u8 queue_type,
-                            const u64 logical_address_of_page,
-                            const u64 count)
-{
-       if (count != 1) {
-               ehca_gen_err("Ppage counter=%llx", count);
-               return H_PARAMETER;
-       }
-       return hipz_h_register_rpage(adapter_handle,
-                                    pagesize,
-                                    queue_type,
-                                    eq_handle.handle,
-                                    logical_address_of_page, count);
-}
-
-u64 hipz_h_query_int_state(const struct ipz_adapter_handle adapter_handle,
-                          u32 ist)
-{
-       u64 ret;
-       ret = ehca_plpar_hcall_norets(H_QUERY_INT_STATE,
-                                     adapter_handle.handle, /* r4 */
-                                     ist,                   /* r5 */
-                                     0, 0, 0, 0, 0);
-
-       if (ret != H_SUCCESS && ret != H_BUSY)
-               ehca_gen_err("Could not query interrupt state.");
-
-       return ret;
-}
-
-u64 hipz_h_register_rpage_cq(const struct ipz_adapter_handle adapter_handle,
-                            const struct ipz_cq_handle cq_handle,
-                            struct ehca_pfcq *pfcq,
-                            const u8 pagesize,
-                            const u8 queue_type,
-                            const u64 logical_address_of_page,
-                            const u64 count,
-                            const struct h_galpa gal)
-{
-       if (count != 1) {
-               ehca_gen_err("Page counter=%llx", count);
-               return H_PARAMETER;
-       }
-
-       return hipz_h_register_rpage(adapter_handle, pagesize, queue_type,
-                                    cq_handle.handle, logical_address_of_page,
-                                    count);
-}
-
-u64 hipz_h_register_rpage_qp(const struct ipz_adapter_handle adapter_handle,
-                            const struct ipz_qp_handle qp_handle,
-                            struct ehca_pfqp *pfqp,
-                            const u8 pagesize,
-                            const u8 queue_type,
-                            const u64 logical_address_of_page,
-                            const u64 count,
-                            const struct h_galpa galpa)
-{
-       if (count > 1) {
-               ehca_gen_err("Page counter=%llx", count);
-               return H_PARAMETER;
-       }
-
-       return hipz_h_register_rpage(adapter_handle, pagesize, queue_type,
-                                    qp_handle.handle, logical_address_of_page,
-                                    count);
-}
-
-u64 hipz_h_disable_and_get_wqe(const struct ipz_adapter_handle adapter_handle,
-                              const struct ipz_qp_handle qp_handle,
-                              struct ehca_pfqp *pfqp,
-                              void **log_addr_next_sq_wqe2processed,
-                              void **log_addr_next_rq_wqe2processed,
-                              int dis_and_get_function_code)
-{
-       u64 ret;
-       unsigned long outs[PLPAR_HCALL9_BUFSIZE];
-
-       ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs,
-                               adapter_handle.handle,     /* r4 */
-                               dis_and_get_function_code, /* r5 */
-                               qp_handle.handle,          /* r6 */
-                               0, 0, 0, 0, 0, 0);
-       if (log_addr_next_sq_wqe2processed)
-               *log_addr_next_sq_wqe2processed = (void *)outs[0];
-       if (log_addr_next_rq_wqe2processed)
-               *log_addr_next_rq_wqe2processed = (void *)outs[1];
-
-       return ret;
-}
-
-u64 hipz_h_modify_qp(const struct ipz_adapter_handle adapter_handle,
-                    const struct ipz_qp_handle qp_handle,
-                    struct ehca_pfqp *pfqp,
-                    const u64 update_mask,
-                    struct hcp_modify_qp_control_block *mqpcb,
-                    struct h_galpa gal)
-{
-       u64 ret;
-       unsigned long outs[PLPAR_HCALL9_BUFSIZE];
-       ret = ehca_plpar_hcall9(H_MODIFY_QP, outs,
-                               adapter_handle.handle, /* r4 */
-                               qp_handle.handle,      /* r5 */
-                               update_mask,           /* r6 */
-                               __pa(mqpcb),           /* r7 */
-                               0, 0, 0, 0, 0);
-
-       if (ret == H_NOT_ENOUGH_RESOURCES)
-               ehca_gen_err("Insufficient resources ret=%lli", ret);
-
-       return ret;
-}
-
-u64 hipz_h_query_qp(const struct ipz_adapter_handle adapter_handle,
-                   const struct ipz_qp_handle qp_handle,
-                   struct ehca_pfqp *pfqp,
-                   struct hcp_modify_qp_control_block *qqpcb,
-                   struct h_galpa gal)
-{
-       return ehca_plpar_hcall_norets(H_QUERY_QP,
-                                      adapter_handle.handle, /* r4 */
-                                      qp_handle.handle,      /* r5 */
-                                      __pa(qqpcb),           /* r6 */
-                                      0, 0, 0, 0);
-}
-
-u64 hipz_h_destroy_qp(const struct ipz_adapter_handle adapter_handle,
-                     struct ehca_qp *qp)
-{
-       u64 ret;
-       unsigned long outs[PLPAR_HCALL9_BUFSIZE];
-
-       ret = hcp_galpas_dtor(&qp->galpas);
-       if (ret) {
-               ehca_gen_err("Could not destruct qp->galpas");
-               return H_RESOURCE;
-       }
-       ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs,
-                               adapter_handle.handle,     /* r4 */
-                               /* function code */
-                               1,                         /* r5 */
-                               qp->ipz_qp_handle.handle,  /* r6 */
-                               0, 0, 0, 0, 0, 0);
-       if (ret == H_HARDWARE)
-               ehca_gen_err("HCA not operational. ret=%lli", ret);
-
-       ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
-                                     adapter_handle.handle,     /* r4 */
-                                     qp->ipz_qp_handle.handle,  /* r5 */
-                                     0, 0, 0, 0, 0);
-
-       if (ret == H_RESOURCE)
-               ehca_gen_err("Resource still in use. ret=%lli", ret);
-
-       return ret;
-}
-
-u64 hipz_h_define_aqp0(const struct ipz_adapter_handle adapter_handle,
-                      const struct ipz_qp_handle qp_handle,
-                      struct h_galpa gal,
-                      u32 port)
-{
-       return ehca_plpar_hcall_norets(H_DEFINE_AQP0,
-                                      adapter_handle.handle, /* r4 */
-                                      qp_handle.handle,      /* r5 */
-                                      port,                  /* r6 */
-                                      0, 0, 0, 0);
-}
-
-u64 hipz_h_define_aqp1(const struct ipz_adapter_handle adapter_handle,
-                      const struct ipz_qp_handle qp_handle,
-                      struct h_galpa gal,
-                      u32 port, u32 * pma_qp_nr,
-                      u32 * bma_qp_nr)
-{
-       u64 ret;
-       unsigned long outs[PLPAR_HCALL9_BUFSIZE];
-
-       ret = ehca_plpar_hcall9(H_DEFINE_AQP1, outs,
-                               adapter_handle.handle, /* r4 */
-                               qp_handle.handle,      /* r5 */
-                               port,                  /* r6 */
-                               0, 0, 0, 0, 0, 0);
-       *pma_qp_nr = (u32)outs[0];
-       *bma_qp_nr = (u32)outs[1];
-
-       if (ret == H_ALIAS_EXIST)
-               ehca_gen_err("AQP1 already exists. ret=%lli", ret);
-
-       return ret;
-}
-
-u64 hipz_h_attach_mcqp(const struct ipz_adapter_handle adapter_handle,
-                      const struct ipz_qp_handle qp_handle,
-                      struct h_galpa gal,
-                      u16 mcg_dlid,
-                      u64 subnet_prefix, u64 interface_id)
-{
-       u64 ret;
-
-       ret = ehca_plpar_hcall_norets(H_ATTACH_MCQP,
-                                     adapter_handle.handle,  /* r4 */
-                                     qp_handle.handle,       /* r5 */
-                                     mcg_dlid,               /* r6 */
-                                     interface_id,           /* r7 */
-                                     subnet_prefix,          /* r8 */
-                                     0, 0);
-
-       if (ret == H_NOT_ENOUGH_RESOURCES)
-               ehca_gen_err("Not enough resources. ret=%lli", ret);
-
-       return ret;
-}
-
-u64 hipz_h_detach_mcqp(const struct ipz_adapter_handle adapter_handle,
-                      const struct ipz_qp_handle qp_handle,
-                      struct h_galpa gal,
-                      u16 mcg_dlid,
-                      u64 subnet_prefix, u64 interface_id)
-{
-       return ehca_plpar_hcall_norets(H_DETACH_MCQP,
-                                      adapter_handle.handle, /* r4 */
-                                      qp_handle.handle,      /* r5 */
-                                      mcg_dlid,              /* r6 */
-                                      interface_id,          /* r7 */
-                                      subnet_prefix,         /* r8 */
-                                      0, 0);
-}
-
-u64 hipz_h_destroy_cq(const struct ipz_adapter_handle adapter_handle,
-                     struct ehca_cq *cq,
-                     u8 force_flag)
-{
-       u64 ret;
-
-       ret = hcp_galpas_dtor(&cq->galpas);
-       if (ret) {
-               ehca_gen_err("Could not destruct cp->galpas");
-               return H_RESOURCE;
-       }
-
-       ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
-                                     adapter_handle.handle,     /* r4 */
-                                     cq->ipz_cq_handle.handle,  /* r5 */
-                                     force_flag != 0 ? 1L : 0L, /* r6 */
-                                     0, 0, 0, 0);
-
-       if (ret == H_RESOURCE)
-               ehca_gen_err("H_FREE_RESOURCE failed ret=%lli ", ret);
-
-       return ret;
-}
-
-u64 hipz_h_destroy_eq(const struct ipz_adapter_handle adapter_handle,
-                     struct ehca_eq *eq)
-{
-       u64 ret;
-
-       ret = hcp_galpas_dtor(&eq->galpas);
-       if (ret) {
-               ehca_gen_err("Could not destruct eq->galpas");
-               return H_RESOURCE;
-       }
-
-       ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
-                                     adapter_handle.handle,     /* r4 */
-                                     eq->ipz_eq_handle.handle,  /* r5 */
-                                     0, 0, 0, 0, 0);
-
-       if (ret == H_RESOURCE)
-               ehca_gen_err("Resource in use. ret=%lli ", ret);
-
-       return ret;
-}
-
-u64 hipz_h_alloc_resource_mr(const struct ipz_adapter_handle adapter_handle,
-                            const struct ehca_mr *mr,
-                            const u64 vaddr,
-                            const u64 length,
-                            const u32 access_ctrl,
-                            const struct ipz_pd pd,
-                            struct ehca_mr_hipzout_parms *outparms)
-{
-       u64 ret;
-       unsigned long outs[PLPAR_HCALL9_BUFSIZE];
-
-       ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
-                               adapter_handle.handle,            /* r4 */
-                               5,                                /* r5 */
-                               vaddr,                            /* r6 */
-                               length,                           /* r7 */
-                               (((u64)access_ctrl) << 32ULL),    /* r8 */
-                               pd.value,                         /* r9 */
-                               0, 0, 0);
-       outparms->handle.handle = outs[0];
-       outparms->lkey = (u32)outs[2];
-       outparms->rkey = (u32)outs[3];
-
-       return ret;
-}
-
-u64 hipz_h_register_rpage_mr(const struct ipz_adapter_handle adapter_handle,
-                            const struct ehca_mr *mr,
-                            const u8 pagesize,
-                            const u8 queue_type,
-                            const u64 logical_address_of_page,
-                            const u64 count)
-{
-       u64 ret;
-
-       if (unlikely(ehca_debug_level >= 3)) {
-               if (count > 1) {
-                       u64 *kpage;
-                       int i;
-                       kpage = __va(logical_address_of_page);
-                       for (i = 0; i < count; i++)
-                               ehca_gen_dbg("kpage[%d]=%p",
-                                            i, (void *)kpage[i]);
-               } else
-                       ehca_gen_dbg("kpage=%p",
-                                    (void *)logical_address_of_page);
-       }
-
-       if ((count > 1) && (logical_address_of_page & (EHCA_PAGESIZE-1))) {
-               ehca_gen_err("logical_address_of_page not on a 4k boundary "
-                            "adapter_handle=%llx mr=%p mr_handle=%llx "
-                            "pagesize=%x queue_type=%x "
-                            "logical_address_of_page=%llx count=%llx",
-                            adapter_handle.handle, mr,
-                            mr->ipz_mr_handle.handle, pagesize, queue_type,
-                            logical_address_of_page, count);
-               ret = H_PARAMETER;
-       } else
-               ret = hipz_h_register_rpage(adapter_handle, pagesize,
-                                           queue_type,
-                                           mr->ipz_mr_handle.handle,
-                                           logical_address_of_page, count);
-       return ret;
-}
-
-u64 hipz_h_query_mr(const struct ipz_adapter_handle adapter_handle,
-                   const struct ehca_mr *mr,
-                   struct ehca_mr_hipzout_parms *outparms)
-{
-       u64 ret;
-       unsigned long outs[PLPAR_HCALL9_BUFSIZE];
-
-       ret = ehca_plpar_hcall9(H_QUERY_MR, outs,
-                               adapter_handle.handle,     /* r4 */
-                               mr->ipz_mr_handle.handle,  /* r5 */
-                               0, 0, 0, 0, 0, 0, 0);
-       outparms->len = outs[0];
-       outparms->vaddr = outs[1];
-       outparms->acl  = outs[4] >> 32;
-       outparms->lkey = (u32)(outs[5] >> 32);
-       outparms->rkey = (u32)(outs[5] & (0xffffffff));
-
-       return ret;
-}
-
-u64 hipz_h_free_resource_mr(const struct ipz_adapter_handle adapter_handle,
-                           const struct ehca_mr *mr)
-{
-       return ehca_plpar_hcall_norets(H_FREE_RESOURCE,
-                                      adapter_handle.handle,    /* r4 */
-                                      mr->ipz_mr_handle.handle, /* r5 */
-                                      0, 0, 0, 0, 0);
-}
-
-u64 hipz_h_reregister_pmr(const struct ipz_adapter_handle adapter_handle,
-                         const struct ehca_mr *mr,
-                         const u64 vaddr_in,
-                         const u64 length,
-                         const u32 access_ctrl,
-                         const struct ipz_pd pd,
-                         const u64 mr_addr_cb,
-                         struct ehca_mr_hipzout_parms *outparms)
-{
-       u64 ret;
-       unsigned long outs[PLPAR_HCALL9_BUFSIZE];
-
-       ret = ehca_plpar_hcall9(H_REREGISTER_PMR, outs,
-                               adapter_handle.handle,    /* r4 */
-                               mr->ipz_mr_handle.handle, /* r5 */
-                               vaddr_in,                 /* r6 */
-                               length,                   /* r7 */
-                               /* r8 */
-                               ((((u64)access_ctrl) << 32ULL) | pd.value),
-                               mr_addr_cb,               /* r9 */
-                               0, 0, 0);
-       outparms->vaddr = outs[1];
-       outparms->lkey = (u32)outs[2];
-       outparms->rkey = (u32)outs[3];
-
-       return ret;
-}
-
-u64 hipz_h_register_smr(const struct ipz_adapter_handle adapter_handle,
-                       const struct ehca_mr *mr,
-                       const struct ehca_mr *orig_mr,
-                       const u64 vaddr_in,
-                       const u32 access_ctrl,
-                       const struct ipz_pd pd,
-                       struct ehca_mr_hipzout_parms *outparms)
-{
-       u64 ret;
-       unsigned long outs[PLPAR_HCALL9_BUFSIZE];
-
-       ret = ehca_plpar_hcall9(H_REGISTER_SMR, outs,
-                               adapter_handle.handle,            /* r4 */
-                               orig_mr->ipz_mr_handle.handle,    /* r5 */
-                               vaddr_in,                         /* r6 */
-                               (((u64)access_ctrl) << 32ULL),    /* r7 */
-                               pd.value,                         /* r8 */
-                               0, 0, 0, 0);
-       outparms->handle.handle = outs[0];
-       outparms->lkey = (u32)outs[2];
-       outparms->rkey = (u32)outs[3];
-
-       return ret;
-}
-
-u64 hipz_h_alloc_resource_mw(const struct ipz_adapter_handle adapter_handle,
-                            const struct ehca_mw *mw,
-                            const struct ipz_pd pd,
-                            struct ehca_mw_hipzout_parms *outparms)
-{
-       u64 ret;
-       unsigned long outs[PLPAR_HCALL9_BUFSIZE];
-
-       ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
-                               adapter_handle.handle,      /* r4 */
-                               6,                          /* r5 */
-                               pd.value,                   /* r6 */
-                               0, 0, 0, 0, 0, 0);
-       outparms->handle.handle = outs[0];
-       outparms->rkey = (u32)outs[3];
-
-       return ret;
-}
-
-u64 hipz_h_query_mw(const struct ipz_adapter_handle adapter_handle,
-                   const struct ehca_mw *mw,
-                   struct ehca_mw_hipzout_parms *outparms)
-{
-       u64 ret;
-       unsigned long outs[PLPAR_HCALL9_BUFSIZE];
-
-       ret = ehca_plpar_hcall9(H_QUERY_MW, outs,
-                               adapter_handle.handle,    /* r4 */
-                               mw->ipz_mw_handle.handle, /* r5 */
-                               0, 0, 0, 0, 0, 0, 0);
-       outparms->rkey = (u32)outs[3];
-
-       return ret;
-}
-
-u64 hipz_h_free_resource_mw(const struct ipz_adapter_handle adapter_handle,
-                           const struct ehca_mw *mw)
-{
-       return ehca_plpar_hcall_norets(H_FREE_RESOURCE,
-                                      adapter_handle.handle,    /* r4 */
-                                      mw->ipz_mw_handle.handle, /* r5 */
-                                      0, 0, 0, 0, 0);
-}
-
-u64 hipz_h_error_data(const struct ipz_adapter_handle adapter_handle,
-                     const u64 ressource_handle,
-                     void *rblock,
-                     unsigned long *byte_count)
-{
-       u64 r_cb = __pa(rblock);
-
-       if (r_cb & (EHCA_PAGESIZE-1)) {
-               ehca_gen_err("rblock not page aligned.");
-               return H_PARAMETER;
-       }
-
-       return ehca_plpar_hcall_norets(H_ERROR_DATA,
-                                      adapter_handle.handle,
-                                      ressource_handle,
-                                      r_cb,
-                                      0, 0, 0, 0);
-}
-
-u64 hipz_h_eoi(int irq)
-{
-       unsigned long xirr;
-
-       iosync();
-       xirr = (0xffULL << 24) | irq;
-
-       return plpar_hcall_norets(H_EOI, xirr);
-}
diff --git a/drivers/infiniband/hw/ehca/hcp_if.h b/drivers/infiniband/hw/ehca/hcp_if.h
deleted file mode 100644 (file)
index a46e514..0000000
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- *  IBM eServer eHCA Infiniband device driver for Linux on POWER
- *
- *  Firmware Infiniband Interface code for POWER
- *
- *  Authors: Christoph Raisch <raisch@de.ibm.com>
- *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
- *           Gerd Bayer <gerd.bayer@de.ibm.com>
- *           Waleri Fomin <fomin@de.ibm.com>
- *
- *  Copyright (c) 2005 IBM Corporation
- *
- *  All rights reserved.
- *
- *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
- *  BSD.
- *
- * OpenIB BSD License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __HCP_IF_H__
-#define __HCP_IF_H__
-
-#include "ehca_classes.h"
-#include "ehca_tools.h"
-#include "hipz_hw.h"
-
-/*
- * hipz_h_alloc_resource_eq allocates EQ resources in HW and FW, initialize
- * resources, create the empty EQPT (ring).
- */
-u64 hipz_h_alloc_resource_eq(const struct ipz_adapter_handle adapter_handle,
-                            struct ehca_pfeq *pfeq,
-                            const u32 neq_control,
-                            const u32 number_of_entries,
-                            struct ipz_eq_handle *eq_handle,
-                            u32 * act_nr_of_entries,
-                            u32 * act_pages,
-                            u32 * eq_ist);
-
-u64 hipz_h_reset_event(const struct ipz_adapter_handle adapter_handle,
-                      struct ipz_eq_handle eq_handle,
-                      const u64 event_mask);
-/*
- * hipz_h_allocate_resource_cq allocates CQ resources in HW and FW, initialize
- * resources, create the empty CQPT (ring).
- */
-u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle,
-                            struct ehca_cq *cq,
-                            struct ehca_alloc_cq_parms *param);
-
-
-/*
- * hipz_h_alloc_resource_qp allocates QP resources in HW and FW,
- * initialize resources, create empty QPPTs (2 rings).
- */
-u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle,
-                            struct ehca_alloc_qp_parms *parms, int is_user);
-
-u64 hipz_h_query_port(const struct ipz_adapter_handle adapter_handle,
-                     const u8 port_id,
-                     struct hipz_query_port *query_port_response_block);
-
-u64 hipz_h_modify_port(const struct ipz_adapter_handle adapter_handle,
-                      const u8 port_id, const u32 port_cap,
-                      const u8 init_type, const int modify_mask);
-
-u64 hipz_h_query_hca(const struct ipz_adapter_handle adapter_handle,
-                    struct hipz_query_hca *query_hca_rblock);
-
-/*
- * hipz_h_register_rpage internal function in hcp_if.h for all
- * hcp_H_REGISTER_RPAGE calls.
- */
-u64 hipz_h_register_rpage(const struct ipz_adapter_handle adapter_handle,
-                         const u8 pagesize,
-                         const u8 queue_type,
-                         const u64 resource_handle,
-                         const u64 logical_address_of_page,
-                         u64 count);
-
-u64 hipz_h_register_rpage_eq(const struct ipz_adapter_handle adapter_handle,
-                            const struct ipz_eq_handle eq_handle,
-                            struct ehca_pfeq *pfeq,
-                            const u8 pagesize,
-                            const u8 queue_type,
-                            const u64 logical_address_of_page,
-                            const u64 count);
-
-u64 hipz_h_query_int_state(const struct ipz_adapter_handle
-                          hcp_adapter_handle,
-                          u32 ist);
-
-u64 hipz_h_register_rpage_cq(const struct ipz_adapter_handle adapter_handle,
-                            const struct ipz_cq_handle cq_handle,
-                            struct ehca_pfcq *pfcq,
-                            const u8 pagesize,
-                            const u8 queue_type,
-                            const u64 logical_address_of_page,
-                            const u64 count,
-                            const struct h_galpa gal);
-
-u64 hipz_h_register_rpage_qp(const struct ipz_adapter_handle adapter_handle,
-                            const struct ipz_qp_handle qp_handle,
-                            struct ehca_pfqp *pfqp,
-                            const u8 pagesize,
-                            const u8 queue_type,
-                            const u64 logical_address_of_page,
-                            const u64 count,
-                            const struct h_galpa galpa);
-
-u64 hipz_h_disable_and_get_wqe(const struct ipz_adapter_handle adapter_handle,
-                              const struct ipz_qp_handle qp_handle,
-                              struct ehca_pfqp *pfqp,
-                              void **log_addr_next_sq_wqe_tb_processed,
-                              void **log_addr_next_rq_wqe_tb_processed,
-                              int dis_and_get_function_code);
-enum hcall_sigt {
-       HCALL_SIGT_NO_CQE = 0,
-       HCALL_SIGT_BY_WQE = 1,
-       HCALL_SIGT_EVERY = 2
-};
-
-u64 hipz_h_modify_qp(const struct ipz_adapter_handle adapter_handle,
-                    const struct ipz_qp_handle qp_handle,
-                    struct ehca_pfqp *pfqp,
-                    const u64 update_mask,
-                    struct hcp_modify_qp_control_block *mqpcb,
-                    struct h_galpa gal);
-
-u64 hipz_h_query_qp(const struct ipz_adapter_handle adapter_handle,
-                   const struct ipz_qp_handle qp_handle,
-                   struct ehca_pfqp *pfqp,
-                   struct hcp_modify_qp_control_block *qqpcb,
-                   struct h_galpa gal);
-
-u64 hipz_h_destroy_qp(const struct ipz_adapter_handle adapter_handle,
-                     struct ehca_qp *qp);
-
-u64 hipz_h_define_aqp0(const struct ipz_adapter_handle adapter_handle,
-                      const struct ipz_qp_handle qp_handle,
-                      struct h_galpa gal,
-                      u32 port);
-
-u64 hipz_h_define_aqp1(const struct ipz_adapter_handle adapter_handle,
-                      const struct ipz_qp_handle qp_handle,
-                      struct h_galpa gal,
-                      u32 port, u32 * pma_qp_nr,
-                      u32 * bma_qp_nr);
-
-u64 hipz_h_attach_mcqp(const struct ipz_adapter_handle adapter_handle,
-                      const struct ipz_qp_handle qp_handle,
-                      struct h_galpa gal,
-                      u16 mcg_dlid,
-                      u64 subnet_prefix, u64 interface_id);
-
-u64 hipz_h_detach_mcqp(const struct ipz_adapter_handle adapter_handle,
-                      const struct ipz_qp_handle qp_handle,
-                      struct h_galpa gal,
-                      u16 mcg_dlid,
-                      u64 subnet_prefix, u64 interface_id);
-
-u64 hipz_h_destroy_cq(const struct ipz_adapter_handle adapter_handle,
-                     struct ehca_cq *cq,
-                     u8 force_flag);
-
-u64 hipz_h_destroy_eq(const struct ipz_adapter_handle adapter_handle,
-                     struct ehca_eq *eq);
-
-/*
- * hipz_h_alloc_resource_mr allocates MR resources in HW and FW, initialize
- * resources.
- */
-u64 hipz_h_alloc_resource_mr(const struct ipz_adapter_handle adapter_handle,
-                            const struct ehca_mr *mr,
-                            const u64 vaddr,
-                            const u64 length,
-                            const u32 access_ctrl,
-                            const struct ipz_pd pd,
-                            struct ehca_mr_hipzout_parms *outparms);
-
-/* hipz_h_register_rpage_mr registers MR resource pages in HW and FW */
-u64 hipz_h_register_rpage_mr(const struct ipz_adapter_handle adapter_handle,
-                            const struct ehca_mr *mr,
-                            const u8 pagesize,
-                            const u8 queue_type,
-                            const u64 logical_address_of_page,
-                            const u64 count);
-
-/* hipz_h_query_mr queries MR in HW and FW */
-u64 hipz_h_query_mr(const struct ipz_adapter_handle adapter_handle,
-                   const struct ehca_mr *mr,
-                   struct ehca_mr_hipzout_parms *outparms);
-
-/* hipz_h_free_resource_mr frees MR resources in HW and FW */
-u64 hipz_h_free_resource_mr(const struct ipz_adapter_handle adapter_handle,
-                           const struct ehca_mr *mr);
-
-/* hipz_h_reregister_pmr reregisters MR in HW and FW */
-u64 hipz_h_reregister_pmr(const struct ipz_adapter_handle adapter_handle,
-                         const struct ehca_mr *mr,
-                         const u64 vaddr_in,
-                         const u64 length,
-                         const u32 access_ctrl,
-                         const struct ipz_pd pd,
-                         const u64 mr_addr_cb,
-                         struct ehca_mr_hipzout_parms *outparms);
-
-/* hipz_h_register_smr register shared MR in HW and FW */
-u64 hipz_h_register_smr(const struct ipz_adapter_handle adapter_handle,
-                       const struct ehca_mr *mr,
-                       const struct ehca_mr *orig_mr,
-                       const u64 vaddr_in,
-                       const u32 access_ctrl,
-                       const struct ipz_pd pd,
-                       struct ehca_mr_hipzout_parms *outparms);
-
-/*
- * hipz_h_alloc_resource_mw allocates MW resources in HW and FW, initialize
- * resources.
- */
-u64 hipz_h_alloc_resource_mw(const struct ipz_adapter_handle adapter_handle,
-                            const struct ehca_mw *mw,
-                            const struct ipz_pd pd,
-                            struct ehca_mw_hipzout_parms *outparms);
-
-/* hipz_h_query_mw queries MW in HW and FW */
-u64 hipz_h_query_mw(const struct ipz_adapter_handle adapter_handle,
-                   const struct ehca_mw *mw,
-                   struct ehca_mw_hipzout_parms *outparms);
-
-/* hipz_h_free_resource_mw frees MW resources in HW and FW */
-u64 hipz_h_free_resource_mw(const struct ipz_adapter_handle adapter_handle,
-                           const struct ehca_mw *mw);
-
-u64 hipz_h_error_data(const struct ipz_adapter_handle adapter_handle,
-                     const u64 ressource_handle,
-                     void *rblock,
-                     unsigned long *byte_count);
-u64 hipz_h_eoi(int irq);
-
-#endif /* __HCP_IF_H__ */
diff --git a/drivers/infiniband/hw/ehca/hcp_phyp.c b/drivers/infiniband/hw/ehca/hcp_phyp.c
deleted file mode 100644 (file)
index 077376f..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- *  IBM eServer eHCA Infiniband device driver for Linux on POWER
- *
- *   load store abstraction for ehca register access with tracing
- *
- *  Authors: Christoph Raisch <raisch@de.ibm.com>
- *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
- *
- *  Copyright (c) 2005 IBM Corporation
- *
- *  All rights reserved.
- *
- *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
- *  BSD.
- *
- * OpenIB BSD License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "ehca_classes.h"
-#include "hipz_hw.h"
-
-u64 hcall_map_page(u64 physaddr)
-{
-       return (u64)ioremap(physaddr, EHCA_PAGESIZE);
-}
-
-int hcall_unmap_page(u64 mapaddr)
-{
-       iounmap((volatile void __iomem *) mapaddr);
-       return 0;
-}
-
-int hcp_galpas_ctor(struct h_galpas *galpas, int is_user,
-                   u64 paddr_kernel, u64 paddr_user)
-{
-       if (!is_user) {
-               galpas->kernel.fw_handle = hcall_map_page(paddr_kernel);
-               if (!galpas->kernel.fw_handle)
-                       return -ENOMEM;
-       } else
-               galpas->kernel.fw_handle = 0;
-
-       galpas->user.fw_handle = paddr_user;
-
-       return 0;
-}
-
-int hcp_galpas_dtor(struct h_galpas *galpas)
-{
-       if (galpas->kernel.fw_handle) {
-               int ret = hcall_unmap_page(galpas->kernel.fw_handle);
-               if (ret)
-                       return ret;
-       }
-
-       galpas->user.fw_handle = galpas->kernel.fw_handle = 0;
-
-       return 0;
-}
diff --git a/drivers/infiniband/hw/ehca/hcp_phyp.h b/drivers/infiniband/hw/ehca/hcp_phyp.h
deleted file mode 100644 (file)
index d1b0299..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- *  IBM eServer eHCA Infiniband device driver for Linux on POWER
- *
- *  Firmware calls
- *
- *  Authors: Christoph Raisch <raisch@de.ibm.com>
- *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
- *           Waleri Fomin <fomin@de.ibm.com>
- *           Gerd Bayer <gerd.bayer@de.ibm.com>
- *
- *  Copyright (c) 2005 IBM Corporation
- *
- *  All rights reserved.
- *
- *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
- *  BSD.
- *
- * OpenIB BSD License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __HCP_PHYP_H__
-#define __HCP_PHYP_H__
-
-
-/*
- * eHCA page (mapped into memory)
- * resource to access eHCA register pages in CPU address space
-*/
-struct h_galpa {
-       u64 fw_handle;
-       /* for pSeries this is a 64bit memory address where
-          I/O memory is mapped into CPU address space (kv) */
-};
-
-/*
- * resource to access eHCA address space registers, all types
- */
-struct h_galpas {
-       u32 pid;                /*PID of userspace galpa checking */
-       struct h_galpa user;    /* user space accessible resource,
-                                  set to 0 if unused */
-       struct h_galpa kernel;  /* kernel space accessible resource,
-                                  set to 0 if unused */
-};
-
-static inline u64 hipz_galpa_load(struct h_galpa galpa, u32 offset)
-{
-       u64 addr = galpa.fw_handle + offset;
-       return *(volatile u64 __force *)addr;
-}
-
-static inline void hipz_galpa_store(struct h_galpa galpa, u32 offset, u64 value)
-{
-       u64 addr = galpa.fw_handle + offset;
-       *(volatile u64 __force *)addr = value;
-}
-
-int hcp_galpas_ctor(struct h_galpas *galpas, int is_user,
-                   u64 paddr_kernel, u64 paddr_user);
-
-int hcp_galpas_dtor(struct h_galpas *galpas);
-
-u64 hcall_map_page(u64 physaddr);
-
-int hcall_unmap_page(u64 mapaddr);
-
-#endif
diff --git a/drivers/infiniband/hw/ehca/hipz_fns.h b/drivers/infiniband/hw/ehca/hipz_fns.h
deleted file mode 100644 (file)
index 9dac93d..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- *  IBM eServer eHCA Infiniband device driver for Linux on POWER
- *
- *  HW abstraction register functions
- *
- *  Authors: Christoph Raisch <raisch@de.ibm.com>
- *           Reinhard Ernst <rernst@de.ibm.com>
- *
- *  Copyright (c) 2005 IBM Corporation
- *
- *  All rights reserved.
- *
- *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
- *  BSD.
- *
- * OpenIB BSD License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __HIPZ_FNS_H__
-#define __HIPZ_FNS_H__
-
-#include "ehca_classes.h"
-#include "hipz_hw.h"
-
-#include "hipz_fns_core.h"
-
-#define hipz_galpa_store_eq(gal, offset, value) \
-       hipz_galpa_store(gal, EQTEMM_OFFSET(offset), value)
-
-#define hipz_galpa_load_eq(gal, offset) \
-       hipz_galpa_load(gal, EQTEMM_OFFSET(offset))
-
-#define hipz_galpa_store_qped(gal, offset, value) \
-       hipz_galpa_store(gal, QPEDMM_OFFSET(offset), value)
-
-#define hipz_galpa_load_qped(gal, offset) \
-       hipz_galpa_load(gal, QPEDMM_OFFSET(offset))
-
-#define hipz_galpa_store_mrmw(gal, offset, value) \
-       hipz_galpa_store(gal, MRMWMM_OFFSET(offset), value)
-
-#define hipz_galpa_load_mrmw(gal, offset) \
-       hipz_galpa_load(gal, MRMWMM_OFFSET(offset))
-
-#endif
diff --git a/drivers/infiniband/hw/ehca/hipz_fns_core.h b/drivers/infiniband/hw/ehca/hipz_fns_core.h
deleted file mode 100644 (file)
index 868735f..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- *  IBM eServer eHCA Infiniband device driver for Linux on POWER
- *
- *  HW abstraction register functions
- *
- *  Authors: Christoph Raisch <raisch@de.ibm.com>
- *           Heiko J Schick <schickhj@de.ibm.com>
- *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
- *           Reinhard Ernst <rernst@de.ibm.com>
- *
- *  Copyright (c) 2005 IBM Corporation
- *
- *  All rights reserved.
- *
- *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
- *  BSD.
- *
- * OpenIB BSD License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __HIPZ_FNS_CORE_H__
-#define __HIPZ_FNS_CORE_H__
-
-#include "hcp_phyp.h"
-#include "hipz_hw.h"
-
-#define hipz_galpa_store_cq(gal, offset, value) \
-       hipz_galpa_store(gal, CQTEMM_OFFSET(offset), value)
-
-#define hipz_galpa_load_cq(gal, offset) \
-       hipz_galpa_load(gal, CQTEMM_OFFSET(offset))
-
-#define hipz_galpa_store_qp(gal, offset, value) \
-       hipz_galpa_store(gal, QPTEMM_OFFSET(offset), value)
-#define hipz_galpa_load_qp(gal, offset) \
-       hipz_galpa_load(gal, QPTEMM_OFFSET(offset))
-
-static inline void hipz_update_sqa(struct ehca_qp *qp, u16 nr_wqes)
-{
-       /*  ringing doorbell :-) */
-       hipz_galpa_store_qp(qp->galpas.kernel, qpx_sqa,
-                           EHCA_BMASK_SET(QPX_SQADDER, nr_wqes));
-}
-
-static inline void hipz_update_rqa(struct ehca_qp *qp, u16 nr_wqes)
-{
-       /*  ringing doorbell :-) */
-       hipz_galpa_store_qp(qp->galpas.kernel, qpx_rqa,
-                           EHCA_BMASK_SET(QPX_RQADDER, nr_wqes));
-}
-
-static inline void hipz_update_feca(struct ehca_cq *cq, u32 nr_cqes)
-{
-       hipz_galpa_store_cq(cq->galpas.kernel, cqx_feca,
-                           EHCA_BMASK_SET(CQX_FECADDER, nr_cqes));
-}
-
-static inline void hipz_set_cqx_n0(struct ehca_cq *cq, u32 value)
-{
-       u64 cqx_n0_reg;
-
-       hipz_galpa_store_cq(cq->galpas.kernel, cqx_n0,
-                           EHCA_BMASK_SET(CQX_N0_GENERATE_SOLICITED_COMP_EVENT,
-                                          value));
-       cqx_n0_reg = hipz_galpa_load_cq(cq->galpas.kernel, cqx_n0);
-}
-
-static inline void hipz_set_cqx_n1(struct ehca_cq *cq, u32 value)
-{
-       u64 cqx_n1_reg;
-
-       hipz_galpa_store_cq(cq->galpas.kernel, cqx_n1,
-                           EHCA_BMASK_SET(CQX_N1_GENERATE_COMP_EVENT, value));
-       cqx_n1_reg = hipz_galpa_load_cq(cq->galpas.kernel, cqx_n1);
-}
-
-#endif /* __HIPZ_FNC_CORE_H__ */
diff --git a/drivers/infiniband/hw/ehca/hipz_hw.h b/drivers/infiniband/hw/ehca/hipz_hw.h
deleted file mode 100644 (file)
index bf996c7..0000000
+++ /dev/null
@@ -1,414 +0,0 @@
-/*
- *  IBM eServer eHCA Infiniband device driver for Linux on POWER
- *
- *  eHCA register definitions
- *
- *  Authors: Waleri Fomin <fomin@de.ibm.com>
- *           Christoph Raisch <raisch@de.ibm.com>
- *           Reinhard Ernst <rernst@de.ibm.com>
- *
- *  Copyright (c) 2005 IBM Corporation
- *
- *  All rights reserved.
- *
- *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
- *  BSD.
- *
- * OpenIB BSD License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __HIPZ_HW_H__
-#define __HIPZ_HW_H__
-
-#include "ehca_tools.h"
-
-#define EHCA_MAX_MTU 4
-
-/* QP Table Entry Memory Map */
-struct hipz_qptemm {
-       u64 qpx_hcr;
-       u64 qpx_c;
-       u64 qpx_herr;
-       u64 qpx_aer;
-/* 0x20*/
-       u64 qpx_sqa;
-       u64 qpx_sqc;
-       u64 qpx_rqa;
-       u64 qpx_rqc;
-/* 0x40*/
-       u64 qpx_st;
-       u64 qpx_pmstate;
-       u64 qpx_pmfa;
-       u64 qpx_pkey;
-/* 0x60*/
-       u64 qpx_pkeya;
-       u64 qpx_pkeyb;
-       u64 qpx_pkeyc;
-       u64 qpx_pkeyd;
-/* 0x80*/
-       u64 qpx_qkey;
-       u64 qpx_dqp;
-       u64 qpx_dlidp;
-       u64 qpx_portp;
-/* 0xa0*/
-       u64 qpx_slidp;
-       u64 qpx_slidpp;
-       u64 qpx_dlida;
-       u64 qpx_porta;
-/* 0xc0*/
-       u64 qpx_slida;
-       u64 qpx_slidpa;
-       u64 qpx_slvl;
-       u64 qpx_ipd;
-/* 0xe0*/
-       u64 qpx_mtu;
-       u64 qpx_lato;
-       u64 qpx_rlimit;
-       u64 qpx_rnrlimit;
-/* 0x100*/
-       u64 qpx_t;
-       u64 qpx_sqhp;
-       u64 qpx_sqptp;
-       u64 qpx_nspsn;
-/* 0x120*/
-       u64 qpx_nspsnhwm;
-       u64 reserved1;
-       u64 qpx_sdsi;
-       u64 qpx_sdsbc;
-/* 0x140*/
-       u64 qpx_sqwsize;
-       u64 qpx_sqwts;
-       u64 qpx_lsn;
-       u64 qpx_nssn;
-/* 0x160 */
-       u64 qpx_mor;
-       u64 qpx_cor;
-       u64 qpx_sqsize;
-       u64 qpx_erc;
-/* 0x180*/
-       u64 qpx_rnrrc;
-       u64 qpx_ernrwt;
-       u64 qpx_rnrresp;
-       u64 qpx_lmsna;
-/* 0x1a0 */
-       u64 qpx_sqhpc;
-       u64 qpx_sqcptp;
-       u64 qpx_sigt;
-       u64 qpx_wqecnt;
-/* 0x1c0*/
-       u64 qpx_rqhp;
-       u64 qpx_rqptp;
-       u64 qpx_rqsize;
-       u64 qpx_nrr;
-/* 0x1e0*/
-       u64 qpx_rdmac;
-       u64 qpx_nrpsn;
-       u64 qpx_lapsn;
-       u64 qpx_lcr;
-/* 0x200*/
-       u64 qpx_rwc;
-       u64 qpx_rwva;
-       u64 qpx_rdsi;
-       u64 qpx_rdsbc;
-/* 0x220*/
-       u64 qpx_rqwsize;
-       u64 qpx_crmsn;
-       u64 qpx_rdd;
-       u64 qpx_larpsn;
-/* 0x240*/
-       u64 qpx_pd;
-       u64 qpx_scqn;
-       u64 qpx_rcqn;
-       u64 qpx_aeqn;
-/* 0x260*/
-       u64 qpx_aaelog;
-       u64 qpx_ram;
-       u64 qpx_rdmaqe0;
-       u64 qpx_rdmaqe1;
-/* 0x280*/
-       u64 qpx_rdmaqe2;
-       u64 qpx_rdmaqe3;
-       u64 qpx_nrpsnhwm;
-/* 0x298*/
-       u64 reserved[(0x400 - 0x298) / 8];
-/* 0x400 extended data */
-       u64 reserved_ext[(0x500 - 0x400) / 8];
-/* 0x500 */
-       u64 reserved2[(0x1000 - 0x500) / 8];
-/* 0x1000      */
-};
-
-#define QPX_SQADDER EHCA_BMASK_IBM(48, 63)
-#define QPX_RQADDER EHCA_BMASK_IBM(48, 63)
-#define QPX_AAELOG_RESET_SRQ_LIMIT EHCA_BMASK_IBM(3, 3)
-
-#define QPTEMM_OFFSET(x) offsetof(struct hipz_qptemm, x)
-
-/* MRMWPT Entry Memory Map */
-struct hipz_mrmwmm {
-       /* 0x00 */
-       u64 mrx_hcr;
-
-       u64 mrx_c;
-       u64 mrx_herr;
-       u64 mrx_aer;
-       /* 0x20 */
-       u64 mrx_pp;
-       u64 reserved1;
-       u64 reserved2;
-       u64 reserved3;
-       /* 0x40 */
-       u64 reserved4[(0x200 - 0x40) / 8];
-       /* 0x200 */
-       u64 mrx_ctl[64];
-
-};
-
-#define MRMWMM_OFFSET(x) offsetof(struct hipz_mrmwmm, x)
-
-struct hipz_qpedmm {
-       /* 0x00 */
-       u64 reserved0[(0x400) / 8];
-       /* 0x400 */
-       u64 qpedx_phh;
-       u64 qpedx_ppsgp;
-       /* 0x410 */
-       u64 qpedx_ppsgu;
-       u64 qpedx_ppdgp;
-       /* 0x420 */
-       u64 qpedx_ppdgu;
-       u64 qpedx_aph;
-       /* 0x430 */
-       u64 qpedx_apsgp;
-       u64 qpedx_apsgu;
-       /* 0x440 */
-       u64 qpedx_apdgp;
-       u64 qpedx_apdgu;
-       /* 0x450 */
-       u64 qpedx_apav;
-       u64 qpedx_apsav;
-       /* 0x460  */
-       u64 qpedx_hcr;
-       u64 reserved1[4];
-       /* 0x488 */
-       u64 qpedx_rrl0;
-       /* 0x490 */
-       u64 qpedx_rrrkey0;
-       u64 qpedx_rrva0;
-       /* 0x4a0 */
-       u64 reserved2;
-       u64 qpedx_rrl1;
-       /* 0x4b0 */
-       u64 qpedx_rrrkey1;
-       u64 qpedx_rrva1;
-       /* 0x4c0 */
-       u64 reserved3;
-       u64 qpedx_rrl2;
-       /* 0x4d0 */
-       u64 qpedx_rrrkey2;
-       u64 qpedx_rrva2;
-       /* 0x4e0 */
-       u64 reserved4;
-       u64 qpedx_rrl3;
-       /* 0x4f0 */
-       u64 qpedx_rrrkey3;
-       u64 qpedx_rrva3;
-};
-
-#define QPEDMM_OFFSET(x) offsetof(struct hipz_qpedmm, x)
-
-/* CQ Table Entry Memory Map */
-struct hipz_cqtemm {
-       u64 cqx_hcr;
-       u64 cqx_c;
-       u64 cqx_herr;
-       u64 cqx_aer;
-/* 0x20  */
-       u64 cqx_ptp;
-       u64 cqx_tp;
-       u64 cqx_fec;
-       u64 cqx_feca;
-/* 0x40  */
-       u64 cqx_ep;
-       u64 cqx_eq;
-/* 0x50  */
-       u64 reserved1;
-       u64 cqx_n0;
-/* 0x60  */
-       u64 cqx_n1;
-       u64 reserved2[(0x1000 - 0x60) / 8];
-/* 0x1000 */
-};
-
-#define CQX_FEC_CQE_CNT           EHCA_BMASK_IBM(32, 63)
-#define CQX_FECADDER              EHCA_BMASK_IBM(32, 63)
-#define CQX_N0_GENERATE_SOLICITED_COMP_EVENT EHCA_BMASK_IBM(0, 0)
-#define CQX_N1_GENERATE_COMP_EVENT EHCA_BMASK_IBM(0, 0)
-
-#define CQTEMM_OFFSET(x) offsetof(struct hipz_cqtemm, x)
-
-/* EQ Table Entry Memory Map */
-struct hipz_eqtemm {
-       u64 eqx_hcr;
-       u64 eqx_c;
-
-       u64 eqx_herr;
-       u64 eqx_aer;
-/* 0x20 */
-       u64 eqx_ptp;
-       u64 eqx_tp;
-       u64 eqx_ssba;
-       u64 eqx_psba;
-
-/* 0x40 */
-       u64 eqx_cec;
-       u64 eqx_meql;
-       u64 eqx_xisbi;
-       u64 eqx_xisc;
-/* 0x60 */
-       u64 eqx_it;
-
-};
-
-#define EQTEMM_OFFSET(x) offsetof(struct hipz_eqtemm, x)
-
-/* access control defines for MR/MW */
-#define HIPZ_ACCESSCTRL_L_WRITE  0x00800000
-#define HIPZ_ACCESSCTRL_R_WRITE  0x00400000
-#define HIPZ_ACCESSCTRL_R_READ   0x00200000
-#define HIPZ_ACCESSCTRL_R_ATOMIC 0x00100000
-#define HIPZ_ACCESSCTRL_MW_BIND  0x00080000
-
-/* query hca response block */
-struct hipz_query_hca {
-       u32 cur_reliable_dg;
-       u32 cur_qp;
-       u32 cur_cq;
-       u32 cur_eq;
-       u32 cur_mr;
-       u32 cur_mw;
-       u32 cur_ee_context;
-       u32 cur_mcast_grp;
-       u32 cur_qp_attached_mcast_grp;
-       u32 reserved1;
-       u32 cur_ipv6_qp;
-       u32 cur_eth_qp;
-       u32 cur_hp_mr;
-       u32 reserved2[3];
-       u32 max_rd_domain;
-       u32 max_qp;
-       u32 max_cq;
-       u32 max_eq;
-       u32 max_mr;
-       u32 max_hp_mr;
-       u32 max_mw;
-       u32 max_mrwpte;
-       u32 max_special_mrwpte;
-       u32 max_rd_ee_context;
-       u32 max_mcast_grp;
-       u32 max_total_mcast_qp_attach;
-       u32 max_mcast_qp_attach;
-       u32 max_raw_ipv6_qp;
-       u32 max_raw_ethy_qp;
-       u32 internal_clock_frequency;
-       u32 max_pd;
-       u32 max_ah;
-       u32 max_cqe;
-       u32 max_wqes_wq;
-       u32 max_partitions;
-       u32 max_rr_ee_context;
-       u32 max_rr_qp;
-       u32 max_rr_hca;
-       u32 max_act_wqs_ee_context;
-       u32 max_act_wqs_qp;
-       u32 max_sge;
-       u32 max_sge_rd;
-       u32 memory_page_size_supported;
-       u64 max_mr_size;
-       u32 local_ca_ack_delay;
-       u32 num_ports;
-       u32 vendor_id;
-       u32 vendor_part_id;
-       u32 hw_ver;
-       u64 node_guid;
-       u64 hca_cap_indicators;
-       u32 data_counter_register_size;
-       u32 max_shared_rq;
-       u32 max_isns_eq;
-       u32 max_neq;
-} __attribute__ ((packed));
-
-#define HCA_CAP_AH_PORT_NR_CHECK      EHCA_BMASK_IBM( 0,  0)
-#define HCA_CAP_ATOMIC                EHCA_BMASK_IBM( 1,  1)
-#define HCA_CAP_AUTO_PATH_MIG         EHCA_BMASK_IBM( 2,  2)
-#define HCA_CAP_BAD_P_KEY_CTR         EHCA_BMASK_IBM( 3,  3)
-#define HCA_CAP_SQD_RTS_PORT_CHANGE   EHCA_BMASK_IBM( 4,  4)
-#define HCA_CAP_CUR_QP_STATE_MOD      EHCA_BMASK_IBM( 5,  5)
-#define HCA_CAP_INIT_TYPE             EHCA_BMASK_IBM( 6,  6)
-#define HCA_CAP_PORT_ACTIVE_EVENT     EHCA_BMASK_IBM( 7,  7)
-#define HCA_CAP_Q_KEY_VIOL_CTR        EHCA_BMASK_IBM( 8,  8)
-#define HCA_CAP_WQE_RESIZE            EHCA_BMASK_IBM( 9,  9)
-#define HCA_CAP_RAW_PACKET_MCAST      EHCA_BMASK_IBM(10, 10)
-#define HCA_CAP_SHUTDOWN_PORT         EHCA_BMASK_IBM(11, 11)
-#define HCA_CAP_RC_LL_QP              EHCA_BMASK_IBM(12, 12)
-#define HCA_CAP_SRQ                   EHCA_BMASK_IBM(13, 13)
-#define HCA_CAP_UD_LL_QP              EHCA_BMASK_IBM(16, 16)
-#define HCA_CAP_RESIZE_MR             EHCA_BMASK_IBM(17, 17)
-#define HCA_CAP_MINI_QP               EHCA_BMASK_IBM(18, 18)
-#define HCA_CAP_H_ALLOC_RES_SYNC      EHCA_BMASK_IBM(19, 19)
-
-/* query port response block */
-struct hipz_query_port {
-       u32 state;
-       u32 bad_pkey_cntr;
-       u32 lmc;
-       u32 lid;
-       u32 subnet_timeout;
-       u32 qkey_viol_cntr;
-       u32 sm_sl;
-       u32 sm_lid;
-       u32 capability_mask;
-       u32 init_type_reply;
-       u32 pkey_tbl_len;
-       u32 gid_tbl_len;
-       u64 gid_prefix;
-       u32 port_nr;
-       u16 pkey_entries[16];
-       u8  reserved1[32];
-       u32 trent_size;
-       u32 trbuf_size;
-       u64 max_msg_sz;
-       u32 max_mtu;
-       u32 vl_cap;
-       u32 phys_pstate;
-       u32 phys_state;
-       u32 phys_speed;
-       u32 phys_width;
-       u8  reserved2[1884];
-       u64 guid_entries[255];
-} __attribute__ ((packed));
-
-#endif
diff --git a/drivers/infiniband/hw/ehca/ipz_pt_fn.c b/drivers/infiniband/hw/ehca/ipz_pt_fn.c
deleted file mode 100644 (file)
index 7ffc748..0000000
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- *  IBM eServer eHCA Infiniband device driver for Linux on POWER
- *
- *  internal queue handling
- *
- *  Authors: Waleri Fomin <fomin@de.ibm.com>
- *           Reinhard Ernst <rernst@de.ibm.com>
- *           Christoph Raisch <raisch@de.ibm.com>
- *
- *  Copyright (c) 2005 IBM Corporation
- *
- *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
- *  BSD.
- *
- * OpenIB BSD License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <linux/slab.h>
-
-#include "ehca_tools.h"
-#include "ipz_pt_fn.h"
-#include "ehca_classes.h"
-
-#define PAGES_PER_KPAGE (PAGE_SIZE >> EHCA_PAGESHIFT)
-
-struct kmem_cache *small_qp_cache;
-
-void *ipz_qpageit_get_inc(struct ipz_queue *queue)
-{
-       void *ret = ipz_qeit_get(queue);
-       queue->current_q_offset += queue->pagesize;
-       if (queue->current_q_offset > queue->queue_length) {
-               queue->current_q_offset -= queue->pagesize;
-               ret = NULL;
-       }
-       if (((u64)ret) % queue->pagesize) {
-               ehca_gen_err("ERROR!! not at PAGE-Boundary");
-               return NULL;
-       }
-       return ret;
-}
-
-void *ipz_qeit_eq_get_inc(struct ipz_queue *queue)
-{
-       void *ret = ipz_qeit_get(queue);
-       u64 last_entry_in_q = queue->queue_length - queue->qe_size;
-
-       queue->current_q_offset += queue->qe_size;
-       if (queue->current_q_offset > last_entry_in_q) {
-               queue->current_q_offset = 0;
-               queue->toggle_state = (~queue->toggle_state) & 1;
-       }
-
-       return ret;
-}
-
-int ipz_queue_abs_to_offset(struct ipz_queue *queue, u64 addr, u64 *q_offset)
-{
-       int i;
-       for (i = 0; i < queue->queue_length / queue->pagesize; i++) {
-               u64 page = __pa(queue->queue_pages[i]);
-               if (addr >= page && addr < page + queue->pagesize) {
-                       *q_offset = addr - page + i * queue->pagesize;
-                       return 0;
-               }
-       }
-       return -EINVAL;
-}
-
-#if PAGE_SHIFT < EHCA_PAGESHIFT
-#error Kernel pages must be at least as large than eHCA pages (4K) !
-#endif
-
-/*
- * allocate pages for queue:
- * outer loop allocates whole kernel pages (page aligned) and
- * inner loop divides a kernel page into smaller hca queue pages
- */
-static int alloc_queue_pages(struct ipz_queue *queue, const u32 nr_of_pages)
-{
-       int k, f = 0;
-       u8 *kpage;
-
-       while (f < nr_of_pages) {
-               kpage = (u8 *)get_zeroed_page(GFP_KERNEL);
-               if (!kpage)
-                       goto out;
-
-               for (k = 0; k < PAGES_PER_KPAGE && f < nr_of_pages; k++) {
-                       queue->queue_pages[f] = (struct ipz_page *)kpage;
-                       kpage += EHCA_PAGESIZE;
-                       f++;
-               }
-       }
-       return 1;
-
-out:
-       for (f = 0; f < nr_of_pages && queue->queue_pages[f];
-            f += PAGES_PER_KPAGE)
-               free_page((unsigned long)(queue->queue_pages)[f]);
-       return 0;
-}
-
-static int alloc_small_queue_page(struct ipz_queue *queue, struct ehca_pd *pd)
-{
-       int order = ilog2(queue->pagesize) - 9;
-       struct ipz_small_queue_page *page;
-       unsigned long bit;
-
-       mutex_lock(&pd->lock);
-
-       if (!list_empty(&pd->free[order]))
-               page = list_entry(pd->free[order].next,
-                                 struct ipz_small_queue_page, list);
-       else {
-               page = kmem_cache_zalloc(small_qp_cache, GFP_KERNEL);
-               if (!page)
-                       goto out;
-
-               page->page = get_zeroed_page(GFP_KERNEL);
-               if (!page->page) {
-                       kmem_cache_free(small_qp_cache, page);
-                       goto out;
-               }
-
-               list_add(&page->list, &pd->free[order]);
-       }
-
-       bit = find_first_zero_bit(page->bitmap, IPZ_SPAGE_PER_KPAGE >> order);
-       __set_bit(bit, page->bitmap);
-       page->fill++;
-
-       if (page->fill == IPZ_SPAGE_PER_KPAGE >> order)
-               list_move(&page->list, &pd->full[order]);
-
-       mutex_unlock(&pd->lock);
-
-       queue->queue_pages[0] = (void *)(page->page | (bit << (order + 9)));
-       queue->small_page = page;
-       queue->offset = bit << (order + 9);
-       return 1;
-
-out:
-       ehca_err(pd->ib_pd.device, "failed to allocate small queue page");
-       mutex_unlock(&pd->lock);
-       return 0;
-}
-
-static void free_small_queue_page(struct ipz_queue *queue, struct ehca_pd *pd)
-{
-       int order = ilog2(queue->pagesize) - 9;
-       struct ipz_small_queue_page *page = queue->small_page;
-       unsigned long bit;
-       int free_page = 0;
-
-       bit = ((unsigned long)queue->queue_pages[0] & ~PAGE_MASK)
-               >> (order + 9);
-
-       mutex_lock(&pd->lock);
-
-       __clear_bit(bit, page->bitmap);
-       page->fill--;
-
-       if (page->fill == 0) {
-               list_del(&page->list);
-               free_page = 1;
-       }
-
-       if (page->fill == (IPZ_SPAGE_PER_KPAGE >> order) - 1)
-               /* the page was full until we freed the chunk */
-               list_move_tail(&page->list, &pd->free[order]);
-
-       mutex_unlock(&pd->lock);
-
-       if (free_page) {
-               free_page(page->page);
-               kmem_cache_free(small_qp_cache, page);
-       }
-}
-
-int ipz_queue_ctor(struct ehca_pd *pd, struct ipz_queue *queue,
-                  const u32 nr_of_pages, const u32 pagesize,
-                  const u32 qe_size, const u32 nr_of_sg,
-                  int is_small)
-{
-       if (pagesize > PAGE_SIZE) {
-               ehca_gen_err("FATAL ERROR: pagesize=%x "
-                            "is greater than kernel page size", pagesize);
-               return 0;
-       }
-
-       /* init queue fields */
-       queue->queue_length = nr_of_pages * pagesize;
-       queue->pagesize = pagesize;
-       queue->qe_size = qe_size;
-       queue->act_nr_of_sg = nr_of_sg;
-       queue->current_q_offset = 0;
-       queue->toggle_state = 1;
-       queue->small_page = NULL;
-
-       /* allocate queue page pointers */
-       queue->queue_pages = kzalloc(nr_of_pages * sizeof(void *),
-                                    GFP_KERNEL | __GFP_NOWARN);
-       if (!queue->queue_pages) {
-               queue->queue_pages = vzalloc(nr_of_pages * sizeof(void *));
-               if (!queue->queue_pages) {
-                       ehca_gen_err("Couldn't allocate queue page list");
-                       return 0;
-               }
-       }
-
-       /* allocate actual queue pages */
-       if (is_small) {
-               if (!alloc_small_queue_page(queue, pd))
-                       goto ipz_queue_ctor_exit0;
-       } else
-               if (!alloc_queue_pages(queue, nr_of_pages))
-                       goto ipz_queue_ctor_exit0;
-
-       return 1;
-
-ipz_queue_ctor_exit0:
-       ehca_gen_err("Couldn't alloc pages queue=%p "
-                "nr_of_pages=%x",  queue, nr_of_pages);
-       kvfree(queue->queue_pages);
-
-       return 0;
-}
-
-int ipz_queue_dtor(struct ehca_pd *pd, struct ipz_queue *queue)
-{
-       int i, nr_pages;
-
-       if (!queue || !queue->queue_pages) {
-               ehca_gen_dbg("queue or queue_pages is NULL");
-               return 0;
-       }
-
-       if (queue->small_page)
-               free_small_queue_page(queue, pd);
-       else {
-               nr_pages = queue->queue_length / queue->pagesize;
-               for (i = 0; i < nr_pages; i += PAGES_PER_KPAGE)
-                       free_page((unsigned long)queue->queue_pages[i]);
-       }
-
-       kvfree(queue->queue_pages);
-
-       return 1;
-}
-
-int ehca_init_small_qp_cache(void)
-{
-       small_qp_cache = kmem_cache_create("ehca_cache_small_qp",
-                                          sizeof(struct ipz_small_queue_page),
-                                          0, SLAB_HWCACHE_ALIGN, NULL);
-       if (!small_qp_cache)
-               return -ENOMEM;
-
-       return 0;
-}
-
-void ehca_cleanup_small_qp_cache(void)
-{
-       kmem_cache_destroy(small_qp_cache);
-}
diff --git a/drivers/infiniband/hw/ehca/ipz_pt_fn.h b/drivers/infiniband/hw/ehca/ipz_pt_fn.h
deleted file mode 100644 (file)
index a801274..0000000
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- *  IBM eServer eHCA Infiniband device driver for Linux on POWER
- *
- *  internal queue handling
- *
- *  Authors: Waleri Fomin <fomin@de.ibm.com>
- *           Reinhard Ernst <rernst@de.ibm.com>
- *           Christoph Raisch <raisch@de.ibm.com>
- *
- *  Copyright (c) 2005 IBM Corporation
- *
- *  All rights reserved.
- *
- *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
- *  BSD.
- *
- * OpenIB BSD License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __IPZ_PT_FN_H__
-#define __IPZ_PT_FN_H__
-
-#define EHCA_PAGESHIFT   12
-#define EHCA_PAGESIZE   4096UL
-#define EHCA_PAGEMASK   (~(EHCA_PAGESIZE-1))
-#define EHCA_PT_ENTRIES 512UL
-
-#include "ehca_tools.h"
-#include "ehca_qes.h"
-
-struct ehca_pd;
-struct ipz_small_queue_page;
-
-extern struct kmem_cache *small_qp_cache;
-
-/* struct generic ehca page */
-struct ipz_page {
-       u8 entries[EHCA_PAGESIZE];
-};
-
-#define IPZ_SPAGE_PER_KPAGE (PAGE_SIZE / 512)
-
-struct ipz_small_queue_page {
-       unsigned long page;
-       unsigned long bitmap[IPZ_SPAGE_PER_KPAGE / BITS_PER_LONG];
-       int fill;
-       void *mapped_addr;
-       u32 mmap_count;
-       struct list_head list;
-};
-
-/* struct generic queue in linux kernel virtual memory (kv) */
-struct ipz_queue {
-       u64 current_q_offset;   /* current queue entry */
-
-       struct ipz_page **queue_pages;  /* array of pages belonging to queue */
-       u32 qe_size;            /* queue entry size */
-       u32 act_nr_of_sg;
-       u32 queue_length;       /* queue length allocated in bytes */
-       u32 pagesize;
-       u32 toggle_state;       /* toggle flag - per page */
-       u32 offset; /* save offset within page for small_qp */
-       struct ipz_small_queue_page *small_page;
-};
-
-/*
- * return current Queue Entry for a certain q_offset
- * returns address (kv) of Queue Entry
- */
-static inline void *ipz_qeit_calc(struct ipz_queue *queue, u64 q_offset)
-{
-       struct ipz_page *current_page;
-       if (q_offset >= queue->queue_length)
-               return NULL;
-       current_page = (queue->queue_pages)[q_offset >> EHCA_PAGESHIFT];
-       return &current_page->entries[q_offset & (EHCA_PAGESIZE - 1)];
-}
-
-/*
- * return current Queue Entry
- * returns address (kv) of Queue Entry
- */
-static inline void *ipz_qeit_get(struct ipz_queue *queue)
-{
-       return ipz_qeit_calc(queue, queue->current_q_offset);
-}
-
-/*
- * return current Queue Page , increment Queue Page iterator from
- * page to page in struct ipz_queue, last increment will return 0! and
- * NOT wrap
- * returns address (kv) of Queue Page
- * warning don't use in parallel with ipz_QE_get_inc()
- */
-void *ipz_qpageit_get_inc(struct ipz_queue *queue);
-
-/*
- * return current Queue Entry, increment Queue Entry iterator by one
- * step in struct ipz_queue, will wrap in ringbuffer
- * returns address (kv) of Queue Entry BEFORE increment
- * warning don't use in parallel with ipz_qpageit_get_inc()
- */
-static inline void *ipz_qeit_get_inc(struct ipz_queue *queue)
-{
-       void *ret = ipz_qeit_get(queue);
-       queue->current_q_offset += queue->qe_size;
-       if (queue->current_q_offset >= queue->queue_length) {
-               queue->current_q_offset = 0;
-               /* toggle the valid flag */
-               queue->toggle_state = (~queue->toggle_state) & 1;
-       }
-
-       return ret;
-}
-
-/*
- * return a bool indicating whether current Queue Entry is valid
- */
-static inline int ipz_qeit_is_valid(struct ipz_queue *queue)
-{
-       struct ehca_cqe *cqe = ipz_qeit_get(queue);
-       return ((cqe->cqe_flags >> 7) == (queue->toggle_state & 1));
-}
-
-/*
- * return current Queue Entry, increment Queue Entry iterator by one
- * step in struct ipz_queue, will wrap in ringbuffer
- * returns address (kv) of Queue Entry BEFORE increment
- * returns 0 and does not increment, if wrong valid state
- * warning don't use in parallel with ipz_qpageit_get_inc()
- */
-static inline void *ipz_qeit_get_inc_valid(struct ipz_queue *queue)
-{
-       return ipz_qeit_is_valid(queue) ? ipz_qeit_get_inc(queue) : NULL;
-}
-
-/*
- * returns and resets Queue Entry iterator
- * returns address (kv) of first Queue Entry
- */
-static inline void *ipz_qeit_reset(struct ipz_queue *queue)
-{
-       queue->current_q_offset = 0;
-       return ipz_qeit_get(queue);
-}
-
-/*
- * return the q_offset corresponding to an absolute address
- */
-int ipz_queue_abs_to_offset(struct ipz_queue *queue, u64 addr, u64 *q_offset);
-
-/*
- * return the next queue offset. don't modify the queue.
- */
-static inline u64 ipz_queue_advance_offset(struct ipz_queue *queue, u64 offset)
-{
-       offset += queue->qe_size;
-       if (offset >= queue->queue_length) offset = 0;
-       return offset;
-}
-
-/* struct generic page table */
-struct ipz_pt {
-       u64 entries[EHCA_PT_ENTRIES];
-};
-
-/* struct page table for a queue, only to be used in pf */
-struct ipz_qpt {
-       /* queue page tables (kv), use u64 because we know the element length */
-       u64 *qpts;
-       u32 n_qpts;
-       u32 n_ptes;       /*  number of page table entries */
-       u64 *current_pte_addr;
-};
-
-/*
- * constructor for a ipz_queue_t, placement new for ipz_queue_t,
- * new for all dependent datastructors
- * all QP Tables are the same
- * flow:
- *    allocate+pin queue
- * see ipz_qpt_ctor()
- * returns true if ok, false if out of memory
- */
-int ipz_queue_ctor(struct ehca_pd *pd, struct ipz_queue *queue,
-                  const u32 nr_of_pages, const u32 pagesize,
-                  const u32 qe_size, const u32 nr_of_sg,
-                  int is_small);
-
-/*
- * destructor for a ipz_queue_t
- *  -# free queue
- *  see ipz_queue_ctor()
- *  returns true if ok, false if queue was NULL-ptr of free failed
- */
-int ipz_queue_dtor(struct ehca_pd *pd, struct ipz_queue *queue);
-
-/*
- * constructor for a ipz_qpt_t,
- * placement new for struct ipz_queue, new for all dependent datastructors
- * all QP Tables are the same,
- * flow:
- * -# allocate+pin queue
- * -# initialise ptcb
- * -# allocate+pin PTs
- * -# link PTs to a ring, according to HCA Arch, set bit62 id needed
- * -# the ring must have room for exactly nr_of_PTEs
- * see ipz_qpt_ctor()
- */
-void ipz_qpt_ctor(struct ipz_qpt *qpt,
-                 const u32 nr_of_qes,
-                 const u32 pagesize,
-                 const u32 qe_size,
-                 const u8 lowbyte, const u8 toggle,
-                 u32 * act_nr_of_QEs, u32 * act_nr_of_pages);
-
-/*
- * return current Queue Entry, increment Queue Entry iterator by one
- * step in struct ipz_queue, will wrap in ringbuffer
- * returns address (kv) of Queue Entry BEFORE increment
- * warning don't use in parallel with ipz_qpageit_get_inc()
- * warning unpredictable results may occur if steps>act_nr_of_queue_entries
- * fix EQ page problems
- */
-void *ipz_qeit_eq_get_inc(struct ipz_queue *queue);
-
-/*
- * return current Event Queue Entry, increment Queue Entry iterator
- * by one step in struct ipz_queue if valid, will wrap in ringbuffer
- * returns address (kv) of Queue Entry BEFORE increment
- * returns 0 and does not increment, if wrong valid state
- * warning don't use in parallel with ipz_queue_QPageit_get_inc()
- * warning unpredictable results may occur if steps>act_nr_of_queue_entries
- */
-static inline void *ipz_eqit_eq_get_inc_valid(struct ipz_queue *queue)
-{
-       void *ret = ipz_qeit_get(queue);
-       u32 qe = *(u8 *)ret;
-       if ((qe >> 7) != (queue->toggle_state & 1))
-               return NULL;
-       ipz_qeit_eq_get_inc(queue); /* this is a good one */
-       return ret;
-}
-
-static inline void *ipz_eqit_eq_peek_valid(struct ipz_queue *queue)
-{
-       void *ret = ipz_qeit_get(queue);
-       u32 qe = *(u8 *)ret;
-       if ((qe >> 7) != (queue->toggle_state & 1))
-               return NULL;
-       return ret;
-}
-
-/* returns address (GX) of first queue entry */
-static inline u64 ipz_qpt_get_firstpage(struct ipz_qpt *qpt)
-{
-       return be64_to_cpu(qpt->qpts[0]);
-}
-
-/* returns address (kv) of first page of queue page table */
-static inline void *ipz_qpt_get_qpt(struct ipz_qpt *qpt)
-{
-       return qpt->qpts;
-}
-
-#endif                         /* __IPZ_PT_FN_H__ */
index 41d6911e244e1765a34b77fe067cf4e4ddeab172..f1ccd40beae9eb2b7a8e6aaad7ef1a98ab8a0a81 100644 (file)
@@ -245,7 +245,6 @@ static int mlx5_ib_query_device(struct ib_device *ibdev,
                props->device_cap_flags |= IB_DEVICE_BAD_QKEY_CNTR;
        if (MLX5_CAP_GEN(mdev, apm))
                props->device_cap_flags |= IB_DEVICE_AUTO_PATH_MIG;
-       props->device_cap_flags |= IB_DEVICE_LOCAL_DMA_LKEY;
        if (MLX5_CAP_GEN(mdev, xrc))
                props->device_cap_flags |= IB_DEVICE_XRC;
        props->device_cap_flags |= IB_DEVICE_MEM_MGT_EXTENSIONS;
@@ -795,53 +794,6 @@ static int mlx5_ib_mmap(struct ib_ucontext *ibcontext, struct vm_area_struct *vm
        return 0;
 }
 
-static int alloc_pa_mkey(struct mlx5_ib_dev *dev, u32 *key, u32 pdn)
-{
-       struct mlx5_create_mkey_mbox_in *in;
-       struct mlx5_mkey_seg *seg;
-       struct mlx5_core_mr mr;
-       int err;
-
-       in = kzalloc(sizeof(*in), GFP_KERNEL);
-       if (!in)
-               return -ENOMEM;
-
-       seg = &in->seg;
-       seg->flags = MLX5_PERM_LOCAL_READ | MLX5_ACCESS_MODE_PA;
-       seg->flags_pd = cpu_to_be32(pdn | MLX5_MKEY_LEN64);
-       seg->qpn_mkey7_0 = cpu_to_be32(0xffffff << 8);
-       seg->start_addr = 0;
-
-       err = mlx5_core_create_mkey(dev->mdev, &mr, in, sizeof(*in),
-                                   NULL, NULL, NULL);
-       if (err) {
-               mlx5_ib_warn(dev, "failed to create mkey, %d\n", err);
-               goto err_in;
-       }
-
-       kfree(in);
-       *key = mr.key;
-
-       return 0;
-
-err_in:
-       kfree(in);
-
-       return err;
-}
-
-static void free_pa_mkey(struct mlx5_ib_dev *dev, u32 key)
-{
-       struct mlx5_core_mr mr;
-       int err;
-
-       memset(&mr, 0, sizeof(mr));
-       mr.key = key;
-       err = mlx5_core_destroy_mkey(dev->mdev, &mr);
-       if (err)
-               mlx5_ib_warn(dev, "failed to destroy mkey 0x%x\n", key);
-}
-
 static struct ib_pd *mlx5_ib_alloc_pd(struct ib_device *ibdev,
                                      struct ib_ucontext *context,
                                      struct ib_udata *udata)
@@ -867,13 +819,6 @@ static struct ib_pd *mlx5_ib_alloc_pd(struct ib_device *ibdev,
                        kfree(pd);
                        return ERR_PTR(-EFAULT);
                }
-       } else {
-               err = alloc_pa_mkey(to_mdev(ibdev), &pd->pa_lkey, pd->pdn);
-               if (err) {
-                       mlx5_core_dealloc_pd(to_mdev(ibdev)->mdev, pd->pdn);
-                       kfree(pd);
-                       return ERR_PTR(err);
-               }
        }
 
        return &pd->ibpd;
@@ -884,9 +829,6 @@ static int mlx5_ib_dealloc_pd(struct ib_pd *pd)
        struct mlx5_ib_dev *mdev = to_mdev(pd->device);
        struct mlx5_ib_pd *mpd = to_mpd(pd);
 
-       if (!pd->uobject)
-               free_pa_mkey(mdev, mpd->pa_lkey);
-
        mlx5_core_dealloc_pd(mdev->mdev, mpd->pdn);
        kfree(mpd);
 
@@ -1245,18 +1187,10 @@ static int create_dev_resources(struct mlx5_ib_resources *devr)
        struct ib_srq_init_attr attr;
        struct mlx5_ib_dev *dev;
        struct ib_cq_init_attr cq_attr = {.cqe = 1};
-       u32 rsvd_lkey;
        int ret = 0;
 
        dev = container_of(devr, struct mlx5_ib_dev, devr);
 
-       ret = mlx5_core_query_special_context(dev->mdev, &rsvd_lkey);
-       if (ret) {
-               pr_err("Failed to query special context %d\n", ret);
-               return ret;
-       }
-       dev->ib_dev.local_dma_lkey = rsvd_lkey;
-
        devr->p0 = mlx5_ib_alloc_pd(&dev->ib_dev, NULL, NULL);
        if (IS_ERR(devr->p0)) {
                ret = PTR_ERR(devr->p0);
@@ -1418,6 +1352,7 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
        strlcpy(dev->ib_dev.name, "mlx5_%d", IB_DEVICE_NAME_MAX);
        dev->ib_dev.owner               = THIS_MODULE;
        dev->ib_dev.node_type           = RDMA_NODE_IB_CA;
+       dev->ib_dev.local_dma_lkey      = 0 /* not supported for now */;
        dev->num_ports          = MLX5_CAP_GEN(mdev, num_ports);
        dev->ib_dev.phys_port_cnt     = dev->num_ports;
        dev->ib_dev.num_comp_vectors    =
index bb8cda79e8812cf1122feaa70a3f113958858d77..22123b79d550d6a7e0474501592f36dc6f0b632e 100644 (file)
@@ -103,7 +103,6 @@ static inline struct mlx5_ib_ucontext *to_mucontext(struct ib_ucontext *ibuconte
 struct mlx5_ib_pd {
        struct ib_pd            ibpd;
        u32                     pdn;
-       u32                     pa_lkey;
 };
 
 /* Use macros here so that don't have to duplicate
@@ -213,7 +212,6 @@ struct mlx5_ib_qp {
        int                     uuarn;
 
        int                     create_type;
-       u32                     pa_lkey;
 
        /* Store signature errors */
        bool                    signature_en;
index c745c6c5e10da0b296fd19ef6ee01d7650af44ff..6f521a3418e8e1c69b9cca74fc8443dd05e30dac 100644 (file)
@@ -925,8 +925,6 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd,
                        err = create_kernel_qp(dev, init_attr, qp, &in, &inlen);
                        if (err)
                                mlx5_ib_dbg(dev, "err %d\n", err);
-                       else
-                               qp->pa_lkey = to_mpd(pd)->pa_lkey;
                }
 
                if (err)
@@ -2045,7 +2043,7 @@ static void set_frwr_pages(struct mlx5_wqe_data_seg *dseg,
                mfrpl->mapped_page_list[i] = cpu_to_be64(page_list[i] | perm);
        dseg->addr = cpu_to_be64(mfrpl->map);
        dseg->byte_count = cpu_to_be32(ALIGN(sizeof(u64) * wr->wr.fast_reg.page_list_len, 64));
-       dseg->lkey = cpu_to_be32(pd->pa_lkey);
+       dseg->lkey = cpu_to_be32(pd->ibpd.local_dma_lkey);
 }
 
 static __be32 send_ieth(struct ib_send_wr *wr)
index 5be13d8991bce0e7c4edec27c8034e847d4cba29..f903502d3883256e8044dbbec9b2ef9baa2fbdc4 100644 (file)
@@ -1,9 +1,24 @@
 /*
  * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
  *
- * This program is free software; you may redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
index 04a66229584e0089ef72e027f986d3d71a574b0d..7fe9502ce8d3df43a57b8e7325ecd0aa262949cd 100644 (file)
@@ -1,9 +1,24 @@
 /*
  * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
  *
- * This program is free software; you may redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
index 3935672661423ff007f6cfc405197967e56c9792..596e0ed49a8e2a066097b5612da723535fdcccbc 100644 (file)
@@ -1,9 +1,24 @@
 /*
  * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
  *
- * This program is free software; you may redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
index 9d737ed5e55d905e6452d2c5fb20f040cf765705..b54986de5f0cad3677461af613862351ca3fb3f2 100644 (file)
@@ -1,9 +1,24 @@
 /*
  * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
  *
- * This program is free software; you may redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
index 5d13860161a4a64af533b3a5aee3c43e25e475d0..5e55b8bc6fe402af423118c1454b5bc67d21d8ba 100644 (file)
@@ -1,9 +1,24 @@
 /*
  * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
  *
- * This program is free software; you may redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
index 4087d24a88f6d9a1e6080b3a2b91dff473cd0944..98453e91daa6f0a1d91c9eb50d468a2585bfcdbe 100644 (file)
@@ -1,9 +1,24 @@
 /*
  * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
  *
- * This program is free software; you may redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
index e3c9bd9d3ba366d7f5cd8ef30f5cd5f43b3fbe74..3c37dd59c04eaec750e5ddbf98383e8e4b64d669 100644 (file)
@@ -1,9 +1,24 @@
 /*
  * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
  *
- * This program is free software; you may redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
index 93713a2230b36724c5bef33933de4c512ba89784..3a8add9ddf4611f89272ee21a0a17dc70fe5028f 100644 (file)
@@ -1,9 +1,24 @@
 /*
  * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
  *
- * This program is free software; you may redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
index e5a9297dd1bd3eac9f2dda97f2954e002a31ca4f..525bf272671e6973afb13472263dd8f730c4eac3 100644 (file)
@@ -1,9 +1,24 @@
 /*
  * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
  *
- * This program is free software; you may redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
index 34c49b8105feb4b59ae320997622e4145d24a742..0c15bd885035ee5fe5110e1317cafe09e762fe07 100644 (file)
@@ -1,9 +1,24 @@
 /*
  * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
  *
- * This program is free software; you may redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
index db3588df3546b3ceaf8dce0ae8e175e6326265a3..85dc3f989ff72aa565c85efb4d07fdc7772d3c93 100644 (file)
@@ -1,9 +1,24 @@
 /*
  * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
  *
- * This program is free software; you may redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
index b0aafe8db0c35a9d2930e59207a0a01f530b1792..b1458be1d402d60b417904ec450e3d7a0b5b5020 100644 (file)
@@ -1,9 +1,24 @@
 /*
  * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
  *
- * This program is free software; you may redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
index 27dc67c1689ff4245dff59931f91e5c3d22b58c4..3412ea06116e2cca6ba802571edd5e48186edc7f 100644 (file)
@@ -1,9 +1,24 @@
 /*
  * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
  *
- * This program is free software; you may redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
index 0d09b493cd02b4f8fa12a217c8cfc19e39cc5693..3d98e16cfeaf67fa9300d941eb064b96fd40b274 100644 (file)
@@ -1,9 +1,24 @@
 /*
  * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
  *
- * This program is free software; you may redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
index 7df43827cb29661a039d1794d24a20e6cbf1b094..f8e3211689a3453164c9044f3bef4601053c1dba 100644 (file)
@@ -1,9 +1,24 @@
 /*
  * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
  *
- * This program is free software; you may redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
index 0bd04efa16f33f514c30b3b5c32cf62f8488c271..414eaa566bd94e5f05a796a5416ef8f76e7939f6 100644 (file)
@@ -1,9 +1,24 @@
 /*
  * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
  *
- * This program is free software; you may redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
index 75777a66c6848a1d7e946782052382e8f031c0b9..183fcb6a952f4bdaf0714492e1e3cce4a3d15852 100644 (file)
@@ -1,9 +1,24 @@
 /*
  * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
  *
- * This program is free software; you may redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
index ddef6f77a78cf4c3fbf68a1b867a23b843fd3124..de318389a301a58058fb166acd85aef0189e89d5 100644 (file)
@@ -1,9 +1,24 @@
 /*
  * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
  *
- * This program is free software; you may redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
index 7e5dc6d9f462d68ecc3a99a7ef997e74d4e2b626..9a7a2d9755c021928ea38be608abda733129a76d 100644 (file)
@@ -1,9 +1,24 @@
 /*
  * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
  *
- * This program is free software; you may redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
index cb2337f0532b5dcbe0d328eb74a196d976b7b6dc..645a5f6e6c88f0a4166bf0647d26d3b7bf082670 100644 (file)
@@ -7,7 +7,7 @@
  * licenses.  You may choose to be licensed under the terms of the GNU
  * General Public License (GPL) Version 2, available from the file
  * COPYING in the main directory of this source tree, or the
- * OpenIB.org BSD license below:
+ * BSD license below:
  *
  *     Redistribution and use in source and binary forms, with or
  *     without modification, are permitted provided that the following
index 70440996e8f2cbee289fb137d16dbd7ece78d345..45ca7c1613a7f76a86b8ac81c0d215746490ea04 100644 (file)
@@ -1,9 +1,24 @@
 /*
  * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
  *
- * This program is free software; you may redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
index 3a4288e0fbace4621df7166e7e64ca7a97a9d283..42b4b4c4e452eae8b712fb0ef295f304a7ab7492 100644 (file)
@@ -1,9 +1,24 @@
 /*
  * Copyright (c) 2014, Cisco Systems, Inc. All rights reserved.
  *
- * This program is free software; you may redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
index d4f752e258fd4812ec81c2f627ba4ff9e222e4cc..c0b0b876ab905a574dd23c3a87fa13d8d9ce4990 100644 (file)
@@ -1,9 +1,24 @@
 /*
  * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
  *
- * This program is free software; you may redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
index 656b88c39edab15c27214e2e963ce31104fcb2e5..66de93fb8ea934c15051f7b33fa7808306f19f05 100644 (file)
@@ -1,9 +1,24 @@
 /*
  * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
  *
- * This program is free software; you may redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
index 14d931a8829dc4616571af436e30fd2b03070825..a08423e478af2778f9529f558221658aa62c1f42 100644 (file)
@@ -1,9 +1,24 @@
 /*
  * Copyright (c) 2013, Cisco Systems, Inc. All rights reserved.
  *
- * This program is free software; you may redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
index ca2873698d75444066312640a1eb84dc5e2190db..edc5b8565d6d9eb5ba6e22e1baefd21d53986b5f 100644 (file)
@@ -80,7 +80,7 @@ enum {
        IPOIB_NUM_WC              = 4,
 
        IPOIB_MAX_PATH_REC_QUEUE  = 3,
-       IPOIB_MAX_MCAST_QUEUE     = 3,
+       IPOIB_MAX_MCAST_QUEUE     = 64,
 
        IPOIB_FLAG_OPER_UP        = 0,
        IPOIB_FLAG_INITIALIZED    = 1,
@@ -495,6 +495,7 @@ void ipoib_dev_cleanup(struct net_device *dev);
 void ipoib_mcast_join_task(struct work_struct *work);
 void ipoib_mcast_carrier_on_task(struct work_struct *work);
 void ipoib_mcast_send(struct net_device *dev, u8 *daddr, struct sk_buff *skb);
+void ipoib_mcast_free(struct ipoib_mcast *mc);
 
 void ipoib_mcast_restart_task(struct work_struct *work);
 int ipoib_mcast_start_thread(struct net_device *dev);
@@ -548,6 +549,8 @@ void ipoib_path_iter_read(struct ipoib_path_iter *iter,
 
 int ipoib_mcast_attach(struct net_device *dev, u16 mlid,
                       union ib_gid *mgid, int set_qkey);
+int ipoib_mcast_leave(struct net_device *dev, struct ipoib_mcast *mcast);
+struct ipoib_mcast *__ipoib_mcast_find(struct net_device *dev, void *mgid);
 
 int ipoib_init_qp(struct net_device *dev);
 int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca);
index 36536ce5a3e2f9d51278be970d51bb51ec07232c..babba05d7a0eb707f472d7de3cb06843a0844eff 100644 (file)
@@ -1149,6 +1149,9 @@ static void __ipoib_reap_neigh(struct ipoib_dev_priv *priv)
        unsigned long dt;
        unsigned long flags;
        int i;
+       LIST_HEAD(remove_list);
+       struct ipoib_mcast *mcast, *tmcast;
+       struct net_device *dev = priv->dev;
 
        if (test_bit(IPOIB_STOP_NEIGH_GC, &priv->flags))
                return;
@@ -1176,6 +1179,19 @@ static void __ipoib_reap_neigh(struct ipoib_dev_priv *priv)
                                                          lockdep_is_held(&priv->lock))) != NULL) {
                        /* was the neigh idle for two GC periods */
                        if (time_after(neigh_obsolete, neigh->alive)) {
+                               u8 *mgid = neigh->daddr + 4;
+
+                               /* Is this multicast ? */
+                               if (*mgid == 0xff) {
+                                       mcast = __ipoib_mcast_find(dev, mgid);
+
+                                       if (mcast && test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)) {
+                                               list_del(&mcast->list);
+                                               rb_erase(&mcast->rb_node, &priv->multicast_tree);
+                                               list_add_tail(&mcast->list, &remove_list);
+                                       }
+                               }
+
                                rcu_assign_pointer(*np,
                                                   rcu_dereference_protected(neigh->hnext,
                                                                             lockdep_is_held(&priv->lock)));
@@ -1191,6 +1207,10 @@ static void __ipoib_reap_neigh(struct ipoib_dev_priv *priv)
 
 out_unlock:
        spin_unlock_irqrestore(&priv->lock, flags);
+       list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
+               ipoib_mcast_leave(dev, mcast);
+               ipoib_mcast_free(mcast);
+       }
 }
 
 static void ipoib_reap_neigh(struct work_struct *work)
index 09a1748f9d131423f020020456d61d2f6c44a8b1..d750a86042f3d8da0736c23a52f41737b329c37d 100644 (file)
@@ -106,7 +106,7 @@ static void __ipoib_mcast_schedule_join_thread(struct ipoib_dev_priv *priv,
                queue_delayed_work(priv->wq, &priv->mcast_task, 0);
 }
 
-static void ipoib_mcast_free(struct ipoib_mcast *mcast)
+void ipoib_mcast_free(struct ipoib_mcast *mcast)
 {
        struct net_device *dev = mcast->dev;
        int tx_dropped = 0;
@@ -153,7 +153,7 @@ static struct ipoib_mcast *ipoib_mcast_alloc(struct net_device *dev,
        return mcast;
 }
 
-static struct ipoib_mcast *__ipoib_mcast_find(struct net_device *dev, void *mgid)
+struct ipoib_mcast *__ipoib_mcast_find(struct net_device *dev, void *mgid)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
        struct rb_node *n = priv->multicast_tree.rb_node;
@@ -508,17 +508,19 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast)
                rec.hop_limit     = priv->broadcast->mcmember.hop_limit;
 
                /*
-                * Historically Linux IPoIB has never properly supported SEND
-                * ONLY join. It emulated it by not providing all the required
-                * attributes, which is enough to prevent group creation and
-                * detect if there are full members or not. A major problem
-                * with supporting SEND ONLY is detecting when the group is
-                * auto-destroyed as IPoIB will cache the MLID..
+                * Send-only IB Multicast joins do not work at the core
+                * IB layer yet, so we can't use them here.  However,
+                * we are emulating an Ethernet multicast send, which
+                * does not require a multicast subscription and will
+                * still send properly.  The most appropriate thing to
+                * do is to create the group if it doesn't exist as that
+                * most closely emulates the behavior, from a user space
+                * application perspecitive, of Ethernet multicast
+                * operation.  For now, we do a full join, maybe later
+                * when the core IB layers support send only joins we
+                * will use them.
                 */
-#if 1
-               if (test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags))
-                       comp_mask &= ~IB_SA_MCMEMBER_REC_TRAFFIC_CLASS;
-#else
+#if 0
                if (test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags))
                        rec.join_state = 4;
 #endif
@@ -675,7 +677,7 @@ int ipoib_mcast_stop_thread(struct net_device *dev)
        return 0;
 }
 
-static int ipoib_mcast_leave(struct net_device *dev, struct ipoib_mcast *mcast)
+int ipoib_mcast_leave(struct net_device *dev, struct ipoib_mcast *mcast)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
        int ret = 0;
index 1ace5d83a4d761b82ffbe446bbf41a1f051cd66b..f58ff96b6cbb9778153b4ab79794f8a206fa9343 100644 (file)
@@ -97,6 +97,11 @@ unsigned int iser_max_sectors = ISER_DEF_MAX_SECTORS;
 module_param_named(max_sectors, iser_max_sectors, uint, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(max_sectors, "Max number of sectors in a single scsi command (default:1024");
 
+bool iser_always_reg = true;
+module_param_named(always_register, iser_always_reg, bool, S_IRUGO);
+MODULE_PARM_DESC(always_register,
+                "Always register memory, even for continuous memory regions (default:true)");
+
 bool iser_pi_enable = false;
 module_param_named(pi_enable, iser_pi_enable, bool, S_IRUGO);
 MODULE_PARM_DESC(pi_enable, "Enable T10-PI offload support (default:disabled)");
index 86f6583485ef3f99c678a5ce1087f45e7e2ba1f1..a5edd6ede692c7be3d1c6da2f355b062cea9e43e 100644 (file)
@@ -611,6 +611,7 @@ extern int iser_debug_level;
 extern bool iser_pi_enable;
 extern int iser_pi_guard;
 extern unsigned int iser_max_sectors;
+extern bool iser_always_reg;
 
 int iser_assign_reg_ops(struct iser_device *device);
 
index 2493cc748db839b4ec885b82e5292633f242ad01..4c46d67d37a13100b60c6daa0a0b01b8f6855608 100644 (file)
@@ -803,11 +803,12 @@ static int
 iser_reg_prot_sg(struct iscsi_iser_task *task,
                 struct iser_data_buf *mem,
                 struct iser_fr_desc *desc,
+                bool use_dma_key,
                 struct iser_mem_reg *reg)
 {
        struct iser_device *device = task->iser_conn->ib_conn.device;
 
-       if (mem->dma_nents == 1)
+       if (use_dma_key)
                return iser_reg_dma(device, mem, reg);
 
        return device->reg_ops->reg_mem(task, mem, &desc->pi_ctx->rsc, reg);
@@ -817,11 +818,12 @@ static int
 iser_reg_data_sg(struct iscsi_iser_task *task,
                 struct iser_data_buf *mem,
                 struct iser_fr_desc *desc,
+                bool use_dma_key,
                 struct iser_mem_reg *reg)
 {
        struct iser_device *device = task->iser_conn->ib_conn.device;
 
-       if (mem->dma_nents == 1)
+       if (use_dma_key)
                return iser_reg_dma(device, mem, reg);
 
        return device->reg_ops->reg_mem(task, mem, &desc->rsc, reg);
@@ -836,14 +838,17 @@ int iser_reg_rdma_mem(struct iscsi_iser_task *task,
        struct iser_mem_reg *reg = &task->rdma_reg[dir];
        struct iser_mem_reg *data_reg;
        struct iser_fr_desc *desc = NULL;
+       bool use_dma_key;
        int err;
 
        err = iser_handle_unaligned_buf(task, mem, dir);
        if (unlikely(err))
                return err;
 
-       if (mem->dma_nents != 1 ||
-           scsi_get_prot_op(task->sc) != SCSI_PROT_NORMAL) {
+       use_dma_key = (mem->dma_nents == 1 && !iser_always_reg &&
+                      scsi_get_prot_op(task->sc) == SCSI_PROT_NORMAL);
+
+       if (!use_dma_key) {
                desc = device->reg_ops->reg_desc_get(ib_conn);
                reg->mem_h = desc;
        }
@@ -853,7 +858,7 @@ int iser_reg_rdma_mem(struct iscsi_iser_task *task,
        else
                data_reg = &task->desc.data_reg;
 
-       err = iser_reg_data_sg(task, mem, desc, data_reg);
+       err = iser_reg_data_sg(task, mem, desc, use_dma_key, data_reg);
        if (unlikely(err))
                goto err_reg;
 
@@ -866,7 +871,8 @@ int iser_reg_rdma_mem(struct iscsi_iser_task *task,
                        if (unlikely(err))
                                goto err_reg;
 
-                       err = iser_reg_prot_sg(task, mem, desc, prot_reg);
+                       err = iser_reg_prot_sg(task, mem, desc,
+                                              use_dma_key, prot_reg);
                        if (unlikely(err))
                                goto err_reg;
                }
index ae70cc1463ac2b75d7eae512bf3224e90ba2d59f..85132d867bc86fcfcd99b7065e9f746301422de1 100644 (file)
@@ -133,11 +133,15 @@ static int iser_create_device_ib_res(struct iser_device *device)
                             (unsigned long)comp);
        }
 
-       device->mr = ib_get_dma_mr(device->pd, IB_ACCESS_LOCAL_WRITE |
-                                  IB_ACCESS_REMOTE_WRITE |
-                                  IB_ACCESS_REMOTE_READ);
-       if (IS_ERR(device->mr))
-               goto dma_mr_err;
+       if (!iser_always_reg) {
+               int access = IB_ACCESS_LOCAL_WRITE |
+                            IB_ACCESS_REMOTE_WRITE |
+                            IB_ACCESS_REMOTE_READ;
+
+               device->mr = ib_get_dma_mr(device->pd, access);
+               if (IS_ERR(device->mr))
+                       goto dma_mr_err;
+       }
 
        INIT_IB_EVENT_HANDLER(&device->event_handler, device->ib_device,
                                iser_event_handler);
@@ -147,7 +151,8 @@ static int iser_create_device_ib_res(struct iser_device *device)
        return 0;
 
 handler_err:
-       ib_dereg_mr(device->mr);
+       if (device->mr)
+               ib_dereg_mr(device->mr);
 dma_mr_err:
        for (i = 0; i < device->comps_used; i++)
                tasklet_kill(&device->comps[i].tasklet);
@@ -173,7 +178,6 @@ comps_err:
 static void iser_free_device_ib_res(struct iser_device *device)
 {
        int i;
-       BUG_ON(device->mr == NULL);
 
        for (i = 0; i < device->comps_used; i++) {
                struct iser_comp *comp = &device->comps[i];
@@ -184,7 +188,8 @@ static void iser_free_device_ib_res(struct iser_device *device)
        }
 
        (void)ib_unregister_event_handler(&device->event_handler);
-       (void)ib_dereg_mr(device->mr);
+       if (device->mr)
+               (void)ib_dereg_mr(device->mr);
        ib_dealloc_pd(device->pd);
 
        kfree(device->comps);
index 403bd29443b8e7d06ac1a16cdae826088af98efe..aa59037d75040b7d6e1126bb620339c1c603bc89 100644 (file)
@@ -238,8 +238,6 @@ isert_alloc_rx_descriptors(struct isert_conn *isert_conn)
                rx_sg->lkey = device->pd->local_dma_lkey;
        }
 
-       isert_conn->rx_desc_head = 0;
-
        return 0;
 
 dma_map_fail:
@@ -634,7 +632,7 @@ static void
 isert_init_conn(struct isert_conn *isert_conn)
 {
        isert_conn->state = ISER_CONN_INIT;
-       INIT_LIST_HEAD(&isert_conn->accept_node);
+       INIT_LIST_HEAD(&isert_conn->node);
        init_completion(&isert_conn->login_comp);
        init_completion(&isert_conn->login_req_comp);
        init_completion(&isert_conn->wait);
@@ -762,28 +760,15 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
        ret = isert_rdma_post_recvl(isert_conn);
        if (ret)
                goto out_conn_dev;
-       /*
-        * Obtain the second reference now before isert_rdma_accept() to
-        * ensure that any initiator generated REJECT CM event that occurs
-        * asynchronously won't drop the last reference until the error path
-        * in iscsi_target_login_sess_out() does it's ->iscsit_free_conn() ->
-        * isert_free_conn() -> isert_put_conn() -> kref_put().
-        */
-       if (!kref_get_unless_zero(&isert_conn->kref)) {
-               isert_warn("conn %p connect_release is running\n", isert_conn);
-               goto out_conn_dev;
-       }
 
        ret = isert_rdma_accept(isert_conn);
        if (ret)
                goto out_conn_dev;
 
-       mutex_lock(&isert_np->np_accept_mutex);
-       list_add_tail(&isert_conn->accept_node, &isert_np->np_accept_list);
-       mutex_unlock(&isert_np->np_accept_mutex);
+       mutex_lock(&isert_np->mutex);
+       list_add_tail(&isert_conn->node, &isert_np->accepted);
+       mutex_unlock(&isert_np->mutex);
 
-       isert_info("np %p: Allow accept_np to continue\n", np);
-       up(&isert_np->np_sem);
        return 0;
 
 out_conn_dev:
@@ -831,13 +816,21 @@ static void
 isert_connected_handler(struct rdma_cm_id *cma_id)
 {
        struct isert_conn *isert_conn = cma_id->qp->qp_context;
+       struct isert_np *isert_np = cma_id->context;
 
        isert_info("conn %p\n", isert_conn);
 
        mutex_lock(&isert_conn->mutex);
-       if (isert_conn->state != ISER_CONN_FULL_FEATURE)
-               isert_conn->state = ISER_CONN_UP;
+       isert_conn->state = ISER_CONN_UP;
+       kref_get(&isert_conn->kref);
        mutex_unlock(&isert_conn->mutex);
+
+       mutex_lock(&isert_np->mutex);
+       list_move_tail(&isert_conn->node, &isert_np->pending);
+       mutex_unlock(&isert_np->mutex);
+
+       isert_info("np %p: Allow accept_np to continue\n", isert_np);
+       up(&isert_np->sem);
 }
 
 static void
@@ -903,14 +896,14 @@ isert_np_cma_handler(struct isert_np *isert_np,
 
        switch (event) {
        case RDMA_CM_EVENT_DEVICE_REMOVAL:
-               isert_np->np_cm_id = NULL;
+               isert_np->cm_id = NULL;
                break;
        case RDMA_CM_EVENT_ADDR_CHANGE:
-               isert_np->np_cm_id = isert_setup_id(isert_np);
-               if (IS_ERR(isert_np->np_cm_id)) {
+               isert_np->cm_id = isert_setup_id(isert_np);
+               if (IS_ERR(isert_np->cm_id)) {
                        isert_err("isert np %p setup id failed: %ld\n",
-                                 isert_np, PTR_ERR(isert_np->np_cm_id));
-                       isert_np->np_cm_id = NULL;
+                                 isert_np, PTR_ERR(isert_np->cm_id));
+                       isert_np->cm_id = NULL;
                }
                break;
        default:
@@ -929,7 +922,7 @@ isert_disconnected_handler(struct rdma_cm_id *cma_id,
        struct isert_conn *isert_conn;
        bool terminating = false;
 
-       if (isert_np->np_cm_id == cma_id)
+       if (isert_np->cm_id == cma_id)
                return isert_np_cma_handler(cma_id->context, event);
 
        isert_conn = cma_id->qp->qp_context;
@@ -945,13 +938,13 @@ isert_disconnected_handler(struct rdma_cm_id *cma_id,
        if (terminating)
                goto out;
 
-       mutex_lock(&isert_np->np_accept_mutex);
-       if (!list_empty(&isert_conn->accept_node)) {
-               list_del_init(&isert_conn->accept_node);
+       mutex_lock(&isert_np->mutex);
+       if (!list_empty(&isert_conn->node)) {
+               list_del_init(&isert_conn->node);
                isert_put_conn(isert_conn);
                queue_work(isert_release_wq, &isert_conn->release_work);
        }
-       mutex_unlock(&isert_np->np_accept_mutex);
+       mutex_unlock(&isert_np->mutex);
 
 out:
        return 0;
@@ -962,6 +955,7 @@ isert_connect_error(struct rdma_cm_id *cma_id)
 {
        struct isert_conn *isert_conn = cma_id->qp->qp_context;
 
+       list_del_init(&isert_conn->node);
        isert_conn->cm_id = NULL;
        isert_put_conn(isert_conn);
 
@@ -1006,35 +1000,51 @@ isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
 }
 
 static int
-isert_post_recv(struct isert_conn *isert_conn, u32 count)
+isert_post_recvm(struct isert_conn *isert_conn, u32 count)
 {
        struct ib_recv_wr *rx_wr, *rx_wr_failed;
        int i, ret;
-       unsigned int rx_head = isert_conn->rx_desc_head;
        struct iser_rx_desc *rx_desc;
 
        for (rx_wr = isert_conn->rx_wr, i = 0; i < count; i++, rx_wr++) {
-               rx_desc         = &isert_conn->rx_descs[rx_head];
-               rx_wr->wr_id    = (uintptr_t)rx_desc;
-               rx_wr->sg_list  = &rx_desc->rx_sg;
-               rx_wr->num_sge  = 1;
-               rx_wr->next     = rx_wr + 1;
-               rx_head = (rx_head + 1) & (ISERT_QP_MAX_RECV_DTOS - 1);
+               rx_desc = &isert_conn->rx_descs[i];
+               rx_wr->wr_id = (uintptr_t)rx_desc;
+               rx_wr->sg_list = &rx_desc->rx_sg;
+               rx_wr->num_sge = 1;
+               rx_wr->next = rx_wr + 1;
        }
-
        rx_wr--;
        rx_wr->next = NULL; /* mark end of work requests list */
 
        isert_conn->post_recv_buf_count += count;
        ret = ib_post_recv(isert_conn->qp, isert_conn->rx_wr,
-                               &rx_wr_failed);
+                          &rx_wr_failed);
        if (ret) {
                isert_err("ib_post_recv() failed with ret: %d\n", ret);
                isert_conn->post_recv_buf_count -= count;
-       } else {
-               isert_dbg("Posted %d RX buffers\n", count);
-               isert_conn->rx_desc_head = rx_head;
        }
+
+       return ret;
+}
+
+static int
+isert_post_recv(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc)
+{
+       struct ib_recv_wr *rx_wr_failed, rx_wr;
+       int ret;
+
+       rx_wr.wr_id = (uintptr_t)rx_desc;
+       rx_wr.sg_list = &rx_desc->rx_sg;
+       rx_wr.num_sge = 1;
+       rx_wr.next = NULL;
+
+       isert_conn->post_recv_buf_count++;
+       ret = ib_post_recv(isert_conn->qp, &rx_wr, &rx_wr_failed);
+       if (ret) {
+               isert_err("ib_post_recv() failed with ret: %d\n", ret);
+               isert_conn->post_recv_buf_count--;
+       }
+
        return ret;
 }
 
@@ -1205,7 +1215,8 @@ isert_put_login_tx(struct iscsi_conn *conn, struct iscsi_login *login,
                        if (ret)
                                return ret;
 
-                       ret = isert_post_recv(isert_conn, ISERT_MIN_POSTED_RX);
+                       ret = isert_post_recvm(isert_conn,
+                                              ISERT_QP_MAX_RECV_DTOS);
                        if (ret)
                                return ret;
 
@@ -1278,7 +1289,7 @@ isert_rx_login_req(struct isert_conn *isert_conn)
 }
 
 static struct iscsi_cmd
-*isert_allocate_cmd(struct iscsi_conn *conn)
+*isert_allocate_cmd(struct iscsi_conn *conn, struct iser_rx_desc *rx_desc)
 {
        struct isert_conn *isert_conn = conn->context;
        struct isert_cmd *isert_cmd;
@@ -1292,6 +1303,7 @@ static struct iscsi_cmd
        isert_cmd = iscsit_priv_cmd(cmd);
        isert_cmd->conn = isert_conn;
        isert_cmd->iscsi_cmd = cmd;
+       isert_cmd->rx_desc = rx_desc;
 
        return cmd;
 }
@@ -1303,9 +1315,9 @@ isert_handle_scsi_cmd(struct isert_conn *isert_conn,
 {
        struct iscsi_conn *conn = isert_conn->conn;
        struct iscsi_scsi_req *hdr = (struct iscsi_scsi_req *)buf;
-       struct scatterlist *sg;
        int imm_data, imm_data_len, unsol_data, sg_nents, rc;
        bool dump_payload = false;
+       unsigned int data_len;
 
        rc = iscsit_setup_scsi_cmd(conn, cmd, buf);
        if (rc < 0)
@@ -1314,7 +1326,10 @@ isert_handle_scsi_cmd(struct isert_conn *isert_conn,
        imm_data = cmd->immediate_data;
        imm_data_len = cmd->first_burst_len;
        unsol_data = cmd->unsolicited_data;
+       data_len = cmd->se_cmd.data_length;
 
+       if (imm_data && imm_data_len == data_len)
+               cmd->se_cmd.se_cmd_flags |= SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC;
        rc = iscsit_process_scsi_cmd(conn, cmd, hdr);
        if (rc < 0) {
                return 0;
@@ -1326,13 +1341,20 @@ isert_handle_scsi_cmd(struct isert_conn *isert_conn,
        if (!imm_data)
                return 0;
 
-       sg = &cmd->se_cmd.t_data_sg[0];
-       sg_nents = max(1UL, DIV_ROUND_UP(imm_data_len, PAGE_SIZE));
-
-       isert_dbg("Copying Immediate SG: %p sg_nents: %u from %p imm_data_len: %d\n",
-                 sg, sg_nents, &rx_desc->data[0], imm_data_len);
-
-       sg_copy_from_buffer(sg, sg_nents, &rx_desc->data[0], imm_data_len);
+       if (imm_data_len != data_len) {
+               sg_nents = max(1UL, DIV_ROUND_UP(imm_data_len, PAGE_SIZE));
+               sg_copy_from_buffer(cmd->se_cmd.t_data_sg, sg_nents,
+                                   &rx_desc->data[0], imm_data_len);
+               isert_dbg("Copy Immediate sg_nents: %u imm_data_len: %d\n",
+                         sg_nents, imm_data_len);
+       } else {
+               sg_init_table(&isert_cmd->sg, 1);
+               cmd->se_cmd.t_data_sg = &isert_cmd->sg;
+               cmd->se_cmd.t_data_nents = 1;
+               sg_set_buf(&isert_cmd->sg, &rx_desc->data[0], imm_data_len);
+               isert_dbg("Transfer Immediate imm_data_len: %d\n",
+                         imm_data_len);
+       }
 
        cmd->write_data_done += imm_data_len;
 
@@ -1407,6 +1429,15 @@ isert_handle_iscsi_dataout(struct isert_conn *isert_conn,
        if (rc < 0)
                return rc;
 
+       /*
+        * multiple data-outs on the same command can arrive -
+        * so post the buffer before hand
+        */
+       rc = isert_post_recv(isert_conn, rx_desc);
+       if (rc) {
+               isert_err("ib_post_recv failed with %d\n", rc);
+               return rc;
+       }
        return 0;
 }
 
@@ -1479,7 +1510,7 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc,
 
        switch (opcode) {
        case ISCSI_OP_SCSI_CMD:
-               cmd = isert_allocate_cmd(conn);
+               cmd = isert_allocate_cmd(conn, rx_desc);
                if (!cmd)
                        break;
 
@@ -1493,7 +1524,7 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc,
                                        rx_desc, (unsigned char *)hdr);
                break;
        case ISCSI_OP_NOOP_OUT:
-               cmd = isert_allocate_cmd(conn);
+               cmd = isert_allocate_cmd(conn, rx_desc);
                if (!cmd)
                        break;
 
@@ -1506,7 +1537,7 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc,
                                                (unsigned char *)hdr);
                break;
        case ISCSI_OP_SCSI_TMFUNC:
-               cmd = isert_allocate_cmd(conn);
+               cmd = isert_allocate_cmd(conn, rx_desc);
                if (!cmd)
                        break;
 
@@ -1514,22 +1545,20 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc,
                                                (unsigned char *)hdr);
                break;
        case ISCSI_OP_LOGOUT:
-               cmd = isert_allocate_cmd(conn);
+               cmd = isert_allocate_cmd(conn, rx_desc);
                if (!cmd)
                        break;
 
                ret = iscsit_handle_logout_cmd(conn, cmd, (unsigned char *)hdr);
                break;
        case ISCSI_OP_TEXT:
-               if (be32_to_cpu(hdr->ttt) != 0xFFFFFFFF) {
+               if (be32_to_cpu(hdr->ttt) != 0xFFFFFFFF)
                        cmd = iscsit_find_cmd_from_itt(conn, hdr->itt);
-                       if (!cmd)
-                               break;
-               } else {
-                       cmd = isert_allocate_cmd(conn);
-                       if (!cmd)
-                               break;
-               }
+               else
+                       cmd = isert_allocate_cmd(conn, rx_desc);
+
+               if (!cmd)
+                       break;
 
                isert_cmd = iscsit_priv_cmd(cmd);
                ret = isert_handle_text_cmd(isert_conn, isert_cmd, cmd,
@@ -1589,7 +1618,7 @@ isert_rcv_completion(struct iser_rx_desc *desc,
        struct ib_device *ib_dev = isert_conn->cm_id->device;
        struct iscsi_hdr *hdr;
        u64 rx_dma;
-       int rx_buflen, outstanding;
+       int rx_buflen;
 
        if ((char *)desc == isert_conn->login_req_buf) {
                rx_dma = isert_conn->login_req_dma;
@@ -1629,22 +1658,6 @@ isert_rcv_completion(struct iser_rx_desc *desc,
                                      DMA_FROM_DEVICE);
 
        isert_conn->post_recv_buf_count--;
-       isert_dbg("Decremented post_recv_buf_count: %d\n",
-                 isert_conn->post_recv_buf_count);
-
-       if ((char *)desc == isert_conn->login_req_buf)
-               return;
-
-       outstanding = isert_conn->post_recv_buf_count;
-       if (outstanding + ISERT_MIN_POSTED_RX <= ISERT_QP_MAX_RECV_DTOS) {
-               int err, count = min(ISERT_QP_MAX_RECV_DTOS - outstanding,
-                               ISERT_MIN_POSTED_RX);
-               err = isert_post_recv(isert_conn, count);
-               if (err) {
-                       isert_err("isert_post_recv() count: %d failed, %d\n",
-                              count, err);
-               }
-       }
 }
 
 static int
@@ -2156,6 +2169,12 @@ isert_post_response(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd)
        struct ib_send_wr *wr_failed;
        int ret;
 
+       ret = isert_post_recv(isert_conn, isert_cmd->rx_desc);
+       if (ret) {
+               isert_err("ib_post_recv failed with %d\n", ret);
+               return ret;
+       }
+
        ret = ib_post_send(isert_conn->qp, &isert_cmd->tx_desc.send_wr,
                           &wr_failed);
        if (ret) {
@@ -2950,6 +2969,12 @@ isert_put_datain(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
                                   &isert_cmd->tx_desc.send_wr);
                isert_cmd->rdma_wr.s_send_wr.next = &isert_cmd->tx_desc.send_wr;
                wr->send_wr_num += 1;
+
+               rc = isert_post_recv(isert_conn, isert_cmd->rx_desc);
+               if (rc) {
+                       isert_err("ib_post_recv failed with %d\n", rc);
+                       return rc;
+               }
        }
 
        rc = ib_post_send(isert_conn->qp, wr->send_wr, &wr_failed);
@@ -2999,9 +3024,16 @@ isert_get_dataout(struct iscsi_conn *conn, struct iscsi_cmd *cmd, bool recovery)
 static int
 isert_immediate_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state)
 {
-       int ret;
+       struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd);
+       int ret = 0;
 
        switch (state) {
+       case ISTATE_REMOVE:
+               spin_lock_bh(&conn->cmd_lock);
+               list_del_init(&cmd->i_conn_node);
+               spin_unlock_bh(&conn->cmd_lock);
+               isert_put_cmd(isert_cmd, true);
+               break;
        case ISTATE_SEND_NOPIN_WANT_RESPONSE:
                ret = isert_put_nopin(cmd, conn, false);
                break;
@@ -3106,10 +3138,10 @@ isert_setup_np(struct iscsi_np *np,
                isert_err("Unable to allocate struct isert_np\n");
                return -ENOMEM;
        }
-       sema_init(&isert_np->np_sem, 0);
-       mutex_init(&isert_np->np_accept_mutex);
-       INIT_LIST_HEAD(&isert_np->np_accept_list);
-       init_completion(&isert_np->np_login_comp);
+       sema_init(&isert_np->sem, 0);
+       mutex_init(&isert_np->mutex);
+       INIT_LIST_HEAD(&isert_np->accepted);
+       INIT_LIST_HEAD(&isert_np->pending);
        isert_np->np = np;
 
        /*
@@ -3125,7 +3157,7 @@ isert_setup_np(struct iscsi_np *np,
                goto out;
        }
 
-       isert_np->np_cm_id = isert_lid;
+       isert_np->cm_id = isert_lid;
        np->np_context = isert_np;
 
        return 0;
@@ -3214,7 +3246,7 @@ isert_accept_np(struct iscsi_np *np, struct iscsi_conn *conn)
        int ret;
 
 accept_wait:
-       ret = down_interruptible(&isert_np->np_sem);
+       ret = down_interruptible(&isert_np->sem);
        if (ret)
                return -ENODEV;
 
@@ -3231,15 +3263,15 @@ accept_wait:
        }
        spin_unlock_bh(&np->np_thread_lock);
 
-       mutex_lock(&isert_np->np_accept_mutex);
-       if (list_empty(&isert_np->np_accept_list)) {
-               mutex_unlock(&isert_np->np_accept_mutex);
+       mutex_lock(&isert_np->mutex);
+       if (list_empty(&isert_np->pending)) {
+               mutex_unlock(&isert_np->mutex);
                goto accept_wait;
        }
-       isert_conn = list_first_entry(&isert_np->np_accept_list,
-                       struct isert_conn, accept_node);
-       list_del_init(&isert_conn->accept_node);
-       mutex_unlock(&isert_np->np_accept_mutex);
+       isert_conn = list_first_entry(&isert_np->pending,
+                       struct isert_conn, node);
+       list_del_init(&isert_conn->node);
+       mutex_unlock(&isert_np->mutex);
 
        conn->context = isert_conn;
        isert_conn->conn = conn;
@@ -3257,28 +3289,39 @@ isert_free_np(struct iscsi_np *np)
        struct isert_np *isert_np = np->np_context;
        struct isert_conn *isert_conn, *n;
 
-       if (isert_np->np_cm_id)
-               rdma_destroy_id(isert_np->np_cm_id);
+       if (isert_np->cm_id)
+               rdma_destroy_id(isert_np->cm_id);
 
        /*
         * FIXME: At this point we don't have a good way to insure
         * that at this point we don't have hanging connections that
         * completed RDMA establishment but didn't start iscsi login
         * process. So work-around this by cleaning up what ever piled
-        * up in np_accept_list.
+        * up in accepted and pending lists.
         */
-       mutex_lock(&isert_np->np_accept_mutex);
-       if (!list_empty(&isert_np->np_accept_list)) {
-               isert_info("Still have isert connections, cleaning up...\n");
+       mutex_lock(&isert_np->mutex);
+       if (!list_empty(&isert_np->pending)) {
+               isert_info("Still have isert pending connections\n");
+               list_for_each_entry_safe(isert_conn, n,
+                                        &isert_np->pending,
+                                        node) {
+                       isert_info("cleaning isert_conn %p state (%d)\n",
+                                  isert_conn, isert_conn->state);
+                       isert_connect_release(isert_conn);
+               }
+       }
+
+       if (!list_empty(&isert_np->accepted)) {
+               isert_info("Still have isert accepted connections\n");
                list_for_each_entry_safe(isert_conn, n,
-                                        &isert_np->np_accept_list,
-                                        accept_node) {
+                                        &isert_np->accepted,
+                                        node) {
                        isert_info("cleaning isert_conn %p state (%d)\n",
                                   isert_conn, isert_conn->state);
                        isert_connect_release(isert_conn);
                }
        }
-       mutex_unlock(&isert_np->np_accept_mutex);
+       mutex_unlock(&isert_np->mutex);
 
        np->np_context = NULL;
        kfree(isert_np);
@@ -3345,6 +3388,41 @@ isert_wait4flush(struct isert_conn *isert_conn)
        wait_for_completion(&isert_conn->wait_comp_err);
 }
 
+/**
+ * isert_put_unsol_pending_cmds() - Drop commands waiting for
+ *     unsolicitate dataout
+ * @conn:    iscsi connection
+ *
+ * We might still have commands that are waiting for unsolicited
+ * dataouts messages. We must put the extra reference on those
+ * before blocking on the target_wait_for_session_cmds
+ */
+static void
+isert_put_unsol_pending_cmds(struct iscsi_conn *conn)
+{
+       struct iscsi_cmd *cmd, *tmp;
+       static LIST_HEAD(drop_cmd_list);
+
+       spin_lock_bh(&conn->cmd_lock);
+       list_for_each_entry_safe(cmd, tmp, &conn->conn_cmd_list, i_conn_node) {
+               if ((cmd->cmd_flags & ICF_NON_IMMEDIATE_UNSOLICITED_DATA) &&
+                   (cmd->write_data_done < conn->sess->sess_ops->FirstBurstLength) &&
+                   (cmd->write_data_done < cmd->se_cmd.data_length))
+                       list_move_tail(&cmd->i_conn_node, &drop_cmd_list);
+       }
+       spin_unlock_bh(&conn->cmd_lock);
+
+       list_for_each_entry_safe(cmd, tmp, &drop_cmd_list, i_conn_node) {
+               list_del_init(&cmd->i_conn_node);
+               if (cmd->i_state != ISTATE_REMOVE) {
+                       struct isert_cmd *isert_cmd = iscsit_priv_cmd(cmd);
+
+                       isert_info("conn %p dropping cmd %p\n", conn, cmd);
+                       isert_put_cmd(isert_cmd, true);
+               }
+       }
+}
+
 static void isert_wait_conn(struct iscsi_conn *conn)
 {
        struct isert_conn *isert_conn = conn->context;
@@ -3363,8 +3441,9 @@ static void isert_wait_conn(struct iscsi_conn *conn)
        isert_conn_terminate(isert_conn);
        mutex_unlock(&isert_conn->mutex);
 
-       isert_wait4cmds(conn);
        isert_wait4flush(isert_conn);
+       isert_put_unsol_pending_cmds(conn);
+       isert_wait4cmds(conn);
        isert_wait4logout(isert_conn);
 
        queue_work(isert_release_wq, &isert_conn->release_work);
index 6a04ba3c0f7224563e3432dffa38c4fcd12fad83..c5b99bcecbcff806945be8baa9cc6dbeca46418a 100644 (file)
@@ -113,7 +113,6 @@ enum {
 };
 
 struct isert_rdma_wr {
-       struct list_head        wr_list;
        struct isert_cmd        *isert_cmd;
        enum iser_ib_op_code    iser_ib_op;
        struct ib_sge           *ib_sge;
@@ -134,14 +133,13 @@ struct isert_cmd {
        uint64_t                write_va;
        u64                     pdu_buf_dma;
        u32                     pdu_buf_len;
-       u32                     read_va_off;
-       u32                     write_va_off;
-       u32                     rdma_wr_num;
        struct isert_conn       *conn;
        struct iscsi_cmd        *iscsi_cmd;
        struct iser_tx_desc     tx_desc;
+       struct iser_rx_desc     *rx_desc;
        struct isert_rdma_wr    rdma_wr;
        struct work_struct      comp_work;
+       struct scatterlist      sg;
 };
 
 struct isert_device;
@@ -159,11 +157,10 @@ struct isert_conn {
        u64                     login_req_dma;
        int                     login_req_len;
        u64                     login_rsp_dma;
-       unsigned int            rx_desc_head;
        struct iser_rx_desc     *rx_descs;
-       struct ib_recv_wr       rx_wr[ISERT_MIN_POSTED_RX];
+       struct ib_recv_wr       rx_wr[ISERT_QP_MAX_RECV_DTOS];
        struct iscsi_conn       *conn;
-       struct list_head        accept_node;
+       struct list_head        node;
        struct completion       login_comp;
        struct completion       login_req_comp;
        struct iser_tx_desc     login_tx_desc;
@@ -222,9 +219,9 @@ struct isert_device {
 
 struct isert_np {
        struct iscsi_np         *np;
-       struct semaphore        np_sem;
-       struct rdma_cm_id       *np_cm_id;
-       struct mutex            np_accept_mutex;
-       struct list_head        np_accept_list;
-       struct completion       np_login_comp;
+       struct semaphore        sem;
+       struct rdma_cm_id       *cm_id;
+       struct mutex            mutex;
+       struct list_head        accepted;
+       struct list_head        pending;
 };
index 56eb471b5576954f6119664b23a1d7b83316d3fb..4215b5382092c15d693e62de6e029626e9fa551d 100644 (file)
@@ -196,6 +196,7 @@ config JOYSTICK_TWIDJOY
 config JOYSTICK_ZHENHUA
        tristate "5-byte Zhenhua RC transmitter"
        select SERIO
+       select BITREVERSE
        help
          Say Y here if you have a Zhen Hua PPM-4CH transmitter which is
          supplied with a ready to fly micro electric indoor helicopters
index b76ac580703ce5dc9ef97fac6620adc47ea44273..a8bc2fe170dd83e12ff78706f97f9bc32a72e5cd 100644 (file)
@@ -150,7 +150,7 @@ static void walkera0701_irq_handler(void *handler_data)
                if (w->counter == 24) { /* full frame */
                        walkera0701_parse_frame(w);
                        w->counter = NO_SYNC;
-                       if (abs(pulse_time - SYNC_PULSE) < RESERVE)     /* new frame sync */
+                       if (abs64(pulse_time - SYNC_PULSE) < RESERVE)   /* new frame sync */
                                w->counter = 0;
                } else {
                        if ((pulse_time > (ANALOG_MIN_PULSE - RESERVE)
@@ -161,7 +161,7 @@ static void walkera0701_irq_handler(void *handler_data)
                        } else
                                w->counter = NO_SYNC;
                }
-       } else if (abs(pulse_time - SYNC_PULSE - BIN0_PULSE) <
+       } else if (abs64(pulse_time - SYNC_PULSE - BIN0_PULSE) <
                                RESERVE + BIN1_PULSE - BIN0_PULSE)      /* frame sync .. */
                w->counter = 0;
 
index b052afec9a11f0d323eb735dee3d262eabf116a2..6639b2b8528aa6da9a518d3bd3dc0da3010f4a09 100644 (file)
@@ -266,7 +266,7 @@ static int omap4_keypad_probe(struct platform_device *pdev)
 
        error = omap4_keypad_parse_dt(&pdev->dev, keypad_data);
        if (error)
-               return error;
+               goto err_free_keypad;
 
        res = request_mem_region(res->start, resource_size(res), pdev->name);
        if (!res) {
index 867db8a91372017d2af6a11d24f189a7bc796fc2..e317b75357a0182d99ef3c04223596bd1de6fc80 100644 (file)
@@ -93,7 +93,7 @@ static int pm8941_reboot_notify(struct notifier_block *nb,
        default:
                reset_type = PON_PS_HOLD_TYPE_HARD_RESET;
                break;
-       };
+       }
 
        error = regmap_update_bits(pwrkey->regmap,
                                   pwrkey->baseaddr + PON_PS_HOLD_RST_CTL,
index 345df9b03aed7f1eff56cf2f1a743c59c8d5e780..5adbcedcb81cf4391bfdddefe11aae5d3131dd76 100644 (file)
@@ -414,7 +414,7 @@ static int uinput_setup_device(struct uinput_device *udev,
        dev->id.product = user_dev->id.product;
        dev->id.version = user_dev->id.version;
 
-       for_each_set_bit(i, dev->absbit, ABS_CNT) {
+       for (i = 0; i < ABS_CNT; i++) {
                input_abs_set_max(dev, i, user_dev->absmax[i]);
                input_abs_set_min(dev, i, user_dev->absmin[i]);
                input_abs_set_fuzz(dev, i, user_dev->absfuzz[i]);
index 4d246861d692b810f3074aa7917cda86893ac6c2..41e6cb501e6a1d5b07801463460fe4ebbaace887 100644 (file)
@@ -100,7 +100,7 @@ static const struct alps_nibble_commands alps_v6_nibble_commands[] = {
 #define ALPS_FOUR_BUTTONS      0x40    /* 4 direction button present */
 #define ALPS_PS2_INTERLEAVED   0x80    /* 3-byte PS/2 packet interleaved with
                                           6-byte ALPS packet */
-#define ALPS_DELL              0x100   /* device is a Dell laptop */
+#define ALPS_STICK_BITS                0x100   /* separate stick button bits */
 #define ALPS_BUTTONPAD         0x200   /* device is a clickpad */
 
 static const struct alps_model_info alps_model_data[] = {
@@ -159,6 +159,43 @@ static const struct alps_protocol_info alps_v8_protocol_data = {
        ALPS_PROTO_V8, 0x18, 0x18, 0
 };
 
+/*
+ * Some v2 models report the stick buttons in separate bits
+ */
+static const struct dmi_system_id alps_dmi_has_separate_stick_buttons[] = {
+#if defined(CONFIG_DMI) && defined(CONFIG_X86)
+       {
+               /* Extrapolated from other entries */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D420"),
+               },
+       },
+       {
+               /* Reported-by: Hans de Bruin <jmdebruin@xmsnet.nl> */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D430"),
+               },
+       },
+       {
+               /* Reported-by: Hans de Goede <hdegoede@redhat.com> */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D620"),
+               },
+       },
+       {
+               /* Extrapolated from other entries */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D630"),
+               },
+       },
+#endif
+       { }
+};
+
 static void alps_set_abs_params_st(struct alps_data *priv,
                                   struct input_dev *dev1);
 static void alps_set_abs_params_semi_mt(struct alps_data *priv,
@@ -253,9 +290,8 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse)
                return;
        }
 
-       /* Dell non interleaved V2 dualpoint has separate stick button bits */
-       if (priv->proto_version == ALPS_PROTO_V2 &&
-           priv->flags == (ALPS_DELL | ALPS_PASS | ALPS_DUALPOINT)) {
+       /* Some models have separate stick button bits */
+       if (priv->flags & ALPS_STICK_BITS) {
                left |= packet[0] & 1;
                right |= packet[0] & 2;
                middle |= packet[0] & 4;
@@ -2552,8 +2588,6 @@ static int alps_set_protocol(struct psmouse *psmouse,
        priv->byte0 = protocol->byte0;
        priv->mask0 = protocol->mask0;
        priv->flags = protocol->flags;
-       if (dmi_name_in_vendors("Dell"))
-               priv->flags |= ALPS_DELL;
 
        priv->x_max = 2000;
        priv->y_max = 1400;
@@ -2568,6 +2602,8 @@ static int alps_set_protocol(struct psmouse *psmouse,
                priv->set_abs_params = alps_set_abs_params_st;
                priv->x_max = 1023;
                priv->y_max = 767;
+               if (dmi_check_system(alps_dmi_has_separate_stick_buttons))
+                       priv->flags |= ALPS_STICK_BITS;
                break;
 
        case ALPS_PROTO_V3:
index 5f191071d44a033d45d1f433475cd3b7d0b4befd..e4eb048d1bf63f8bc2d7027800a81a58cdf4f855 100644 (file)
@@ -241,14 +241,10 @@ static int cyapa_gen6_read_sys_info(struct cyapa *cyapa)
        memcpy(&cyapa->product_id[13], &resp_data[62], 2);
        cyapa->product_id[15] = '\0';
 
+       /* Get the number of Rx electrodes. */
        rotat_align = resp_data[68];
-       if (rotat_align) {
-               cyapa->electrodes_rx = cyapa->electrodes_y;
-               cyapa->electrodes_rx = cyapa->electrodes_y;
-       } else {
-               cyapa->electrodes_rx = cyapa->electrodes_x;
-               cyapa->electrodes_rx = cyapa->electrodes_y;
-       }
+       cyapa->electrodes_rx =
+               rotat_align ? cyapa->electrodes_y : cyapa->electrodes_x;
        cyapa->aligned_electrodes_rx = (cyapa->electrodes_rx + 3) & ~3u;
 
        if (!cyapa->electrodes_x || !cyapa->electrodes_y ||
index 73670f2aebfd5e189ab794c6ffd4b44759bb5acb..c0ec26118732879f7674f68bd0458b3d27602f61 100644 (file)
@@ -60,7 +60,7 @@ struct elan_transport_ops {
        int (*get_sm_version)(struct i2c_client *client,
                              u8* ic_type, u8 *version);
        int (*get_checksum)(struct i2c_client *client, bool iap, u16 *csum);
-       int (*get_product_id)(struct i2c_client *client, u8 *id);
+       int (*get_product_id)(struct i2c_client *client, u16 *id);
 
        int (*get_max)(struct i2c_client *client,
                       unsigned int *max_x, unsigned int *max_y);
index fa945304b9a576d4303c778eca929a5f3517092a..5e1665bbaa0baca86e2c865ba88162be2f209d2e 100644 (file)
@@ -40,7 +40,7 @@
 #include "elan_i2c.h"
 
 #define DRIVER_NAME            "elan_i2c"
-#define ELAN_DRIVER_VERSION    "1.6.0"
+#define ELAN_DRIVER_VERSION    "1.6.1"
 #define ETP_MAX_PRESSURE       255
 #define ETP_FWIDTH_REDUCE      90
 #define ETP_FINGER_WIDTH       15
@@ -76,7 +76,7 @@ struct elan_tp_data {
        unsigned int            x_res;
        unsigned int            y_res;
 
-       u                     product_id;
+       u16                     product_id;
        u8                      fw_version;
        u8                      sm_version;
        u8                      iap_version;
@@ -98,15 +98,25 @@ static int elan_get_fwinfo(u8 iap_version, u16 *validpage_count,
                           u16 *signature_address)
 {
        switch (iap_version) {
+       case 0x00:
+       case 0x06:
        case 0x08:
                *validpage_count = 512;
                break;
+       case 0x03:
+       case 0x07:
        case 0x09:
+       case 0x0A:
+       case 0x0B:
+       case 0x0C:
                *validpage_count = 768;
                break;
        case 0x0D:
                *validpage_count = 896;
                break;
+       case 0x0E:
+               *validpage_count = 640;
+               break;
        default:
                /* unknown ic type clear value */
                *validpage_count = 0;
@@ -266,11 +276,10 @@ static int elan_query_device_info(struct elan_tp_data *data)
 
        error = elan_get_fwinfo(data->iap_version, &data->fw_validpage_count,
                                &data->fw_signature_address);
-       if (error) {
-               dev_err(&data->client->dev,
-                       "unknown iap version %d\n", data->iap_version);
-               return error;
-       }
+       if (error)
+               dev_warn(&data->client->dev,
+                        "unexpected iap version %#04x (ic type: %#04x), firmware update will not work\n",
+                        data->iap_version, data->ic_type);
 
        return 0;
 }
@@ -486,6 +495,9 @@ static ssize_t elan_sysfs_update_fw(struct device *dev,
        const u8 *fw_signature;
        static const u8 signature[] = {0xAA, 0x55, 0xCC, 0x33, 0xFF, 0xFF};
 
+       if (data->fw_validpage_count == 0)
+               return -EINVAL;
+
        /* Look for a firmware with the product id appended. */
        fw_name = kasprintf(GFP_KERNEL, ETP_FW_NAME, data->product_id);
        if (!fw_name) {
index 683c840c9dd73f31d1279b7db88dfacd1f42b7b0..a679e56c44cd49ddea4361aebdb97d4fe7f1e12e 100644 (file)
@@ -276,7 +276,7 @@ static int elan_i2c_get_sm_version(struct i2c_client *client,
        return 0;
 }
 
-static int elan_i2c_get_product_id(struct i2c_client *client, u8 *id)
+static int elan_i2c_get_product_id(struct i2c_client *client, u16 *id)
 {
        int error;
        u8 val[3];
@@ -287,7 +287,7 @@ static int elan_i2c_get_product_id(struct i2c_client *client, u8 *id)
                return error;
        }
 
-       *id = val[0];
+       *id = le16_to_cpup((__le16 *)val);
        return 0;
 }
 
index ff36a366b2aa1aadbe3c9a7f0e9de3eb687d83c3..cb6aecbc1dc28a20885885c4b361ecf8343bc445 100644 (file)
@@ -183,7 +183,7 @@ static int elan_smbus_get_sm_version(struct i2c_client *client,
        return 0;
 }
 
-static int elan_smbus_get_product_id(struct i2c_client *client, u8 *id)
+static int elan_smbus_get_product_id(struct i2c_client *client, u16 *id)
 {
        int error;
        u8 val[3];
@@ -195,7 +195,7 @@ static int elan_smbus_get_product_id(struct i2c_client *client, u8 *id)
                return error;
        }
 
-       *id = val[1];
+       *id = be16_to_cpup((__be16 *)val);
        return 0;
 }
 
index 994ae788615698bf3af613f1de765fe0411be995..6025eb430c0a5010c908961ccf8897943fd3c945 100644 (file)
@@ -519,18 +519,14 @@ static int synaptics_set_mode(struct psmouse *psmouse)
        struct synaptics_data *priv = psmouse->private;
 
        priv->mode = 0;
-
-       if (priv->absolute_mode) {
+       if (priv->absolute_mode)
                priv->mode |= SYN_BIT_ABSOLUTE_MODE;
-               if (SYN_CAP_EXTENDED(priv->capabilities))
-                       priv->mode |= SYN_BIT_W_MODE;
-       }
-
-       if (!SYN_MODE_WMODE(priv->mode) && priv->disable_gesture)
+       if (priv->disable_gesture)
                priv->mode |= SYN_BIT_DISABLE_GESTURE;
-
        if (psmouse->rate >= 80)
                priv->mode |= SYN_BIT_HIGH_RATE;
+       if (SYN_CAP_EXTENDED(priv->capabilities))
+               priv->mode |= SYN_BIT_W_MODE;
 
        if (synaptics_mode_cmd(psmouse, priv->mode))
                return -1;
index 75516996db2070b621c6250cdd9710acf473ad42..316f2c8971011dae527d506ee18d49ce96f316e0 100644 (file)
@@ -212,12 +212,17 @@ int __ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
         * time before the ACK arrives.
         */
        if (ps2_sendbyte(ps2dev, command & 0xff,
-                        command == PS2_CMD_RESET_BAT ? 1000 : 200))
-               goto out;
+                        command == PS2_CMD_RESET_BAT ? 1000 : 200)) {
+               serio_pause_rx(ps2dev->serio);
+               goto out_reset_flags;
+       }
 
-       for (i = 0; i < send; i++)
-               if (ps2_sendbyte(ps2dev, param[i], 200))
-                       goto out;
+       for (i = 0; i < send; i++) {
+               if (ps2_sendbyte(ps2dev, param[i], 200)) {
+                       serio_pause_rx(ps2dev->serio);
+                       goto out_reset_flags;
+               }
+       }
 
        /*
         * The reset command takes a long time to execute.
@@ -234,17 +239,18 @@ int __ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command)
                                   !(ps2dev->flags & PS2_FLAG_CMD), timeout);
        }
 
+       serio_pause_rx(ps2dev->serio);
+
        if (param)
                for (i = 0; i < receive; i++)
                        param[i] = ps2dev->cmdbuf[(receive - 1) - i];
 
        if (ps2dev->cmdcnt && (command != PS2_CMD_RESET_BAT || ps2dev->cmdcnt != 1))
-               goto out;
+               goto out_reset_flags;
 
        rc = 0;
 
- out:
-       serio_pause_rx(ps2dev->serio);
+ out_reset_flags:
        ps2dev->flags = 0;
        serio_continue_rx(ps2dev->serio);
 
index 26b45936f9fdf3334c6f083aeaa7c5ee5bb178dd..1e8cd6f1fe9e875005af95b54787890f81116a5f 100644 (file)
@@ -194,6 +194,7 @@ static int __init parkbd_init(void)
        parkbd_port = parkbd_allocate_serio();
        if (!parkbd_port) {
                parport_release(parkbd_dev);
+               parport_unregister_device(parkbd_dev);
                return -ENOMEM;
        }
 
index 600dcceff5426aaf4f6fc7b20ce966960bf0aa92..deb14c12ae8b19a84c5ba8e0074f4bac43260ecc 100644 (file)
@@ -1006,6 +1006,7 @@ config TOUCHSCREEN_SUN4I
 config TOUCHSCREEN_SUR40
        tristate "Samsung SUR40 (Surface 2.0/PixelSense) touchscreen"
        depends on USB && MEDIA_USB_SUPPORT && HAS_DMA
+       depends on VIDEO_V4L2
        select INPUT_POLLDEV
        select VIDEOBUF2_DMA_SG
        help
index 0f5f968592bd02afd9c5381a8839b3428c3bcbea..04edc8f7122fa77d9c043694ba8f47d0c83dab0c 100644 (file)
@@ -668,18 +668,22 @@ static int ads7846_no_filter(void *ads, int data_idx, int *val)
 
 static int ads7846_get_value(struct ads7846 *ts, struct spi_message *m)
 {
+       int value;
        struct spi_transfer *t =
                list_entry(m->transfers.prev, struct spi_transfer, transfer_list);
 
        if (ts->model == 7845) {
-               return be16_to_cpup((__be16 *)&(((char*)t->rx_buf)[1])) >> 3;
+               value = be16_to_cpup((__be16 *)&(((char *)t->rx_buf)[1]));
        } else {
                /*
                 * adjust:  on-wire is a must-ignore bit, a BE12 value, then
                 * padding; built from two 8 bit values written msb-first.
                 */
-               return be16_to_cpup((__be16 *)t->rx_buf) >> 3;
+               value = be16_to_cpup((__be16 *)t->rx_buf);
        }
+
+       /* enforce ADC output is 12 bits width */
+       return (value >> 3) & 0xfff;
 }
 
 static void ads7846_update_value(struct spi_message *m, int val)
index ff0b75813daa21cff6f8baccfbf453a06ebf383b..8275267eac25441f308e6103e82d48830d1feb71 100644 (file)
@@ -94,7 +94,7 @@ struct imx6ul_tsc {
  * TSC module need ADC to get the measure value. So
  * before config TSC, we should initialize ADC module.
  */
-static void imx6ul_adc_init(struct imx6ul_tsc *tsc)
+static int imx6ul_adc_init(struct imx6ul_tsc *tsc)
 {
        int adc_hc = 0;
        int adc_gc;
@@ -122,17 +122,23 @@ static void imx6ul_adc_init(struct imx6ul_tsc *tsc)
 
        timeout = wait_for_completion_timeout
                        (&tsc->completion, ADC_TIMEOUT);
-       if (timeout == 0)
+       if (timeout == 0) {
                dev_err(tsc->dev, "Timeout for adc calibration\n");
+               return -ETIMEDOUT;
+       }
 
        adc_gs = readl(tsc->adc_regs + REG_ADC_GS);
-       if (adc_gs & ADC_CALF)
+       if (adc_gs & ADC_CALF) {
                dev_err(tsc->dev, "ADC calibration failed\n");
+               return -EINVAL;
+       }
 
        /* TSC need the ADC work in hardware trigger */
        adc_cfg = readl(tsc->adc_regs + REG_ADC_CFG);
        adc_cfg |= ADC_HARDWARE_TRIGGER;
        writel(adc_cfg, tsc->adc_regs + REG_ADC_CFG);
+
+       return 0;
 }
 
 /*
@@ -188,11 +194,17 @@ static void imx6ul_tsc_set(struct imx6ul_tsc *tsc)
        writel(start, tsc->tsc_regs + REG_TSC_FLOW_CONTROL);
 }
 
-static void imx6ul_tsc_init(struct imx6ul_tsc *tsc)
+static int imx6ul_tsc_init(struct imx6ul_tsc *tsc)
 {
-       imx6ul_adc_init(tsc);
+       int err;
+
+       err = imx6ul_adc_init(tsc);
+       if (err)
+               return err;
        imx6ul_tsc_channel_config(tsc);
        imx6ul_tsc_set(tsc);
+
+       return 0;
 }
 
 static void imx6ul_tsc_disable(struct imx6ul_tsc *tsc)
@@ -311,9 +323,7 @@ static int imx6ul_tsc_open(struct input_dev *input_dev)
                return err;
        }
 
-       imx6ul_tsc_init(tsc);
-
-       return 0;
+       return imx6ul_tsc_init(tsc);
 }
 
 static void imx6ul_tsc_close(struct input_dev *input_dev)
@@ -337,7 +347,7 @@ static int imx6ul_tsc_probe(struct platform_device *pdev)
        int tsc_irq;
        int adc_irq;
 
-       tsc = devm_kzalloc(&pdev->dev, sizeof(struct imx6ul_tsc), GFP_KERNEL);
+       tsc = devm_kzalloc(&pdev->dev, sizeof(*tsc), GFP_KERNEL);
        if (!tsc)
                return -ENOMEM;
 
@@ -345,7 +355,7 @@ static int imx6ul_tsc_probe(struct platform_device *pdev)
        if (!input_dev)
                return -ENOMEM;
 
-       input_dev->name = "iMX6UL TouchScreen Controller";
+       input_dev->name = "iMX6UL Touchscreen Controller";
        input_dev->id.bustype = BUS_HOST;
 
        input_dev->open = imx6ul_tsc_open;
@@ -406,7 +416,7 @@ static int imx6ul_tsc_probe(struct platform_device *pdev)
        }
 
        adc_irq = platform_get_irq(pdev, 1);
-       if (adc_irq <= 0) {
+       if (adc_irq < 0) {
                dev_err(&pdev->dev, "no adc irq resource?\n");
                return adc_irq;
        }
@@ -491,7 +501,7 @@ static int __maybe_unused imx6ul_tsc_resume(struct device *dev)
                        goto out;
                }
 
-               imx6ul_tsc_init(tsc);
+               retval = imx6ul_tsc_init(tsc);
        }
 
 out:
index 24d704cd9f882fb8517d036b00d5f64d46787993..7fbb3b0c857150170a293981e1e7940d70478c3f 100644 (file)
@@ -139,14 +139,14 @@ static void lpc32xx_stop_tsc(struct lpc32xx_tsc *tsc)
                   tsc_readl(tsc, LPC32XX_TSC_CON) &
                             ~LPC32XX_TSC_ADCCON_AUTO_EN);
 
-       clk_disable(tsc->clk);
+       clk_disable_unprepare(tsc->clk);
 }
 
 static void lpc32xx_setup_tsc(struct lpc32xx_tsc *tsc)
 {
        u32 tmp;
 
-       clk_enable(tsc->clk);
+       clk_prepare_enable(tsc->clk);
 
        tmp = tsc_readl(tsc, LPC32XX_TSC_CON) & ~LPC32XX_TSC_ADCCON_POWER_UP;
 
index 7cce87650fc8da3e401ec9a9aa1807ea1a2d9dfb..1fafc9f57af6c75a7a8a9e9d6b90e016f4e90272 100644 (file)
@@ -394,12 +394,12 @@ static struct mms114_platform_data *mms114_parse_dt(struct device *dev)
        if (of_property_read_u32(np, "x-size", &pdata->x_size)) {
                dev_err(dev, "failed to get x-size property\n");
                return NULL;
-       };
+       }
 
        if (of_property_read_u32(np, "y-size", &pdata->y_size)) {
                dev_err(dev, "failed to get y-size property\n");
                return NULL;
-       };
+       }
 
        of_property_read_u32(np, "contact-threshold",
                                &pdata->contact_threshold);
index 4664c2a96c67fee361c3476ddc8f9a8e8842d271..cbe6a890a93a0d1448f46e32edbfdc5231ba7098 100644 (file)
@@ -23,8 +23,7 @@ config IOMMU_IO_PGTABLE
 config IOMMU_IO_PGTABLE_LPAE
        bool "ARMv7/v8 Long Descriptor Format"
        select IOMMU_IO_PGTABLE
-       # SWIOTLB guarantees a dma_to_phys() implementation
-       depends on ARM || ARM64 || (COMPILE_TEST && SWIOTLB)
+       depends on HAS_DMA && (ARM || ARM64 || COMPILE_TEST)
        help
          Enable support for the ARM long descriptor pagetable format.
          This allocator supports 4K/2M/1G, 16K/32M and 64K/512M page
@@ -43,7 +42,7 @@ config IOMMU_IO_PGTABLE_LPAE_SELFTEST
 endmenu
 
 config IOMMU_IOVA
-       bool
+       tristate
 
 config OF_IOMMU
        def_bool y
index f82060e778a23bb7a8901ef2356d42b5363d93a6..532e2a211fe1cf9b3d7ff71d36cbcfde49bd29df 100644 (file)
@@ -1974,8 +1974,8 @@ static void set_dte_entry(u16 devid, struct protection_domain *domain, bool ats)
 static void clear_dte_entry(u16 devid)
 {
        /* remove entry from the device table seen by the hardware */
-       amd_iommu_dev_table[devid].data[0] = IOMMU_PTE_P | IOMMU_PTE_TV;
-       amd_iommu_dev_table[devid].data[1] = 0;
+       amd_iommu_dev_table[devid].data[0]  = IOMMU_PTE_P | IOMMU_PTE_TV;
+       amd_iommu_dev_table[devid].data[1] &= DTE_FLAG_MASK;
 
        amd_iommu_apply_erratum_63(devid);
 }
@@ -2006,6 +2006,15 @@ static void do_detach(struct iommu_dev_data *dev_data)
 {
        struct amd_iommu *iommu;
 
+       /*
+        * First check if the device is still attached. It might already
+        * be detached from its domain because the generic
+        * iommu_detach_group code detached it and we try again here in
+        * our alias handling.
+        */
+       if (!dev_data->domain)
+               return;
+
        iommu = amd_iommu_rlookup_table[dev_data->devid];
 
        /* decrease reference counters */
index 5ef347a13cb5d54789c07869b0527d81cb24365e..1b066e7d144d6fdc0043cfbfa340ce2e7a209c50 100644 (file)
@@ -1256,6 +1256,9 @@ static int iommu_init_pci(struct amd_iommu *iommu)
        if (!iommu->dev)
                return -ENODEV;
 
+       /* Prevent binding other PCI device drivers to IOMMU devices */
+       iommu->dev->match_driver = false;
+
        pci_read_config_dword(iommu->dev, cap_ptr + MMIO_CAP_HDR_OFFSET,
                              &iommu->cap);
        pci_read_config_dword(iommu->dev, cap_ptr + MMIO_RANGE_OFFSET,
index f65908841be0184db61f049bc8e2b5a622ca2fbe..c9b64722f62309d76e56ad52c5a3691737ffd6ac 100644 (file)
 #define IOMMU_PTE_IR (1ULL << 61)
 #define IOMMU_PTE_IW (1ULL << 62)
 
+#define DTE_FLAG_MASK  (0x3ffULL << 32)
 #define DTE_FLAG_IOTLB (0x01UL << 32)
 #define DTE_FLAG_GV    (0x01ULL << 55)
 #define DTE_GLX_SHIFT  (56)
index 1131664b918b0a574c7cc654a6a3cd04107f8e81..d21d4edf7236abac49072c086290b76d2ae201b5 100644 (file)
@@ -516,6 +516,13 @@ static void do_fault(struct work_struct *work)
                goto out;
        }
 
+       if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE))) {
+               /* handle_mm_fault would BUG_ON() */
+               up_read(&mm->mmap_sem);
+               handle_fault_error(fault);
+               goto out;
+       }
+
        ret = handle_mm_fault(mm, vma, address, write);
        if (ret & VM_FAULT_ERROR) {
                /* failed to service fault */
index dafaf59dc3b82833fb78d55e8f194ff728999d35..286e890e7d64caa31867044f568e3a3cf6ce2ba9 100644 (file)
@@ -56,6 +56,7 @@
 #define IDR0_TTF_SHIFT                 2
 #define IDR0_TTF_MASK                  0x3
 #define IDR0_TTF_AARCH64               (2 << IDR0_TTF_SHIFT)
+#define IDR0_TTF_AARCH32_64            (3 << IDR0_TTF_SHIFT)
 #define IDR0_S1P                       (1 << 1)
 #define IDR0_S2P                       (1 << 0)
 
 #define CMDQ_TLBI_0_VMID_SHIFT         32
 #define CMDQ_TLBI_0_ASID_SHIFT         48
 #define CMDQ_TLBI_1_LEAF               (1UL << 0)
-#define CMDQ_TLBI_1_ADDR_MASK          ~0xfffUL
+#define CMDQ_TLBI_1_VA_MASK            ~0xfffUL
+#define CMDQ_TLBI_1_IPA_MASK           0xfffffffff000UL
 
 #define CMDQ_PRI_0_SSID_SHIFT          12
 #define CMDQ_PRI_0_SSID_MASK           0xfffffUL
@@ -770,11 +772,13 @@ static int arm_smmu_cmdq_build_cmd(u64 *cmd, struct arm_smmu_cmdq_ent *ent)
                break;
        case CMDQ_OP_TLBI_NH_VA:
                cmd[0] |= (u64)ent->tlbi.asid << CMDQ_TLBI_0_ASID_SHIFT;
-               /* Fallthrough */
+               cmd[1] |= ent->tlbi.leaf ? CMDQ_TLBI_1_LEAF : 0;
+               cmd[1] |= ent->tlbi.addr & CMDQ_TLBI_1_VA_MASK;
+               break;
        case CMDQ_OP_TLBI_S2_IPA:
                cmd[0] |= (u64)ent->tlbi.vmid << CMDQ_TLBI_0_VMID_SHIFT;
                cmd[1] |= ent->tlbi.leaf ? CMDQ_TLBI_1_LEAF : 0;
-               cmd[1] |= ent->tlbi.addr & CMDQ_TLBI_1_ADDR_MASK;
+               cmd[1] |= ent->tlbi.addr & CMDQ_TLBI_1_IPA_MASK;
                break;
        case CMDQ_OP_TLBI_NH_ASID:
                cmd[0] |= (u64)ent->tlbi.asid << CMDQ_TLBI_0_ASID_SHIFT;
@@ -2460,7 +2464,13 @@ static int arm_smmu_device_probe(struct arm_smmu_device *smmu)
        }
 
        /* We only support the AArch64 table format at present */
-       if ((reg & IDR0_TTF_MASK << IDR0_TTF_SHIFT) < IDR0_TTF_AARCH64) {
+       switch (reg & IDR0_TTF_MASK << IDR0_TTF_SHIFT) {
+       case IDR0_TTF_AARCH32_64:
+               smmu->ias = 40;
+               /* Fallthrough */
+       case IDR0_TTF_AARCH64:
+               break;
+       default:
                dev_err(smmu->dev, "AArch64 table format not supported!\n");
                return -ENXIO;
        }
@@ -2541,8 +2551,7 @@ static int arm_smmu_device_probe(struct arm_smmu_device *smmu)
                dev_warn(smmu->dev,
                         "failed to set DMA mask for table walker\n");
 
-       if (!smmu->ias)
-               smmu->ias = smmu->oas;
+       smmu->ias = max(smmu->ias, smmu->oas);
 
        dev_info(smmu->dev, "ias %lu-bit, oas %lu-bit (features 0x%08x)\n",
                 smmu->ias, smmu->oas, smmu->features);
index 2d7349a3ee1496408f051b4da8accebc8dd02ec1..d65cf42399e8e5aa0f856a1ab6869c041adc0c48 100644 (file)
@@ -2115,15 +2115,19 @@ static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
                                return -ENOMEM;
                        /* It is large page*/
                        if (largepage_lvl > 1) {
+                               unsigned long nr_superpages, end_pfn;
+
                                pteval |= DMA_PTE_LARGE_PAGE;
                                lvl_pages = lvl_to_nr_pages(largepage_lvl);
+
+                               nr_superpages = sg_res / lvl_pages;
+                               end_pfn = iov_pfn + nr_superpages * lvl_pages - 1;
+
                                /*
                                 * Ensure that old small page tables are
-                                * removed to make room for superpage,
-                                * if they exist.
+                                * removed to make room for superpage(s).
                                 */
-                               dma_pte_free_pagetable(domain, iov_pfn,
-                                                      iov_pfn + lvl_pages - 1);
+                               dma_pte_free_pagetable(domain, iov_pfn, end_pfn);
                        } else {
                                pteval &= ~(uint64_t)DMA_PTE_LARGE_PAGE;
                        }
@@ -2301,6 +2305,7 @@ static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu,
 
        if (ret) {
                spin_unlock_irqrestore(&device_domain_lock, flags);
+               free_devinfo_mem(info);
                return NULL;
        }
 
@@ -3215,6 +3220,8 @@ static struct iova *intel_alloc_iova(struct device *dev,
 
        /* Restrict dma_mask to the width that the iommu can handle */
        dma_mask = min_t(uint64_t, DOMAIN_MAX_ADDR(domain->gaw), dma_mask);
+       /* Ensure we reserve the whole size-aligned region */
+       nrpages = __roundup_pow_of_two(nrpages);
 
        if (!dmar_forcedac && dma_mask > DMA_BIT_MASK(32)) {
                /*
@@ -3711,7 +3718,7 @@ static inline int iommu_devinfo_cache_init(void)
 static int __init iommu_init_mempool(void)
 {
        int ret;
-       ret = iommu_iova_cache_init();
+       ret = iova_cache_get();
        if (ret)
                return ret;
 
@@ -3725,7 +3732,7 @@ static int __init iommu_init_mempool(void)
 
        kmem_cache_destroy(iommu_domain_cache);
 domain_error:
-       iommu_iova_cache_destroy();
+       iova_cache_put();
 
        return -ENOMEM;
 }
@@ -3734,7 +3741,7 @@ static void __init iommu_exit_mempool(void)
 {
        kmem_cache_destroy(iommu_devinfo_cache);
        kmem_cache_destroy(iommu_domain_cache);
-       iommu_iova_cache_destroy();
+       iova_cache_put();
 }
 
 static void quirk_ioat_snb_local_iommu(struct pci_dev *pdev)
index 73c07482f48763c5af3f0d43d73a2f04774bb74d..7df97777662d4d8a9284a8f2cae4cc0e8891210a 100644 (file)
@@ -202,9 +202,9 @@ typedef u64 arm_lpae_iopte;
 
 static bool selftest_running = false;
 
-static dma_addr_t __arm_lpae_dma_addr(struct device *dev, void *pages)
+static dma_addr_t __arm_lpae_dma_addr(void *pages)
 {
-       return phys_to_dma(dev, virt_to_phys(pages));
+       return (dma_addr_t)virt_to_phys(pages);
 }
 
 static void *__arm_lpae_alloc_pages(size_t size, gfp_t gfp,
@@ -223,10 +223,10 @@ static void *__arm_lpae_alloc_pages(size_t size, gfp_t gfp,
                        goto out_free;
                /*
                 * We depend on the IOMMU being able to work with any physical
-                * address directly, so if the DMA layer suggests it can't by
-                * giving us back some translation, that bodes very badly...
+                * address directly, so if the DMA layer suggests otherwise by
+                * translating or truncating them, that bodes very badly...
                 */
-               if (dma != __arm_lpae_dma_addr(dev, pages))
+               if (dma != virt_to_phys(pages))
                        goto out_unmap;
        }
 
@@ -243,10 +243,8 @@ out_free:
 static void __arm_lpae_free_pages(void *pages, size_t size,
                                  struct io_pgtable_cfg *cfg)
 {
-       struct device *dev = cfg->iommu_dev;
-
        if (!selftest_running)
-               dma_unmap_single(dev, __arm_lpae_dma_addr(dev, pages),
+               dma_unmap_single(cfg->iommu_dev, __arm_lpae_dma_addr(pages),
                                 size, DMA_TO_DEVICE);
        free_pages_exact(pages, size);
 }
@@ -254,12 +252,11 @@ static void __arm_lpae_free_pages(void *pages, size_t size,
 static void __arm_lpae_set_pte(arm_lpae_iopte *ptep, arm_lpae_iopte pte,
                               struct io_pgtable_cfg *cfg)
 {
-       struct device *dev = cfg->iommu_dev;
-
        *ptep = pte;
 
        if (!selftest_running)
-               dma_sync_single_for_device(dev, __arm_lpae_dma_addr(dev, ptep),
+               dma_sync_single_for_device(cfg->iommu_dev,
+                                          __arm_lpae_dma_addr(ptep),
                                           sizeof(pte), DMA_TO_DEVICE);
 }
 
@@ -629,6 +626,11 @@ arm_lpae_alloc_pgtable(struct io_pgtable_cfg *cfg)
        if (cfg->oas > ARM_LPAE_MAX_ADDR_BITS)
                return NULL;
 
+       if (!selftest_running && cfg->iommu_dev->dma_pfn_offset) {
+               dev_err(cfg->iommu_dev, "Cannot accommodate DMA offset for IOMMU page tables\n");
+               return NULL;
+       }
+
        data = kmalloc(sizeof(*data), GFP_KERNEL);
        if (!data)
                return NULL;
index b7c3d923f3e1c0569c42492d435b7c4d9a321caa..fa0adef32bd6d3a4af1b97ee3b1fb22dde6c225f 100644 (file)
  */
 
 #include <linux/iova.h>
+#include <linux/module.h>
 #include <linux/slab.h>
 
-static struct kmem_cache *iommu_iova_cache;
-
-int iommu_iova_cache_init(void)
-{
-       int ret = 0;
-
-       iommu_iova_cache = kmem_cache_create("iommu_iova",
-                                        sizeof(struct iova),
-                                        0,
-                                        SLAB_HWCACHE_ALIGN,
-                                        NULL);
-       if (!iommu_iova_cache) {
-               pr_err("Couldn't create iova cache\n");
-               ret = -ENOMEM;
-       }
-
-       return ret;
-}
-
-void iommu_iova_cache_destroy(void)
-{
-       kmem_cache_destroy(iommu_iova_cache);
-}
-
-struct iova *alloc_iova_mem(void)
-{
-       return kmem_cache_alloc(iommu_iova_cache, GFP_ATOMIC);
-}
-
-void free_iova_mem(struct iova *iova)
-{
-       kmem_cache_free(iommu_iova_cache, iova);
-}
-
 void
 init_iova_domain(struct iova_domain *iovad, unsigned long granule,
        unsigned long start_pfn, unsigned long pfn_32bit)
@@ -72,6 +39,7 @@ init_iova_domain(struct iova_domain *iovad, unsigned long granule,
        iovad->start_pfn = start_pfn;
        iovad->dma_32bit_pfn = pfn_32bit;
 }
+EXPORT_SYMBOL_GPL(init_iova_domain);
 
 static struct rb_node *
 __get_cached_rbnode(struct iova_domain *iovad, unsigned long *limit_pfn)
@@ -120,19 +88,14 @@ __cached_rbnode_delete_update(struct iova_domain *iovad, struct iova *free)
        }
 }
 
-/* Computes the padding size required, to make the
- * the start address naturally aligned on its size
+/*
+ * Computes the padding size required, to make the start address
+ * naturally aligned on the power-of-two order of its size
  */
-static int
-iova_get_pad_size(int size, unsigned int limit_pfn)
+static unsigned int
+iova_get_pad_size(unsigned int size, unsigned int limit_pfn)
 {
-       unsigned int pad_size = 0;
-       unsigned int order = ilog2(size);
-
-       if (order)
-               pad_size = (limit_pfn + 1) % (1 << order);
-
-       return pad_size;
+       return (limit_pfn + 1 - size) & (__roundup_pow_of_two(size) - 1);
 }
 
 static int __alloc_and_insert_iova_range(struct iova_domain *iovad,
@@ -242,6 +205,57 @@ iova_insert_rbtree(struct rb_root *root, struct iova *iova)
        rb_insert_color(&iova->node, root);
 }
 
+static struct kmem_cache *iova_cache;
+static unsigned int iova_cache_users;
+static DEFINE_MUTEX(iova_cache_mutex);
+
+struct iova *alloc_iova_mem(void)
+{
+       return kmem_cache_alloc(iova_cache, GFP_ATOMIC);
+}
+EXPORT_SYMBOL(alloc_iova_mem);
+
+void free_iova_mem(struct iova *iova)
+{
+       kmem_cache_free(iova_cache, iova);
+}
+EXPORT_SYMBOL(free_iova_mem);
+
+int iova_cache_get(void)
+{
+       mutex_lock(&iova_cache_mutex);
+       if (!iova_cache_users) {
+               iova_cache = kmem_cache_create(
+                       "iommu_iova", sizeof(struct iova), 0,
+                       SLAB_HWCACHE_ALIGN, NULL);
+               if (!iova_cache) {
+                       mutex_unlock(&iova_cache_mutex);
+                       printk(KERN_ERR "Couldn't create iova cache\n");
+                       return -ENOMEM;
+               }
+       }
+
+       iova_cache_users++;
+       mutex_unlock(&iova_cache_mutex);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(iova_cache_get);
+
+void iova_cache_put(void)
+{
+       mutex_lock(&iova_cache_mutex);
+       if (WARN_ON(!iova_cache_users)) {
+               mutex_unlock(&iova_cache_mutex);
+               return;
+       }
+       iova_cache_users--;
+       if (!iova_cache_users)
+               kmem_cache_destroy(iova_cache);
+       mutex_unlock(&iova_cache_mutex);
+}
+EXPORT_SYMBOL_GPL(iova_cache_put);
+
 /**
  * alloc_iova - allocates an iova
  * @iovad: - iova domain in question
@@ -265,12 +279,6 @@ alloc_iova(struct iova_domain *iovad, unsigned long size,
        if (!new_iova)
                return NULL;
 
-       /* If size aligned is set then round the size to
-        * to next power of two.
-        */
-       if (size_aligned)
-               size = __roundup_pow_of_two(size);
-
        ret = __alloc_and_insert_iova_range(iovad, size, limit_pfn,
                        new_iova, size_aligned);
 
@@ -281,6 +289,7 @@ alloc_iova(struct iova_domain *iovad, unsigned long size,
 
        return new_iova;
 }
+EXPORT_SYMBOL_GPL(alloc_iova);
 
 /**
  * find_iova - find's an iova for a given pfn
@@ -321,6 +330,7 @@ struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn)
        spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
        return NULL;
 }
+EXPORT_SYMBOL_GPL(find_iova);
 
 /**
  * __free_iova - frees the given iova
@@ -339,6 +349,7 @@ __free_iova(struct iova_domain *iovad, struct iova *iova)
        spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
        free_iova_mem(iova);
 }
+EXPORT_SYMBOL_GPL(__free_iova);
 
 /**
  * free_iova - finds and frees the iova for a given pfn
@@ -356,6 +367,7 @@ free_iova(struct iova_domain *iovad, unsigned long pfn)
                __free_iova(iovad, iova);
 
 }
+EXPORT_SYMBOL_GPL(free_iova);
 
 /**
  * put_iova_domain - destroys the iova doamin
@@ -378,6 +390,7 @@ void put_iova_domain(struct iova_domain *iovad)
        }
        spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
 }
+EXPORT_SYMBOL_GPL(put_iova_domain);
 
 static int
 __is_range_overlap(struct rb_node *node,
@@ -467,6 +480,7 @@ finish:
        spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
        return iova;
 }
+EXPORT_SYMBOL_GPL(reserve_iova);
 
 /**
  * copy_reserved_iova - copies the reserved between domains
@@ -493,6 +507,7 @@ copy_reserved_iova(struct iova_domain *from, struct iova_domain *to)
        }
        spin_unlock_irqrestore(&from->iova_rbtree_lock, flags);
 }
+EXPORT_SYMBOL_GPL(copy_reserved_iova);
 
 struct iova *
 split_and_remove_iova(struct iova_domain *iovad, struct iova *iova,
@@ -534,3 +549,6 @@ error:
                free_iova_mem(prev);
        return NULL;
 }
+
+MODULE_AUTHOR("Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>");
+MODULE_LICENSE("GPL");
index e9c6f2a5b52de0958ec334f0a011f3883edf6bf3..cd7d3bc78e345c49b733b9120c5a5bed2540583b 100644 (file)
@@ -65,12 +65,10 @@ static void combiner_unmask_irq(struct irq_data *data)
        __raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_SET);
 }
 
-static void combiner_handle_cascade_irq(unsigned int __irq,
-                                       struct irq_desc *desc)
+static void combiner_handle_cascade_irq(struct irq_desc *desc)
 {
        struct combiner_chip_data *chip_data = irq_desc_get_handler_data(desc);
        struct irq_chip *chip = irq_desc_get_chip(desc);
-       unsigned int irq = irq_desc_get_irq(desc);
        unsigned int cascade_irq, combiner_irq;
        unsigned long status;
 
@@ -88,7 +86,7 @@ static void combiner_handle_cascade_irq(unsigned int __irq,
        cascade_irq = irq_find_mapping(combiner_irq_domain, combiner_irq);
 
        if (unlikely(!cascade_irq))
-               handle_bad_irq(irq, desc);
+               handle_bad_irq(desc);
        else
                generic_handle_irq(cascade_irq);
 
@@ -165,7 +163,7 @@ static int combiner_irq_domain_map(struct irq_domain *d, unsigned int irq,
 
        irq_set_chip_and_handler(irq, &combiner_chip, handle_level_irq);
        irq_set_chip_data(irq, &combiner_data[hw >> 3]);
-       set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+       irq_set_probe(irq);
 
        return 0;
 }
index 39b72da0c1437fc4caf658a85c0e2ba62dc70694..389318a3be820a560dbc02c7b5e2bd9b37cdeb35 100644 (file)
@@ -200,7 +200,6 @@ static int armada_370_xp_msi_map(struct irq_domain *domain, unsigned int virq,
 {
        irq_set_chip_and_handler(virq, &armada_370_xp_msi_irq_chip,
                                 handle_simple_irq);
-       set_irq_flags(virq, IRQF_VALID);
 
        return 0;
 }
@@ -317,7 +316,8 @@ static int armada_370_xp_mpic_irq_map(struct irq_domain *h,
                irq_set_chip_and_handler(virq, &armada_370_xp_irq_chip,
                                        handle_level_irq);
        }
-       set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
+       irq_set_probe(virq);
+       irq_clear_status_flags(virq, IRQ_NOAUTOEN);
 
        return 0;
 }
@@ -447,8 +447,7 @@ static void armada_370_xp_handle_msi_irq(struct pt_regs *regs, bool is_chained)
 static void armada_370_xp_handle_msi_irq(struct pt_regs *r, bool b) {}
 #endif
 
-static void armada_370_xp_mpic_handle_cascade_irq(unsigned int irq,
-                                                 struct irq_desc *desc)
+static void armada_370_xp_mpic_handle_cascade_irq(struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_desc_get_chip(desc);
        unsigned long irqmap, irqn, irqsrc, cpuid;
index 9da9942ac83c9e4ce861e193061f0f29df8b5700..f6d680485beecaf0ec870a0d7492146e3fb72090 100644 (file)
@@ -88,28 +88,36 @@ static void aic5_mask(struct irq_data *d)
 {
        struct irq_domain *domain = d->domain;
        struct irq_domain_chip_generic *dgc = domain->gc;
-       struct irq_chip_generic *gc = dgc->gc[0];
+       struct irq_chip_generic *bgc = dgc->gc[0];
+       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
 
-       /* Disable interrupt on AIC5 */
-       irq_gc_lock(gc);
+       /*
+        * Disable interrupt on AIC5. We always take the lock of the
+        * first irq chip as all chips share the same registers.
+        */
+       irq_gc_lock(bgc);
        irq_reg_writel(gc, d->hwirq, AT91_AIC5_SSR);
        irq_reg_writel(gc, 1, AT91_AIC5_IDCR);
        gc->mask_cache &= ~d->mask;
-       irq_gc_unlock(gc);
+       irq_gc_unlock(bgc);
 }
 
 static void aic5_unmask(struct irq_data *d)
 {
        struct irq_domain *domain = d->domain;
        struct irq_domain_chip_generic *dgc = domain->gc;
-       struct irq_chip_generic *gc = dgc->gc[0];
+       struct irq_chip_generic *bgc = dgc->gc[0];
+       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
 
-       /* Enable interrupt on AIC5 */
-       irq_gc_lock(gc);
+       /*
+        * Enable interrupt on AIC5. We always take the lock of the
+        * first irq chip as all chips share the same registers.
+        */
+       irq_gc_lock(bgc);
        irq_reg_writel(gc, d->hwirq, AT91_AIC5_SSR);
        irq_reg_writel(gc, 1, AT91_AIC5_IECR);
        gc->mask_cache |= d->mask;
-       irq_gc_unlock(gc);
+       irq_gc_unlock(bgc);
 }
 
 static int aic5_retrigger(struct irq_data *d)
index ed4ca9deca7030bf202b02a1034f71b229a3c2ff..bf9cc5f2e839e845fe1ce65caa672b6212d3ffbc 100644 (file)
@@ -96,7 +96,7 @@ struct armctrl_ic {
 static struct armctrl_ic intc __read_mostly;
 static void __exception_irq_entry bcm2835_handle_irq(
        struct pt_regs *regs);
-static void bcm2836_chained_handle_irq(unsigned int irq, struct irq_desc *desc);
+static void bcm2836_chained_handle_irq(struct irq_desc *desc);
 
 static void armctrl_mask_irq(struct irq_data *d)
 {
@@ -166,7 +166,7 @@ static int __init armctrl_of_init(struct device_node *node,
                        BUG_ON(irq <= 0);
                        irq_set_chip_and_handler(irq, &armctrl_chip,
                                handle_level_irq);
-                       set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+                       irq_set_probe(irq);
                }
        }
 
@@ -245,7 +245,7 @@ static void __exception_irq_entry bcm2835_handle_irq(
                handle_IRQ(irq_linear_revmap(intc.domain, hwirq), regs);
 }
 
-static void bcm2836_chained_handle_irq(unsigned int irq, struct irq_desc *desc)
+static void bcm2836_chained_handle_irq(struct irq_desc *desc)
 {
        u32 hwirq;
 
index 409bdc6366c20a3ba909aae5b770dfe71dac08d9..0fea985ef1dc2da87d0cc7b0fe83ccf57a85aed2 100644 (file)
@@ -115,7 +115,7 @@ static inline void l1_writel(u32 val, void __iomem *reg)
                writel(val, reg);
 }
 
-static void bcm7038_l1_irq_handle(unsigned int irq, struct irq_desc *desc)
+static void bcm7038_l1_irq_handle(struct irq_desc *desc)
 {
        struct bcm7038_l1_chip *intc = irq_desc_get_handler_data(desc);
        struct bcm7038_l1_cpu *cpu;
index d3f976913a6fbd9bb2af3ff4c4b1e906f5bae61e..61b18ab33ad9d0ec25e7fcf58fa69645cc521d17 100644 (file)
@@ -56,7 +56,7 @@ struct bcm7120_l2_intc_data {
        const __be32 *map_mask_prop;
 };
 
-static void bcm7120_l2_intc_irq_handle(unsigned int irq, struct irq_desc *desc)
+static void bcm7120_l2_intc_irq_handle(struct irq_desc *desc)
 {
        struct bcm7120_l1_intc_data *data = irq_desc_get_handler_data(desc);
        struct bcm7120_l2_intc_data *b = data->b;
index aedda06191eb08cdf0a688a9a7fbe63959e021f1..65cd341f331a5e5ae73f8404ce4d2b4cb19e796c 100644 (file)
@@ -49,13 +49,12 @@ struct brcmstb_l2_intc_data {
        u32 saved_mask; /* for suspend/resume */
 };
 
-static void brcmstb_l2_intc_irq_handle(unsigned int __irq,
-                                      struct irq_desc *desc)
+static void brcmstb_l2_intc_irq_handle(struct irq_desc *desc)
 {
        struct brcmstb_l2_intc_data *b = irq_desc_get_handler_data(desc);
        struct irq_chip_generic *gc = irq_get_domain_generic_chip(b->domain, 0);
        struct irq_chip *chip = irq_desc_get_chip(desc);
-       unsigned int irq = irq_desc_get_irq(desc);
+       unsigned int irq;
        u32 status;
 
        chained_irq_enter(chip, desc);
@@ -65,7 +64,7 @@ static void brcmstb_l2_intc_irq_handle(unsigned int __irq,
 
        if (status == 0) {
                raw_spin_lock(&desc->lock);
-               handle_bad_irq(irq, desc);
+               handle_bad_irq(desc);
                raw_spin_unlock(&desc->lock);
                goto out;
        }
index 2dd929eed9e0516fca48845f83720578622609be..eb5eb0cd414d21a78e6bbc59704c809287dffdd0 100644 (file)
@@ -132,14 +132,14 @@ static int __init clps711x_intc_irq_map(struct irq_domain *h, unsigned int virq,
                                        irq_hw_number_t hw)
 {
        irq_flow_handler_t handler = handle_level_irq;
-       unsigned int flags = IRQF_VALID | IRQF_PROBE;
+       unsigned int flags = 0;
 
        if (!clps711x_irqs[hw].flags)
                return 0;
 
        if (clps711x_irqs[hw].flags & CLPS711X_FLAG_FIQ) {
                handler = handle_bad_irq;
-               flags |= IRQF_NOAUTOEN;
+               flags |= IRQ_NOAUTOEN;
        } else if (clps711x_irqs[hw].eoi) {
                handler = handle_fasteoi_irq;
        }
@@ -149,7 +149,7 @@ static int __init clps711x_intc_irq_map(struct irq_domain *h, unsigned int virq,
                writel_relaxed(0, clps711x_intc->base + clps711x_irqs[hw].eoi);
 
        irq_set_chip_and_handler(virq, &clps711x_intc_chip, handler);
-       set_irq_flags(virq, flags);
+       irq_modify_status(virq, IRQ_NOPROBE, flags);
 
        return 0;
 }
index efd95d9955e7e3b5a0be532f36fa64c8a7c4da47..052f266364c0cd1a3af91511a0eb87f11d8b43ec 100644 (file)
@@ -26,7 +26,7 @@
 #define APB_INT_FINALSTATUS_H  0x34
 #define APB_INT_BASE_OFFSET    0x04
 
-static void dw_apb_ictl_handler(unsigned int irq, struct irq_desc *desc)
+static void dw_apb_ictl_handler(struct irq_desc *desc)
 {
        struct irq_domain *d = irq_desc_get_handler_data(desc);
        struct irq_chip *chip = irq_desc_get_chip(desc);
index db04fc1f56b2578203964a13c48548376af8a7fb..12985daa66ab31c9c7981e65ea0926938e5662fa 100644 (file)
@@ -95,8 +95,8 @@ static void gicv2m_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
        struct v2m_data *v2m = irq_data_get_irq_chip_data(data);
        phys_addr_t addr = v2m->res.start + V2M_MSI_SETSPI_NS;
 
-       msg->address_hi = (u32) (addr >> 32);
-       msg->address_lo = (u32) (addr);
+       msg->address_hi = upper_32_bits(addr);
+       msg->address_lo = lower_32_bits(addr);
        msg->data = data->hwirq;
 }
 
index cf351c6374645e7b0e4fe982a937d49b4904cfe9..a7c8c9ffbafd3503228a6c4e63c6870b5d9c784c 100644 (file)
@@ -62,7 +62,7 @@ static int its_get_pci_alias(struct pci_dev *pdev, u16 alias, void *data)
 
        dev_alias->dev_id = alias;
        if (pdev != dev_alias->pdev)
-               dev_alias->count += its_pci_msi_vec_count(dev_alias->pdev);
+               dev_alias->count += its_pci_msi_vec_count(pdev);
 
        return 0;
 }
index 26b55c53755f0db82c5b4cbcd1c16a9beb5c5109..25ceae9f7348b3208bdd6dec0048a88d4ce34f73 100644 (file)
@@ -719,6 +719,9 @@ static unsigned long *its_lpi_alloc_chunks(int nr_irqs, int *base, int *nr_ids)
 out:
        spin_unlock(&lpi_lock);
 
+       if (!bitmap)
+               *base = *nr_ids = 0;
+
        return bitmap;
 }
 
@@ -898,8 +901,10 @@ retry_baser:
                         * non-cacheable as well.
                         */
                        shr = tmp & GITS_BASER_SHAREABILITY_MASK;
-                       if (!shr)
+                       if (!shr) {
                                cache = GITS_BASER_nC;
+                               __flush_dcache_area(base, alloc_size);
+                       }
                        goto retry_baser;
                }
 
@@ -1140,6 +1145,8 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
                return NULL;
        }
 
+       __flush_dcache_area(itt, sz);
+
        dev->its = its;
        dev->itt = itt;
        dev->nr_ites = nr_ites;
index 7deed6ef54c2eaf048538e46ecbcb3ec6d5ff91c..36ecfc870e5a6cb86698cb218ac00cccc491e299 100644 (file)
@@ -70,11 +70,6 @@ static inline int gic_irq_in_rdist(struct irq_data *d)
        return gic_irq(d) < 32;
 }
 
-static inline bool forwarded_irq(struct irq_data *d)
-{
-       return d->handler_data != NULL;
-}
-
 static inline void __iomem *gic_dist_base(struct irq_data *d)
 {
        if (gic_irq_in_rdist(d))        /* SGI+PPI -> SGI_base for this CPU */
@@ -249,7 +244,7 @@ static void gic_eoimode1_mask_irq(struct irq_data *d)
         * disabled/masked will not get "stuck", because there is
         * noone to deactivate it (guest is being terminated).
         */
-       if (forwarded_irq(d))
+       if (irqd_is_forwarded_to_vcpu(d))
                gic_poke_irq(d, GICD_ICACTIVER);
 }
 
@@ -324,7 +319,7 @@ static void gic_eoimode1_eoi_irq(struct irq_data *d)
         * No need to deactivate an LPI, or an interrupt that
         * is is getting forwarded to a vcpu.
         */
-       if (gic_irq(d) >= 8192 || forwarded_irq(d))
+       if (gic_irq(d) >= 8192 || irqd_is_forwarded_to_vcpu(d))
                return;
        gic_write_dir(gic_irq(d));
 }
@@ -357,7 +352,10 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
 
 static int gic_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu)
 {
-       d->handler_data = vcpu;
+       if (vcpu)
+               irqd_set_forwarded_to_vcpu(d);
+       else
+               irqd_clr_forwarded_to_vcpu(d);
        return 0;
 }
 
@@ -754,13 +752,13 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
                irq_set_percpu_devid(irq);
                irq_domain_set_info(d, irq, hw, chip, d->host_data,
                                    handle_percpu_devid_irq, NULL, NULL);
-               set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN);
+               irq_set_status_flags(irq, IRQ_NOAUTOEN);
        }
        /* SPIs */
        if (hw >= 32 && hw < gic_data.irq_nr) {
                irq_domain_set_info(d, irq, hw, chip, d->host_data,
                                    handle_fasteoi_irq, NULL, NULL);
-               set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+               irq_set_probe(irq);
        }
        /* LPIs */
        if (hw >= 8192 && hw < GIC_ID_NR) {
@@ -768,7 +766,6 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
                        return -EPERM;
                irq_domain_set_info(d, irq, hw, chip, d->host_data,
                                    handle_fasteoi_irq, NULL, NULL);
-               set_irq_flags(irq, IRQF_VALID);
        }
 
        return 0;
index e6b7ed537952949eedb43105bcdd555209b62711..982c09c2d79171d21355c75153b4de87f4a1bee2 100644 (file)
@@ -145,29 +145,10 @@ static inline bool cascading_gic_irq(struct irq_data *d)
        void *data = irq_data_get_irq_handler_data(d);
 
        /*
-        * If handler_data pointing to one of the secondary GICs, then
-        * this is a cascading interrupt, and it cannot possibly be
-        * forwarded.
+        * If handler_data is set, this is a cascading interrupt, and
+        * it cannot possibly be forwarded.
         */
-       if (data >= (void *)(gic_data + 1) &&
-           data <  (void *)(gic_data + MAX_GIC_NR))
-               return true;
-
-       return false;
-}
-
-static inline bool forwarded_irq(struct irq_data *d)
-{
-       /*
-        * A forwarded interrupt:
-        * - is on the primary GIC
-        * - has its handler_data set to a value
-        * - that isn't a secondary GIC
-        */
-       if (d->handler_data && !cascading_gic_irq(d))
-               return true;
-
-       return false;
+       return data != NULL;
 }
 
 /*
@@ -201,7 +182,7 @@ static void gic_eoimode1_mask_irq(struct irq_data *d)
         * disabled/masked will not get "stuck", because there is
         * noone to deactivate it (guest is being terminated).
         */
-       if (forwarded_irq(d))
+       if (irqd_is_forwarded_to_vcpu(d))
                gic_poke_irq(d, GIC_DIST_ACTIVE_CLEAR);
 }
 
@@ -218,7 +199,7 @@ static void gic_eoi_irq(struct irq_data *d)
 static void gic_eoimode1_eoi_irq(struct irq_data *d)
 {
        /* Do not deactivate an IRQ forwarded to a vcpu. */
-       if (forwarded_irq(d))
+       if (irqd_is_forwarded_to_vcpu(d))
                return;
 
        writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_DEACTIVATE);
@@ -296,7 +277,10 @@ static int gic_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu)
        if (cascading_gic_irq(d))
                return -EINVAL;
 
-       d->handler_data = vcpu;
+       if (vcpu)
+               irqd_set_forwarded_to_vcpu(d);
+       else
+               irqd_clr_forwarded_to_vcpu(d);
        return 0;
 }
 
@@ -357,7 +341,7 @@ static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
        } while (1);
 }
 
-static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
+static void gic_handle_cascade_irq(struct irq_desc *desc)
 {
        struct gic_chip_data *chip_data = irq_desc_get_handler_data(desc);
        struct irq_chip *chip = irq_desc_get_chip(desc);
@@ -376,7 +360,7 @@ static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
 
        cascade_irq = irq_find_mapping(chip_data->domain, gic_irq);
        if (unlikely(gic_irq < 32 || gic_irq > 1020))
-               handle_bad_irq(cascade_irq, desc);
+               handle_bad_irq(desc);
        else
                generic_handle_irq(cascade_irq);
 
@@ -906,11 +890,11 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
                irq_set_percpu_devid(irq);
                irq_domain_set_info(d, irq, hw, chip, d->host_data,
                                    handle_percpu_devid_irq, NULL, NULL);
-               set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN);
+               irq_set_status_flags(irq, IRQ_NOAUTOEN);
        } else {
                irq_domain_set_info(d, irq, hw, chip, d->host_data,
                                    handle_fasteoi_irq, NULL, NULL);
-               set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+               irq_set_probe(irq);
        }
        return 0;
 }
@@ -1119,12 +1103,49 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
 #ifdef CONFIG_OF
 static int gic_cnt __initdata;
 
+static bool gic_check_eoimode(struct device_node *node, void __iomem **base)
+{
+       struct resource cpuif_res;
+
+       of_address_to_resource(node, 1, &cpuif_res);
+
+       if (!is_hyp_mode_available())
+               return false;
+       if (resource_size(&cpuif_res) < SZ_8K)
+               return false;
+       if (resource_size(&cpuif_res) == SZ_128K) {
+               u32 val_low, val_high;
+
+               /*
+                * Verify that we have the first 4kB of a GIC400
+                * aliased over the first 64kB by checking the
+                * GICC_IIDR register on both ends.
+                */
+               val_low = readl_relaxed(*base + GIC_CPU_IDENT);
+               val_high = readl_relaxed(*base + GIC_CPU_IDENT + 0xf000);
+               if ((val_low & 0xffff0fff) != 0x0202043B ||
+                   val_low != val_high)
+                       return false;
+
+               /*
+                * Move the base up by 60kB, so that we have a 8kB
+                * contiguous region, which allows us to use GICC_DIR
+                * at its normal offset. Please pass me that bucket.
+                */
+               *base += 0xf000;
+               cpuif_res.start += 0xf000;
+               pr_warn("GIC: Adjusting CPU interface base to %pa",
+                       &cpuif_res.start);
+       }
+
+       return true;
+}
+
 static int __init
 gic_of_init(struct device_node *node, struct device_node *parent)
 {
        void __iomem *cpu_base;
        void __iomem *dist_base;
-       struct resource cpu_res;
        u32 percpu_offset;
        int irq;
 
@@ -1137,14 +1158,11 @@ gic_of_init(struct device_node *node, struct device_node *parent)
        cpu_base = of_iomap(node, 1);
        WARN(!cpu_base, "unable to map gic cpu registers\n");
 
-       of_address_to_resource(node, 1, &cpu_res);
-
        /*
         * Disable split EOI/Deactivate if either HYP is not available
         * or the CPU interface is too small.
         */
-       if (gic_cnt == 0 && (!is_hyp_mode_available() ||
-                            resource_size(&cpu_res) < SZ_8K))
+       if (gic_cnt == 0 && !gic_check_eoimode(node, &cpu_base))
                static_key_slow_dec(&supports_deactivate);
 
        if (of_property_read_u32(node, "cpu-offset", &percpu_offset))
index a0128c7c98dd5d6e62335894b3369a2709856248..8f3ca8f3a62b615b2d670851dd8afe1d75904bee 100644 (file)
@@ -307,11 +307,11 @@ static int hip04_irq_domain_map(struct irq_domain *d, unsigned int irq,
                irq_set_percpu_devid(irq);
                irq_set_chip_and_handler(irq, &hip04_irq_chip,
                                         handle_percpu_devid_irq);
-               set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN);
+               irq_set_status_flags(irq, IRQ_NOAUTOEN);
        } else {
                irq_set_chip_and_handler(irq, &hip04_irq_chip,
                                         handle_fasteoi_irq);
-               set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+               irq_set_probe(irq);
        }
        irq_set_chip_data(irq, d->host_data);
        return 0;
index 4836102ba31205ddc5643e1bfacc24e4cd81eacb..e484fd2553210f55fd0eb72375f4ada1511c7fec 100644 (file)
@@ -352,7 +352,7 @@ void __init init_i8259_irqs(void)
        __init_i8259_irqs(NULL);
 }
 
-static void i8259_irq_dispatch(unsigned int __irq, struct irq_desc *desc)
+static void i8259_irq_dispatch(struct irq_desc *desc)
 {
        struct irq_domain *domain = irq_desc_get_handler_data(desc);
        int hwirq = i8259_irq();
index 841604b81004f415473a91f970ae74a02d3a8052..c02d29c9dc05b77aa4ed62083ef22fbdf5feaea8 100644 (file)
@@ -218,7 +218,7 @@ static int pdc_irq_set_wake(struct irq_data *data, unsigned int on)
        return 0;
 }
 
-static void pdc_intc_perip_isr(unsigned int __irq, struct irq_desc *desc)
+static void pdc_intc_perip_isr(struct irq_desc *desc)
 {
        unsigned int irq = irq_desc_get_irq(desc);
        struct pdc_intc_priv *priv;
@@ -240,7 +240,7 @@ found:
        generic_handle_irq(irq_no);
 }
 
-static void pdc_intc_syswake_isr(unsigned int irq, struct irq_desc *desc)
+static void pdc_intc_syswake_isr(struct irq_desc *desc)
 {
        struct pdc_intc_priv *priv;
        unsigned int syswake, irq_no;
index c1517267b5dbcf48aac50c9930db4c54cec762ae..deb89d63a728d214bfbb3470eb25b1227164acac 100644 (file)
@@ -83,7 +83,7 @@ static void keystone_irq_ack(struct irq_data *d)
        /* nothing to do here */
 }
 
-static void keystone_irq_handler(unsigned __irq, struct irq_desc *desc)
+static void keystone_irq_handler(struct irq_desc *desc)
 {
        unsigned int irq = irq_desc_get_irq(desc);
        struct keystone_irq_device *kirq = irq_desc_get_handler_data(desc);
@@ -127,7 +127,7 @@ static int keystone_irq_map(struct irq_domain *h, unsigned int virq,
 
        irq_set_chip_data(virq, kirq);
        irq_set_chip_and_handler(virq, &kirq->chip, handle_level_irq);
-       set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
+       irq_set_probe(virq);
        return 0;
 }
 
index 5f4c52928d1671b99cfc759552562bd5b8d09691..8c38b3d92e1cdb4a101a4abae331c2d9eaae3391 100644 (file)
@@ -446,7 +446,7 @@ static int meta_intc_irq_set_type(struct irq_data *data, unsigned int flow_type)
  * Whilst using TR2 to detect external interrupts is a software convention it is
  * (hopefully) unlikely to change.
  */
-static void meta_intc_irq_demux(unsigned int irq, struct irq_desc *desc)
+static void meta_intc_irq_demux(struct irq_desc *desc)
 {
        struct meta_intc_priv *priv = &meta_intc_priv;
        irq_hw_number_t hw;
index 3d23ce3edb5cccc8b50073af72633e0b3b3ed11f..a5f053bd2f443301a3bf62a9c30c523cded309cd 100644 (file)
@@ -220,7 +220,7 @@ static int metag_internal_irq_set_affinity(struct irq_data *data,
  *     occurred. It is this function's job to demux this irq and
  *     figure out exactly which trigger needs servicing.
  */
-static void metag_internal_irq_demux(unsigned int irq, struct irq_desc *desc)
+static void metag_internal_irq_demux(struct irq_desc *desc)
 {
        struct metag_internal_irq_priv *priv = irq_desc_get_handler_data(desc);
        irq_hw_number_t hw;
index 1764bcf8ee6bedc5619abec9f319b9ba5ca5f441..aeaa061f0dbfd3694d8a9f890822eba266e2e4e0 100644 (file)
@@ -320,6 +320,14 @@ static void gic_handle_shared_int(bool chained)
                intrmask[i] = gic_read(intrmask_reg);
                pending_reg += gic_reg_step;
                intrmask_reg += gic_reg_step;
+
+               if (!config_enabled(CONFIG_64BIT) || mips_cm_is64)
+                       continue;
+
+               pending[i] |= (u64)gic_read(pending_reg) << 32;
+               intrmask[i] |= (u64)gic_read(intrmask_reg) << 32;
+               pending_reg += gic_reg_step;
+               intrmask_reg += gic_reg_step;
        }
 
        bitmap_and(pending, pending, intrmask, gic_shared_intrs);
@@ -426,7 +434,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
        spin_lock_irqsave(&gic_lock, flags);
 
        /* Re-route this IRQ */
-       gic_map_to_vpe(irq, cpumask_first(&tmp));
+       gic_map_to_vpe(irq, mips_cm_vp_id(cpumask_first(&tmp)));
 
        /* Update the pcpu_masks */
        for (i = 0; i < NR_CPUS; i++)
@@ -546,7 +554,7 @@ static void __gic_irq_dispatch(void)
        gic_handle_shared_int(false);
 }
 
-static void gic_irq_dispatch(unsigned int irq, struct irq_desc *desc)
+static void gic_irq_dispatch(struct irq_desc *desc)
 {
        gic_handle_local_int(true);
        gic_handle_shared_int(true);
@@ -599,7 +607,7 @@ static __init void gic_ipi_init_one(unsigned int intr, int cpu,
                                      GIC_SHARED_TO_HWIRQ(intr));
        int i;
 
-       gic_map_to_vpe(intr, cpu);
+       gic_map_to_vpe(intr, mips_cm_vp_id(cpu));
        for (i = 0; i < NR_CPUS; i++)
                clear_bit(intr, pcpu_masks[i].pcpu_mask);
        set_bit(intr, pcpu_masks[cpu].pcpu_mask);
index 781ed6e71dbb3d1343440229b725db4e5eca3e1b..013fc9659a842ba04ee8e238b9958a283108ece5 100644 (file)
@@ -129,7 +129,7 @@ struct irq_chip icu_irq_chip = {
        .irq_unmask     = icu_unmask_irq,
 };
 
-static void icu_mux_irq_demux(unsigned int __irq, struct irq_desc *desc)
+static void icu_mux_irq_demux(struct irq_desc *desc)
 {
        unsigned int irq = irq_desc_get_irq(desc);
        struct irq_domain *domain;
@@ -164,7 +164,6 @@ static int mmp_irq_domain_map(struct irq_domain *d, unsigned int irq,
                              irq_hw_number_t hw)
 {
        irq_set_chip_and_handler(irq, &icu_irq_chip, handle_level_irq);
-       set_irq_flags(irq, IRQF_VALID);
        return 0;
 }
 
@@ -234,7 +233,6 @@ void __init icu_init_irq(void)
        for (irq = 0; irq < 64; irq++) {
                icu_mask_irq(irq_get_irq_data(irq));
                irq_set_chip_and_handler(irq, &icu_irq_chip, handle_level_irq);
-               set_irq_flags(irq, IRQF_VALID);
        }
        irq_set_default_host(icu_data[0].domain);
        set_handle_irq(mmp_handle_irq);
@@ -337,7 +335,6 @@ void __init mmp2_init_icu(void)
                        irq_set_chip_and_handler(irq, &icu_irq_chip,
                                                 handle_level_irq);
                }
-               set_irq_flags(irq, IRQF_VALID);
        }
        irq_set_default_host(icu_data[0].domain);
        set_handle_irq(mmp2_handle_irq);
index 1faf812f3dc8e4a8da4e8d9a2b4f214216705041..604df63e2edf6f9706db28d08bf559a0347e8bd8 100644 (file)
@@ -84,7 +84,6 @@ static int icoll_irq_domain_map(struct irq_domain *d, unsigned int virq,
                                irq_hw_number_t hw)
 {
        irq_set_chip_and_handler(virq, &mxs_icoll_chip, handle_level_irq);
-       set_irq_flags(virq, IRQF_VALID);
 
        return 0;
 }
index 5ea999a724b5db93ade94d5a8daa57f7b19da55b..be4c5a8c96593ac6c218f05283811e5cfee1a158 100644 (file)
@@ -106,7 +106,7 @@ IRQCHIP_DECLARE(orion_intc, "marvell,orion-intc", orion_irq_init);
 #define ORION_BRIDGE_IRQ_CAUSE 0x00
 #define ORION_BRIDGE_IRQ_MASK  0x04
 
-static void orion_bridge_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void orion_bridge_irq_handler(struct irq_desc *desc)
 {
        struct irq_domain *d = irq_desc_get_handler_data(desc);
 
index 0670ab4e3897bf612eb9e932a31ebc378cd3b803..9525335723f68f7e4c408d81a6538dc8e72a2b5f 100644 (file)
@@ -283,6 +283,9 @@ static int intc_irqpin_irq_set_type(struct irq_data *d, unsigned int type)
 static int intc_irqpin_irq_set_wake(struct irq_data *d, unsigned int on)
 {
        struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d);
+       int hw_irq = irqd_to_hwirq(d);
+
+       irq_set_irq_wake(p->irq[hw_irq].requested_irq, on);
 
        if (!p->clk)
                return 0;
@@ -332,6 +335,12 @@ static irqreturn_t intc_irqpin_shared_irq_handler(int irq, void *dev_id)
        return status;
 }
 
+/*
+ * This lock class tells lockdep that INTC External IRQ Pin irqs are in a
+ * different category than their parents, so it won't report false recursion.
+ */
+static struct lock_class_key intc_irqpin_irq_lock_class;
+
 static int intc_irqpin_irq_domain_map(struct irq_domain *h, unsigned int virq,
                                      irq_hw_number_t hw)
 {
@@ -342,8 +351,8 @@ static int intc_irqpin_irq_domain_map(struct irq_domain *h, unsigned int virq,
 
        intc_irqpin_dbg(&p->irq[hw], "map");
        irq_set_chip_data(virq, h->host_data);
+       irq_set_lockdep_class(virq, &intc_irqpin_irq_lock_class);
        irq_set_chip_and_handler(virq, &p->irq_chip, handle_level_irq);
-       set_irq_flags(virq, IRQF_VALID); /* kill me now */
        return 0;
 }
 
index 2aa3add711a6612af6c1653c976a043e743d9058..35bf97ba4a3d196db74ff5835dc9c59fb056c2af 100644 (file)
@@ -121,6 +121,9 @@ static int irqc_irq_set_type(struct irq_data *d, unsigned int type)
 static int irqc_irq_set_wake(struct irq_data *d, unsigned int on)
 {
        struct irqc_priv *p = irq_data_get_irq_chip_data(d);
+       int hw_irq = irqd_to_hwirq(d);
+
+       irq_set_irq_wake(p->irq[hw_irq].requested_irq, on);
 
        if (!p->clk)
                return 0;
@@ -150,6 +153,12 @@ static irqreturn_t irqc_irq_handler(int irq, void *dev_id)
        return IRQ_NONE;
 }
 
+/*
+ * This lock class tells lockdep that IRQC irqs are in a different
+ * category than their parents, so it won't report false recursion.
+ */
+static struct lock_class_key irqc_irq_lock_class;
+
 static int irqc_irq_domain_map(struct irq_domain *h, unsigned int virq,
                               irq_hw_number_t hw)
 {
@@ -157,6 +166,7 @@ static int irqc_irq_domain_map(struct irq_domain *h, unsigned int virq,
 
        irqc_dbg(&p->irq[hw], "map");
        irq_set_chip_data(virq, h->host_data);
+       irq_set_lockdep_class(virq, &irqc_irq_lock_class);
        irq_set_chip_and_handler(virq, &p->irq_chip, handle_level_irq);
        return 0;
 }
index 506d9f20ca51950e481148c4b3d91c49e1766173..7154b011ddd2f65a65f7079bfe88783c50d0d373 100644 (file)
@@ -298,7 +298,7 @@ static struct irq_chip s3c_irq_eint0t4 = {
        .irq_set_type   = s3c_irqext0_type,
 };
 
-static void s3c_irq_demux(unsigned int __irq, struct irq_desc *desc)
+static void s3c_irq_demux(struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_desc_get_chip(desc);
        struct s3c_irq_data *irq_data = irq_desc_get_chip_data(desc);
@@ -466,13 +466,11 @@ static int s3c24xx_irq_map(struct irq_domain *h, unsigned int virq,
 
        irq_set_chip_data(virq, irq_data);
 
-       set_irq_flags(virq, IRQF_VALID);
-
        if (parent_intc && irq_data->type != S3C_IRQTYPE_NONE) {
                if (irq_data->parent_irq > 31) {
                        pr_err("irq-s3c24xx: parent irq %lu is out of range\n",
                               irq_data->parent_irq);
-                       goto err;
+                       return -EINVAL;
                }
 
                parent_irq_data = &parent_intc->irqs[irq_data->parent_irq];
@@ -485,18 +483,12 @@ static int s3c24xx_irq_map(struct irq_domain *h, unsigned int virq,
                if (!irqno) {
                        pr_err("irq-s3c24xx: could not find mapping for parent irq %lu\n",
                               irq_data->parent_irq);
-                       goto err;
+                       return -EINVAL;
                }
                irq_set_chained_handler(irqno, s3c_irq_demux);
        }
 
        return 0;
-
-err:
-       set_irq_flags(virq, 0);
-
-       /* the only error can result from bad mapping data*/
-       return -EINVAL;
 }
 
 static const struct irq_domain_ops s3c24xx_irq_ops = {
@@ -1174,8 +1166,6 @@ static int s3c24xx_irq_map_of(struct irq_domain *h, unsigned int virq,
 
        irq_set_chip_data(virq, irq_data);
 
-       set_irq_flags(virq, IRQF_VALID);
-
        return 0;
 }
 
index 4ad3e7c69aa779e2f53b039fb1138807ce9f1ae2..0704362f4c824c6ba2b87e42353f0481bcff36e5 100644 (file)
@@ -83,7 +83,7 @@ static int sun4i_irq_map(struct irq_domain *d, unsigned int virq,
                         irq_hw_number_t hw)
 {
        irq_set_chip_and_handler(virq, &sun4i_irq_chip, handle_fasteoi_irq);
-       set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
+       irq_set_probe(virq);
 
        return 0;
 }
index 772a82cacbf7a7b2cbb37b263327f86848413d88..c143dd58410c64cc97d5afcc5442a45d5b60ebf9 100644 (file)
@@ -58,7 +58,7 @@ static inline u32 sunxi_sc_nmi_read(struct irq_chip_generic *gc, u32 off)
        return irq_reg_readl(gc, off);
 }
 
-static void sunxi_sc_nmi_handle_irq(unsigned int irq, struct irq_desc *desc)
+static void sunxi_sc_nmi_handle_irq(struct irq_desc *desc)
 {
        struct irq_domain *domain = irq_desc_get_handler_data(desc);
        struct irq_chip *chip = irq_desc_get_chip(desc);
index 3318296613669c1c489f848ac36e399760a0d312..848d782a2a3bdc6a7d3d3c66732da1f205cc8581 100644 (file)
@@ -97,7 +97,7 @@ static int tb10x_irq_set_type(struct irq_data *data, unsigned int flow_type)
        return IRQ_SET_MASK_OK;
 }
 
-static void tb10x_irq_cascade(unsigned int __irq, struct irq_desc *desc)
+static void tb10x_irq_cascade(struct irq_desc *desc)
 {
        struct irq_domain *domain = irq_desc_get_handler_data(desc);
        unsigned int irq = irq_desc_get_irq(desc);
index 2fd89eb88f3a29bc716ec1daf76ad4085e6a743d..fd88e687791aa8cc5a4249f550b2caa161eef46b 100644 (file)
@@ -214,6 +214,7 @@ static struct irq_chip tegra_ictlr_chip = {
        .irq_unmask             = tegra_unmask,
        .irq_retrigger          = tegra_retrigger,
        .irq_set_wake           = tegra_set_wake,
+       .irq_set_type           = irq_chip_set_type_parent,
        .flags                  = IRQCHIP_MASK_ON_SUSPEND,
 #ifdef CONFIG_SMP
        .irq_set_affinity       = irq_chip_set_affinity_parent,
index 16123f688768f24585653171b87de1785b764400..598ab3f0e0ac54b79f1438c2193f8bc112949975 100644 (file)
@@ -65,19 +65,19 @@ static void fpga_irq_unmask(struct irq_data *d)
        writel(mask, f->base + IRQ_ENABLE_SET);
 }
 
-static void fpga_irq_handle(unsigned int __irq, struct irq_desc *desc)
+static void fpga_irq_handle(struct irq_desc *desc)
 {
        struct fpga_irq_data *f = irq_desc_get_handler_data(desc);
-       unsigned int irq = irq_desc_get_irq(desc);
        u32 status = readl(f->base + IRQ_STATUS);
 
        if (status == 0) {
-               do_bad_IRQ(irq, desc);
+               do_bad_IRQ(desc);
                return;
        }
 
        do {
-               irq = ffs(status) - 1;
+               unsigned int irq = ffs(status) - 1;
+
                status &= ~(1 << irq);
                generic_handle_irq(irq_find_mapping(f->domain, irq));
        } while (status);
@@ -128,7 +128,7 @@ static int fpga_irqdomain_map(struct irq_domain *d, unsigned int irq,
        irq_set_chip_data(irq, f);
        irq_set_chip_and_handler(irq, &f->chip,
                                handle_level_irq);
-       set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+       irq_set_probe(irq);
        return 0;
 }
 
index 03846dff42123c96079489f998ed18e7623ff576..b956dfffe78ca1b64a469aac808223718090f3a7 100644 (file)
@@ -201,7 +201,7 @@ static int vic_irqdomain_map(struct irq_domain *d, unsigned int irq,
                return -EPERM;
        irq_set_chip_and_handler(irq, &vic_chip, handle_level_irq);
        irq_set_chip_data(irq, v->base);
-       set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+       irq_set_probe(irq);
        return 0;
 }
 
@@ -225,7 +225,7 @@ static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs)
        return handled;
 }
 
-static void vic_handle_irq_cascaded(unsigned int irq, struct irq_desc *desc)
+static void vic_handle_irq_cascaded(struct irq_desc *desc)
 {
        u32 stat, hwirq;
        struct irq_chip *host_chip = irq_desc_get_chip(desc);
index 8371d9978d31d9db5550ed1cdbf5cb28936b4fbd..f9af0af21751d8cad3a03256e375ae464723fd26 100644 (file)
@@ -167,7 +167,6 @@ static int vt8500_irq_map(struct irq_domain *h, unsigned int virq,
                                                        irq_hw_number_t hw)
 {
        irq_set_chip_and_handler(virq, &vt8500_irq_chip, handle_level_irq);
-       set_irq_flags(virq, IRQF_VALID);
 
        return 0;
 }
index 4cbd9c5dc1e6fc1e65810c28c61c3a780942a8a1..1ccd2abed65f5348d0beaa114a2d1326c8cc1b67 100644 (file)
@@ -182,7 +182,7 @@ static struct spear_shirq *spear320_shirq_blocks[] = {
        &spear320_shirq_intrcomm_ras,
 };
 
-static void shirq_handler(unsigned __irq, struct irq_desc *desc)
+static void shirq_handler(struct irq_desc *desc)
 {
        struct spear_shirq *shirq = irq_desc_get_handler_data(desc);
        u32 pend;
@@ -211,7 +211,6 @@ static void __init spear_shirq_register(struct spear_shirq *shirq,
        for (i = 0; i < shirq->nr_irqs; i++) {
                irq_set_chip_and_handler(shirq->virq_base + i,
                                         shirq->irq_chip, handle_simple_irq);
-               set_irq_flags(shirq->virq_base + i, IRQF_VALID);
                irq_set_chip_data(shirq->virq_base + i, shirq);
        }
 }
index 18accb0a79cc51dea2d1851fc9a27891e8d79d6f..c53a53f6efb6a136ec09075996bd89081e50e536 100644 (file)
@@ -1247,7 +1247,7 @@ static void
 l2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
 {
        struct PStack *st = fi->userdata;
-       struct sk_buff *skb;
+       struct sk_buff *skb, *nskb;
        struct Layer2 *l2 = &st->l2;
        u_char header[MAX_HEADER_LEN];
        int i, hdr_space_needed;
@@ -1262,14 +1262,10 @@ l2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
                return;
 
        hdr_space_needed = l2headersize(l2, 0);
-       if (hdr_space_needed > skb_headroom(skb)) {
-               struct sk_buff *orig_skb = skb;
-
-               skb = skb_realloc_headroom(skb, hdr_space_needed);
-               if (!skb) {
-                       dev_kfree_skb(orig_skb);
-                       return;
-               }
+       nskb = skb_realloc_headroom(skb, hdr_space_needed);
+       if (!nskb) {
+               skb_queue_head(&l2->i_queue, skb);
+               return;
        }
        spin_lock_irqsave(&l2->lock, flags);
        if (test_bit(FLG_MOD128, &l2->flag))
@@ -1282,7 +1278,7 @@ l2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
                       p1);
                dev_kfree_skb(l2->windowar[p1]);
        }
-       l2->windowar[p1] = skb_clone(skb, GFP_ATOMIC);
+       l2->windowar[p1] = skb;
 
        i = sethdraddr(&st->l2, header, CMD);
 
@@ -1295,8 +1291,8 @@ l2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
                l2->vs = (l2->vs + 1) % 8;
        }
        spin_unlock_irqrestore(&l2->lock, flags);
-       memcpy(skb_push(skb, i), header, i);
-       st->l2.l2l1(st, PH_PULL | INDICATION, skb);
+       memcpy(skb_push(nskb, i), header, i);
+       st->l2.l2l1(st, PH_PULL | INDICATION, nskb);
        test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag);
        if (!test_and_set_bit(FLG_T200_RUN, &st->l2.flag)) {
                FsmDelTimer(&st->l2.t203, 13);
index 949cabb88f1c113c9606d26ff72627f6cf9db108..5eb380a2590394ba087e2f160281e1902112910f 100644 (file)
@@ -1476,7 +1476,7 @@ static void
 l2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
 {
        struct layer2   *l2 = fi->userdata;
-       struct sk_buff  *skb, *nskb, *oskb;
+       struct sk_buff  *skb, *nskb;
        u_char          header[MAX_L2HEADER_LEN];
        u_int           i, p1;
 
@@ -1486,48 +1486,34 @@ l2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
        skb = skb_dequeue(&l2->i_queue);
        if (!skb)
                return;
-
-       if (test_bit(FLG_MOD128, &l2->flag))
-               p1 = (l2->vs - l2->va) % 128;
-       else
-               p1 = (l2->vs - l2->va) % 8;
-       p1 = (p1 + l2->sow) % l2->window;
-       if (l2->windowar[p1]) {
-               printk(KERN_WARNING "%s: l2 try overwrite ack queue entry %d\n",
-                      mISDNDevName4ch(&l2->ch), p1);
-               dev_kfree_skb(l2->windowar[p1]);
-       }
-       l2->windowar[p1] = skb;
        i = sethdraddr(l2, header, CMD);
        if (test_bit(FLG_MOD128, &l2->flag)) {
                header[i++] = l2->vs << 1;
                header[i++] = l2->vr << 1;
+       } else
+               header[i++] = (l2->vr << 5) | (l2->vs << 1);
+       nskb = skb_realloc_headroom(skb, i);
+       if (!nskb) {
+               printk(KERN_WARNING "%s: no headroom(%d) copy for IFrame\n",
+                      mISDNDevName4ch(&l2->ch), i);
+               skb_queue_head(&l2->i_queue, skb);
+               return;
+       }
+       if (test_bit(FLG_MOD128, &l2->flag)) {
+               p1 = (l2->vs - l2->va) % 128;
                l2->vs = (l2->vs + 1) % 128;
        } else {
-               header[i++] = (l2->vr << 5) | (l2->vs << 1);
+               p1 = (l2->vs - l2->va) % 8;
                l2->vs = (l2->vs + 1) % 8;
        }
-
-       nskb = skb_clone(skb, GFP_ATOMIC);
-       p1 = skb_headroom(nskb);
-       if (p1 >= i)
-               memcpy(skb_push(nskb, i), header, i);
-       else {
-               printk(KERN_WARNING
-                      "%s: L2 pull_iqueue skb header(%d/%d) too short\n",
-                      mISDNDevName4ch(&l2->ch), i, p1);
-               oskb = nskb;
-               nskb = mI_alloc_skb(oskb->len + i, GFP_ATOMIC);
-               if (!nskb) {
-                       dev_kfree_skb(oskb);
-                       printk(KERN_WARNING "%s: no skb mem in %s\n",
-                              mISDNDevName4ch(&l2->ch), __func__);
-                       return;
-               }
-               memcpy(skb_put(nskb, i), header, i);
-               memcpy(skb_put(nskb, oskb->len), oskb->data, oskb->len);
-               dev_kfree_skb(oskb);
+       p1 = (p1 + l2->sow) % l2->window;
+       if (l2->windowar[p1]) {
+               printk(KERN_WARNING "%s: l2 try overwrite ack queue entry %d\n",
+                      mISDNDevName4ch(&l2->ch), p1);
+               dev_kfree_skb(l2->windowar[p1]);
        }
+       l2->windowar[p1] = skb;
+       memcpy(skb_push(nskb, i), header, i);
        l2down(l2, PH_DATA_REQ, l2_newid(l2), nskb);
        test_and_clear_bit(FLG_ACK_PEND, &l2->flag);
        if (!test_and_set_bit(FLG_T200_RUN, &l2->flag)) {
index 70f4255ff291044dfd0d9b526168c24c7ffa6ea8..42990f2d03178885d6021bce5ef3a9315d70f447 100644 (file)
@@ -170,6 +170,7 @@ config LEDS_SUNFIRE
 
 config LEDS_IPAQ_MICRO
        tristate "LED Support for the Compaq iPAQ h3xxx"
+       depends on LEDS_CLASS
        depends on MFD_IPAQ_MICRO
        help
          Choose this option if you want to use the notification LED on
@@ -229,7 +230,7 @@ config LEDS_LP55XX_COMMON
        tristate "Common Driver for TI/National LP5521/5523/55231/5562/8501"
        depends on LEDS_LP5521 || LEDS_LP5523 || LEDS_LP5562 || LEDS_LP8501
        select FW_LOADER
-       select FW_LOADER_USER_HELPER_FALLBACK
+       select FW_LOADER_USER_HELPER
        help
          This option supports common operations for LP5521/5523/55231/5562/8501
          devices.
index fd7c25fd29c112dffd7337bb279de20740fd1eed..ac77d36b630cda0b32dbcd312e97d461192b8ecc 100644 (file)
@@ -331,7 +331,7 @@ static void aat1290_led_validate_mm_current(struct aat1290_led *led,
        cfg->max_brightness = b + 1;
 }
 
-int init_mm_current_scale(struct aat1290_led *led,
+static int init_mm_current_scale(struct aat1290_led *led,
                        struct aat1290_led_config_data *cfg)
 {
        int max_mm_current_percent[] = { 20, 22, 25, 28, 32, 36, 40, 45, 50, 56,
@@ -559,6 +559,7 @@ static const struct of_device_id aat1290_led_dt_match[] = {
        { .compatible = "skyworks,aat1290" },
        {},
 };
+MODULE_DEVICE_TABLE(of, aat1290_led_dt_match);
 
 static struct platform_driver aat1290_led_driver = {
        .probe          = aat1290_led_probe,
index 986fe1e28f842b0199e49cc284529b8a12ac2b75..1793727bc9ae5f6c64467a68b4646b92e0963e1b 100644 (file)
@@ -395,6 +395,7 @@ static const struct of_device_id bcm6328_leds_of_match[] = {
        { .compatible = "brcm,bcm6328-leds", },
        { },
 };
+MODULE_DEVICE_TABLE(of, bcm6328_leds_of_match);
 
 static struct platform_driver bcm6328_leds_driver = {
        .probe = bcm6328_leds_probe,
index 21f96930b3be3a35a07142e204c449e843c643a3..7ea3526702e0c56b2a841e0bf2d2dccbe3f606f6 100644 (file)
@@ -226,6 +226,7 @@ static const struct of_device_id bcm6358_leds_of_match[] = {
        { .compatible = "brcm,bcm6358-leds", },
        { },
 };
+MODULE_DEVICE_TABLE(of, bcm6358_leds_of_match);
 
 static struct platform_driver bcm6358_leds_driver = {
        .probe = bcm6358_leds_probe,
index 2ae8c4d17ff8e0c2e971102a5844170c2e734ec2..feca07be85f590c09f4b12a69835e59e44ecff9b 100644 (file)
@@ -426,6 +426,7 @@ static const struct of_device_id ktd2692_match[] = {
        { .compatible = "kinetic,ktd2692", },
        { /* sentinel */ },
 };
+MODULE_DEVICE_TABLE(of, ktd2692_match);
 
 static struct platform_driver ktd2692_driver = {
        .driver = {
index df348a06d8c71faa60d80530f29bec8a050469dc..afbb1409b2e24a1a5c6636409e9cf874f84955e4 100644 (file)
@@ -1080,6 +1080,7 @@ static const struct of_device_id max77693_led_dt_match[] = {
        { .compatible = "maxim,max77693-led" },
        {},
 };
+MODULE_DEVICE_TABLE(of, max77693_led_dt_match);
 
 static struct platform_driver max77693_led_driver = {
        .probe          = max77693_led_probe,
index b33514d9f427e279bf091abab4126f55e0d48182..a95a61220169ddc8099ba127d01cdb0db3a5adcb 100644 (file)
@@ -337,6 +337,7 @@ static const struct of_device_id of_ns2_leds_match[] = {
        { .compatible = "lacie,ns2-leds", },
        {},
 };
+MODULE_DEVICE_TABLE(of, of_ns2_leds_match);
 #endif /* CONFIG_OF_GPIO */
 
 struct ns2_led_priv {
index de36237d7c6b45de10fca57cc1870fde5a0620e5..051645498b53f8931e6f1db9a11aeb65e61ac2fd 100644 (file)
@@ -74,7 +74,7 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                ret = -ENOTSUPP;
                dev_err(&pdev->dev,
                        "IO mapped PCI devices are not supported\n");
-               goto out_release;
+               goto out_iounmap;
        }
 
        pci_set_drvdata(pdev, priv);
@@ -89,7 +89,7 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        ret = chameleon_parse_cells(priv->bus, priv->mapbase, priv->base);
        if (ret < 0)
-               goto out_iounmap;
+               goto out_mcb_bus;
        num_cells = ret;
 
        dev_dbg(&pdev->dev, "Found %d cells\n", num_cells);
@@ -98,6 +98,8 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        return 0;
 
+out_mcb_bus:
+       mcb_release_bus(priv->bus);
 out_iounmap:
        iounmap(priv->base);
 out_release:
index e51de52eeb94f71c9d6712a61d31e49f8e6f2f60..48b5890c28e35ad70484d67b29e12a70cb9a4b1b 100644 (file)
@@ -1997,7 +1997,8 @@ int bitmap_resize(struct bitmap *bitmap, sector_t blocks,
        if (bitmap->mddev->bitmap_info.offset || bitmap->mddev->bitmap_info.file)
                ret = bitmap_storage_alloc(&store, chunks,
                                           !bitmap->mddev->bitmap_info.external,
-                                          bitmap->cluster_slot);
+                                          mddev_is_clustered(bitmap->mddev)
+                                          ? bitmap->cluster_slot : 0);
        if (ret)
                goto err;
 
index 20cc36b01b77895625adbe82a14923148d688edb..0a17d1b91a811d712a350c399d94cdc50322f0d0 100644 (file)
@@ -634,10 +634,10 @@ static int __commit_transaction(struct dm_cache_metadata *cmd,
 
        disk_super = dm_block_data(sblock);
 
+       disk_super->flags = cpu_to_le32(cmd->flags);
        if (mutator)
                update_flags(disk_super, mutator);
 
-       disk_super->flags = cpu_to_le32(cmd->flags);
        disk_super->mapping_root = cpu_to_le64(cmd->root);
        disk_super->hint_root = cpu_to_le64(cmd->hint_root);
        disk_super->discard_root = cpu_to_le64(cmd->discard_root);
index 240c9f0e85e74e864624f0cb972c5b4394eaf11f..8a096456579bead67b182f27e65956341a7c8d73 100644 (file)
@@ -436,7 +436,7 @@ static struct dm_cache_policy *wb_create(dm_cblock_t cache_size,
 static struct dm_cache_policy_type wb_policy_type = {
        .name = "cleaner",
        .version = {1, 0, 0},
-       .hint_size = 0,
+       .hint_size = 4,
        .owner = THIS_MODULE,
        .create = wb_create
 };
index d60c88df5234a0099292712cc1117dc1e65b78e0..4b3b6f8aff0cb4112a7bafa2c128027f804468b6 100644 (file)
@@ -968,7 +968,8 @@ static void crypt_free_buffer_pages(struct crypt_config *cc, struct bio *clone);
 
 /*
  * Generate a new unfragmented bio with the given size
- * This should never violate the device limitations
+ * This should never violate the device limitations (but only because
+ * max_segment_size is being constrained to PAGE_SIZE).
  *
  * This function may be called concurrently. If we allocate from the mempool
  * concurrently, there is a possibility of deadlock. For example, if we have
@@ -2045,9 +2046,20 @@ static int crypt_iterate_devices(struct dm_target *ti,
        return fn(ti, cc->dev, cc->start, ti->len, data);
 }
 
+static void crypt_io_hints(struct dm_target *ti, struct queue_limits *limits)
+{
+       /*
+        * Unfortunate constraint that is required to avoid the potential
+        * for exceeding underlying device's max_segments limits -- due to
+        * crypt_alloc_buffer() possibly allocating pages for the encryption
+        * bio that are not as physically contiguous as the original bio.
+        */
+       limits->max_segment_size = PAGE_SIZE;
+}
+
 static struct target_type crypt_target = {
        .name   = "crypt",
-       .version = {1, 14, 0},
+       .version = {1, 14, 1},
        .module = THIS_MODULE,
        .ctr    = crypt_ctr,
        .dtr    = crypt_dtr,
@@ -2058,6 +2070,7 @@ static struct target_type crypt_target = {
        .resume = crypt_resume,
        .message = crypt_message,
        .iterate_devices = crypt_iterate_devices,
+       .io_hints = crypt_io_hints,
 };
 
 static int __init dm_crypt_init(void)
index ebaa4f803eec3a08a0cd9fcd9a9a1b933618c50c..192bb8beeb6b59e296d9a2e06c0ef8c0a9be8aeb 100644 (file)
@@ -203,7 +203,7 @@ int dm_exception_store_create(struct dm_target *ti, int argc, char **argv,
                return -EINVAL;
        }
 
-       tmp_store = kmalloc(sizeof(*tmp_store), GFP_KERNEL);
+       tmp_store = kzalloc(sizeof(*tmp_store), GFP_KERNEL);
        if (!tmp_store) {
                ti->error = "Exception store allocation failed";
                return -ENOMEM;
@@ -215,7 +215,7 @@ int dm_exception_store_create(struct dm_target *ti, int argc, char **argv,
        else if (persistent == 'N')
                type = get_type("N");
        else {
-               ti->error = "Persistent flag is not P or N";
+               ti->error = "Exception store type is not P or N";
                r = -EINVAL;
                goto bad_type;
        }
@@ -233,7 +233,7 @@ int dm_exception_store_create(struct dm_target *ti, int argc, char **argv,
        if (r)
                goto bad;
 
-       r = type->ctr(tmp_store, 0, NULL);
+       r = type->ctr(tmp_store, (strlen(argv[0]) > 1 ? &argv[0][1] : NULL));
        if (r) {
                ti->error = "Exception store type constructor failed";
                goto bad;
index 0b2536247cf55a3215223b8b0c72ff29a629b87a..fae34e7a0b1e4e4d60b5867eff9422e432fba83b 100644 (file)
@@ -42,8 +42,7 @@ struct dm_exception_store_type {
        const char *name;
        struct module *module;
 
-       int (*ctr) (struct dm_exception_store *store,
-                   unsigned argc, char **argv);
+       int (*ctr) (struct dm_exception_store *store, char *options);
 
        /*
         * Destroys this object when you've finished with it.
@@ -123,6 +122,8 @@ struct dm_exception_store {
        unsigned chunk_shift;
 
        void *context;
+
+       bool userspace_supports_overflow;
 };
 
 /*
index 97e165183e79f2991f8191913e0b44fb91b00310..a0901214aef57de00419a14c573bc128431749c7 100644 (file)
@@ -329,8 +329,7 @@ static int validate_region_size(struct raid_set *rs, unsigned long region_size)
                 */
                if (min_region_size > (1 << 13)) {
                        /* If not a power of 2, make it the next power of 2 */
-                       if (min_region_size & (min_region_size - 1))
-                               region_size = 1 << fls(region_size);
+                       region_size = roundup_pow_of_two(min_region_size);
                        DMINFO("Choosing default region size of %lu sectors",
                               region_size);
                } else {
index bf71583296f732b6b78c71ae67dee5222824b2f8..117a05e40090a9b78829ed415446d906c8268701 100644 (file)
@@ -7,6 +7,7 @@
 
 #include "dm-exception-store.h"
 
+#include <linux/ctype.h>
 #include <linux/mm.h>
 #include <linux/pagemap.h>
 #include <linux/vmalloc.h>
@@ -843,10 +844,10 @@ static void persistent_drop_snapshot(struct dm_exception_store *store)
                DMWARN("write header failed");
 }
 
-static int persistent_ctr(struct dm_exception_store *store,
-                         unsigned argc, char **argv)
+static int persistent_ctr(struct dm_exception_store *store, char *options)
 {
        struct pstore *ps;
+       int r;
 
        /* allocate the pstore */
        ps = kzalloc(sizeof(*ps), GFP_KERNEL);
@@ -868,14 +869,32 @@ static int persistent_ctr(struct dm_exception_store *store,
 
        ps->metadata_wq = alloc_workqueue("ksnaphd", WQ_MEM_RECLAIM, 0);
        if (!ps->metadata_wq) {
-               kfree(ps);
                DMERR("couldn't start header metadata update thread");
-               return -ENOMEM;
+               r = -ENOMEM;
+               goto err_workqueue;
+       }
+
+       if (options) {
+               char overflow = toupper(options[0]);
+               if (overflow == 'O')
+                       store->userspace_supports_overflow = true;
+               else {
+                       DMERR("Unsupported persistent store option: %s", options);
+                       r = -EINVAL;
+                       goto err_options;
+               }
        }
 
        store->context = ps;
 
        return 0;
+
+err_options:
+       destroy_workqueue(ps->metadata_wq);
+err_workqueue:
+       kfree(ps);
+
+       return r;
 }
 
 static unsigned persistent_status(struct dm_exception_store *store,
@@ -888,7 +907,8 @@ static unsigned persistent_status(struct dm_exception_store *store,
        case STATUSTYPE_INFO:
                break;
        case STATUSTYPE_TABLE:
-               DMEMIT(" P %llu", (unsigned long long)store->chunk_size);
+               DMEMIT(" %s %llu", store->userspace_supports_overflow ? "PO" : "P",
+                      (unsigned long long)store->chunk_size);
        }
 
        return sz;
index 1ce9a2586e4134a79ec3289808f8229e9aaa2080..9b7c8c8049d6186f54bdfec114c43cb3ce4d77fa 100644 (file)
@@ -70,8 +70,7 @@ static void transient_usage(struct dm_exception_store *store,
        *metadata_sectors = 0;
 }
 
-static int transient_ctr(struct dm_exception_store *store,
-                        unsigned argc, char **argv)
+static int transient_ctr(struct dm_exception_store *store, char *options)
 {
        struct transient_c *tc;
 
index c0bcd6516dfe17f8e7a06ec8c66d1e1d5801f133..c06b74e91cd6aeef00ef4eefae9953d4d8c8f91b 100644 (file)
@@ -1098,7 +1098,7 @@ static void stop_merge(struct dm_snapshot *s)
 }
 
 /*
- * Construct a snapshot mapping: <origin_dev> <COW-dev> <p/n> <chunk-size>
+ * Construct a snapshot mapping: <origin_dev> <COW-dev> <p|po|n> <chunk-size>
  */
 static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 {
@@ -1302,6 +1302,7 @@ static void __handover_exceptions(struct dm_snapshot *snap_src,
 
        u.store_swap = snap_dest->store;
        snap_dest->store = snap_src->store;
+       snap_dest->store->userspace_supports_overflow = u.store_swap->userspace_supports_overflow;
        snap_src->store = u.store_swap;
 
        snap_dest->store->snap = snap_dest;
@@ -1739,8 +1740,11 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio)
 
                        pe = __find_pending_exception(s, pe, chunk);
                        if (!pe) {
-                               s->snapshot_overflowed = 1;
-                               DMERR("Snapshot overflowed: Unable to allocate exception.");
+                               if (s->store->userspace_supports_overflow) {
+                                       s->snapshot_overflowed = 1;
+                                       DMERR("Snapshot overflowed: Unable to allocate exception.");
+                               } else
+                                       __invalidate_snapshot(s, -ENOMEM);
                                r = -EIO;
                                goto out_unlock;
                        }
@@ -2365,7 +2369,7 @@ static struct target_type origin_target = {
 
 static struct target_type snapshot_target = {
        .name    = "snapshot",
-       .version = {1, 14, 0},
+       .version = {1, 15, 0},
        .module  = THIS_MODULE,
        .ctr     = snapshot_ctr,
        .dtr     = snapshot_dtr,
@@ -2379,7 +2383,7 @@ static struct target_type snapshot_target = {
 
 static struct target_type merge_target = {
        .name    = dm_snapshot_merge_target_name,
-       .version = {1, 3, 0},
+       .version = {1, 4, 0},
        .module  = THIS_MODULE,
        .ctr     = snapshot_ctr,
        .dtr     = snapshot_dtr,
index 6578b7bc1fbba5339a740c8447f8bfdf8266fd8f..3897b90bd462d852e0aec27a792be14655efa150 100644 (file)
@@ -3201,7 +3201,7 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
                                                metadata_low_callback,
                                                pool);
        if (r)
-               goto out_free_pt;
+               goto out_flags_changed;
 
        pt->callbacks.congested_fn = pool_is_congested;
        dm_table_add_target_callbacks(ti->table, &pt->callbacks);
@@ -4249,6 +4249,10 @@ static void thin_io_hints(struct dm_target *ti, struct queue_limits *limits)
 {
        struct thin_c *tc = ti->private;
        struct pool *pool = tc->pool;
+       struct queue_limits *pool_limits = dm_get_queue_limits(pool->pool_md);
+
+       if (!pool_limits->discard_granularity)
+               return; /* pool's discard support is disabled */
 
        limits->discard_granularity = pool->sectors_per_block << SECTOR_SHIFT;
        limits->max_discard_sectors = 2048 * 1024 * 16; /* 16G */
index 6264781dc69a6066b88d719537c471b7d1cd7b27..1b5c6047e4f19882fbbe9facbc29aeee54dc8723 100644 (file)
@@ -1001,6 +1001,7 @@ static void end_clone_bio(struct bio *clone)
        struct dm_rq_target_io *tio = info->tio;
        struct bio *bio = info->orig;
        unsigned int nr_bytes = info->orig->bi_iter.bi_size;
+       int error = clone->bi_error;
 
        bio_put(clone);
 
@@ -1011,13 +1012,13 @@ static void end_clone_bio(struct bio *clone)
                 * the remainder.
                 */
                return;
-       else if (bio->bi_error) {
+       else if (error) {
                /*
                 * Don't notice the error to the upper layer yet.
                 * The error handling decision is made by the target driver,
                 * when the request is completed.
                 */
-               tio->error = bio->bi_error;
+               tio->error = error;
                return;
        }
 
@@ -2837,8 +2838,6 @@ static void __dm_destroy(struct mapped_device *md, bool wait)
 
        might_sleep();
 
-       map = dm_get_live_table(md, &srcu_idx);
-
        spin_lock(&_minor_lock);
        idr_replace(&_minor_idr, MINOR_ALLOCED, MINOR(disk_devt(dm_disk(md))));
        set_bit(DMF_FREEING, &md->flags);
@@ -2852,14 +2851,14 @@ static void __dm_destroy(struct mapped_device *md, bool wait)
         * do not race with internal suspend.
         */
        mutex_lock(&md->suspend_lock);
+       map = dm_get_live_table(md, &srcu_idx);
        if (!dm_suspended_md(md)) {
                dm_table_presuspend_targets(map);
                dm_table_postsuspend_targets(map);
        }
-       mutex_unlock(&md->suspend_lock);
-
        /* dm_put_live_table must be before msleep, otherwise deadlock is possible */
        dm_put_live_table(md, srcu_idx);
+       mutex_unlock(&md->suspend_lock);
 
        /*
         * Rare, but there may be I/O requests still going to complete,
index 4f5ecbe94ccbf97c562d96930635c6aaff0550d3..3fe3d04a968ad1ae5e148abbc93cde43be576104 100644 (file)
@@ -5409,9 +5409,13 @@ static int md_set_readonly(struct mddev *mddev, struct block_device *bdev)
                 * which will now never happen */
                wake_up_process(mddev->sync_thread->tsk);
 
+       if (mddev->external && test_bit(MD_CHANGE_PENDING, &mddev->flags))
+               return -EBUSY;
        mddev_unlock(mddev);
        wait_event(resync_wait, !test_bit(MD_RECOVERY_RUNNING,
                                          &mddev->recovery));
+       wait_event(mddev->sb_wait,
+                  !test_bit(MD_CHANGE_PENDING, &mddev->flags));
        mddev_lock_nointr(mddev);
 
        mutex_lock(&mddev->open_mutex);
@@ -8036,8 +8040,7 @@ static int remove_and_add_spares(struct mddev *mddev,
                       !test_bit(Bitmap_sync, &rdev->flags)))
                        continue;
 
-               if (rdev->saved_raid_disk < 0)
-                       rdev->recovery_offset = 0;
+               rdev->recovery_offset = 0;
                if (mddev->pers->
                    hot_add_disk(mddev, rdev) == 0) {
                        if (sysfs_link_rdev(mddev, rdev))
@@ -8160,6 +8163,7 @@ void md_check_recovery(struct mddev *mddev)
                        md_reap_sync_thread(mddev);
                        clear_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
                        clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+                       clear_bit(MD_CHANGE_PENDING, &mddev->flags);
                        goto unlock;
                }
 
index d222522c52e077dcdd012fbf22d929fc6a7cb0ad..d132f06afdd1aa3140922f7965494087cf43eb7a 100644 (file)
@@ -470,8 +470,7 @@ static int multipath_run (struct mddev *mddev)
        return 0;
 
 out_free_conf:
-       if (conf->pool)
-               mempool_destroy(conf->pool);
+       mempool_destroy(conf->pool);
        kfree(conf->multipaths);
        kfree(conf);
        mddev->private = NULL;
index 421a36c593e3e7dedef785a5f78c12914c13d8b3..2e4c4cb79e4d939f0ed2638986d2ccc3ddd8b972 100644 (file)
@@ -301,11 +301,16 @@ static void redistribute3(struct dm_btree_info *info, struct btree_node *parent,
 {
        int s;
        uint32_t max_entries = le32_to_cpu(left->header.max_entries);
-       unsigned target = (nr_left + nr_center + nr_right) / 3;
-       BUG_ON(target > max_entries);
+       unsigned total = nr_left + nr_center + nr_right;
+       unsigned target_right = total / 3;
+       unsigned remainder = (target_right * 3) != total;
+       unsigned target_left = target_right + remainder;
+
+       BUG_ON(target_left > max_entries);
+       BUG_ON(target_right > max_entries);
 
        if (nr_left < nr_right) {
-               s = nr_left - target;
+               s = nr_left - target_left;
 
                if (s < 0 && nr_center < -s) {
                        /* not enough in central node */
@@ -316,10 +321,10 @@ static void redistribute3(struct dm_btree_info *info, struct btree_node *parent,
                } else
                        shift(left, center, s);
 
-               shift(center, right, target - nr_right);
+               shift(center, right, target_right - nr_right);
 
        } else {
-               s = target - nr_right;
+               s = target_right - nr_right;
                if (s > 0 && nr_center < s) {
                        /* not enough in central node */
                        shift(center, right, nr_center);
@@ -329,7 +334,7 @@ static void redistribute3(struct dm_btree_info *info, struct btree_node *parent,
                } else
                        shift(center, right, s);
 
-               shift(left, center, nr_left - target);
+               shift(left, center, nr_left - target_left);
        }
 
        *key_ptr(parent, c->index) = center->keys[0];
index b6cec258cc2138497b3c8875fc4defdb7523701f..0e09aef43998ac250cc296122247875eed23ceb2 100644 (file)
@@ -523,7 +523,7 @@ static int btree_split_beneath(struct shadow_spine *s, uint64_t key)
 
        r = new_block(s->info, &right);
        if (r < 0) {
-               /* FIXME: put left */
+               unlock_block(s->info, left);
                return r;
        }
 
index 63e619b2f44eb3ce51a90eb74980ed8a1f91c639..f8e5db0cb5aaae3038e67ec9f348f1faa4c64508 100644 (file)
@@ -376,12 +376,6 @@ static int raid0_run(struct mddev *mddev)
                struct md_rdev *rdev;
                bool discard_supported = false;
 
-               rdev_for_each(rdev, mddev) {
-                       disk_stack_limits(mddev->gendisk, rdev->bdev,
-                                         rdev->data_offset << 9);
-                       if (blk_queue_discard(bdev_get_queue(rdev->bdev)))
-                               discard_supported = true;
-               }
                blk_queue_max_hw_sectors(mddev->queue, mddev->chunk_sectors);
                blk_queue_max_write_same_sectors(mddev->queue, mddev->chunk_sectors);
                blk_queue_max_discard_sectors(mddev->queue, mddev->chunk_sectors);
@@ -390,6 +384,12 @@ static int raid0_run(struct mddev *mddev)
                blk_queue_io_opt(mddev->queue,
                                 (mddev->chunk_sectors << 9) * mddev->raid_disks);
 
+               rdev_for_each(rdev, mddev) {
+                       disk_stack_limits(mddev->gendisk, rdev->bdev,
+                                         rdev->data_offset << 9);
+                       if (blk_queue_discard(bdev_get_queue(rdev->bdev)))
+                               discard_supported = true;
+               }
                if (!discard_supported)
                        queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
                else
index 4517f06c41bafe0fb2fbe2a5b454b68f012b2455..d9d031ede4bf5d73993a0fc607fab4274627c890 100644 (file)
@@ -881,8 +881,7 @@ static sector_t wait_barrier(struct r1conf *conf, struct bio *bio)
        }
 
        if (bio && bio_data_dir(bio) == WRITE) {
-               if (bio->bi_iter.bi_sector >=
-                   conf->mddev->curr_resync_completed) {
+               if (bio->bi_iter.bi_sector >= conf->next_resync) {
                        if (conf->start_next_window == MaxSector)
                                conf->start_next_window =
                                        conf->next_resync +
@@ -1516,7 +1515,7 @@ static void close_sync(struct r1conf *conf)
        conf->r1buf_pool = NULL;
 
        spin_lock_irq(&conf->resync_lock);
-       conf->next_resync = 0;
+       conf->next_resync = MaxSector - 2 * NEXT_NORMALIO_DISTANCE;
        conf->start_next_window = MaxSector;
        conf->current_window_requests +=
                conf->next_window_requests;
@@ -2196,7 +2195,7 @@ static int narrow_write_error(struct r1bio *r1_bio, int i)
                bio_trim(wbio, sector - r1_bio->sector, sectors);
                wbio->bi_iter.bi_sector += rdev->data_offset;
                wbio->bi_bdev = rdev->bdev;
-               if (submit_bio_wait(WRITE, wbio) == 0)
+               if (submit_bio_wait(WRITE, wbio) < 0)
                        /* failure! */
                        ok = rdev_set_badblocks(rdev, sector,
                                                sectors, 0)
@@ -2259,15 +2258,16 @@ static void handle_write_finished(struct r1conf *conf, struct r1bio *r1_bio)
                        rdev_dec_pending(conf->mirrors[m].rdev,
                                         conf->mddev);
                }
-       if (test_bit(R1BIO_WriteError, &r1_bio->state))
-               close_write(r1_bio);
        if (fail) {
                spin_lock_irq(&conf->device_lock);
                list_add(&r1_bio->retry_list, &conf->bio_end_io_list);
                spin_unlock_irq(&conf->device_lock);
                md_wakeup_thread(conf->mddev->thread);
-       } else
+       } else {
+               if (test_bit(R1BIO_WriteError, &r1_bio->state))
+                       close_write(r1_bio);
                raid_end_bio_io(r1_bio);
+       }
 }
 
 static void handle_read_error(struct r1conf *conf, struct r1bio *r1_bio)
@@ -2383,9 +2383,13 @@ static void raid1d(struct md_thread *thread)
                }
                spin_unlock_irqrestore(&conf->device_lock, flags);
                while (!list_empty(&tmp)) {
-                       r1_bio = list_first_entry(&conf->bio_end_io_list,
-                                                 struct r1bio, retry_list);
+                       r1_bio = list_first_entry(&tmp, struct r1bio,
+                                                 retry_list);
                        list_del(&r1_bio->retry_list);
+                       if (mddev->degraded)
+                               set_bit(R1BIO_Degraded, &r1_bio->state);
+                       if (test_bit(R1BIO_WriteError, &r1_bio->state))
+                               close_write(r1_bio);
                        raid_end_bio_io(r1_bio);
                }
        }
@@ -2843,8 +2847,7 @@ static struct r1conf *setup_conf(struct mddev *mddev)
 
  abort:
        if (conf) {
-               if (conf->r1bio_pool)
-                       mempool_destroy(conf->r1bio_pool);
+               mempool_destroy(conf->r1bio_pool);
                kfree(conf->mirrors);
                safe_put_page(conf->tmppage);
                kfree(conf->poolinfo);
@@ -2946,8 +2949,7 @@ static void raid1_free(struct mddev *mddev, void *priv)
 {
        struct r1conf *conf = priv;
 
-       if (conf->r1bio_pool)
-               mempool_destroy(conf->r1bio_pool);
+       mempool_destroy(conf->r1bio_pool);
        kfree(conf->mirrors);
        safe_put_page(conf->tmppage);
        kfree(conf->poolinfo);
index 0fc33eb888551292bb37461f08d7e704483f93e6..96f36596830696c2f1ba1bd8bc6fbb24d30a43d8 100644 (file)
@@ -39,6 +39,7 @@
  *    far_copies (stored in second byte of layout)
  *    far_offset (stored in bit 16 of layout )
  *    use_far_sets (stored in bit 17 of layout )
+ *    use_far_sets_bugfixed (stored in bit 18 of layout )
  *
  * The data to be stored is divided into chunks using chunksize.  Each device
  * is divided into far_copies sections.   In each section, chunks are laid out
@@ -1497,6 +1498,8 @@ static void status(struct seq_file *seq, struct mddev *mddev)
                        seq_printf(seq, " %d offset-copies", conf->geo.far_copies);
                else
                        seq_printf(seq, " %d far-copies", conf->geo.far_copies);
+               if (conf->geo.far_set_size != conf->geo.raid_disks)
+                       seq_printf(seq, " %d devices per set", conf->geo.far_set_size);
        }
        seq_printf(seq, " [%d/%d] [", conf->geo.raid_disks,
                                        conf->geo.raid_disks - mddev->degraded);
@@ -2467,7 +2470,7 @@ static int narrow_write_error(struct r10bio *r10_bio, int i)
                                   choose_data_offset(r10_bio, rdev) +
                                   (sector - r10_bio->sector));
                wbio->bi_bdev = rdev->bdev;
-               if (submit_bio_wait(WRITE, wbio) == 0)
+               if (submit_bio_wait(WRITE, wbio) < 0)
                        /* Failure! */
                        ok = rdev_set_badblocks(rdev, sector,
                                                sectors, 0)
@@ -2654,16 +2657,17 @@ static void handle_write_completed(struct r10conf *conf, struct r10bio *r10_bio)
                                rdev_dec_pending(rdev, conf->mddev);
                        }
                }
-               if (test_bit(R10BIO_WriteError,
-                            &r10_bio->state))
-                       close_write(r10_bio);
                if (fail) {
                        spin_lock_irq(&conf->device_lock);
                        list_add(&r10_bio->retry_list, &conf->bio_end_io_list);
                        spin_unlock_irq(&conf->device_lock);
                        md_wakeup_thread(conf->mddev->thread);
-               } else
+               } else {
+                       if (test_bit(R10BIO_WriteError,
+                                    &r10_bio->state))
+                               close_write(r10_bio);
                        raid_end_bio_io(r10_bio);
+               }
        }
 }
 
@@ -2688,9 +2692,15 @@ static void raid10d(struct md_thread *thread)
                }
                spin_unlock_irqrestore(&conf->device_lock, flags);
                while (!list_empty(&tmp)) {
-                       r10_bio = list_first_entry(&conf->bio_end_io_list,
-                                                 struct r10bio, retry_list);
+                       r10_bio = list_first_entry(&tmp, struct r10bio,
+                                                  retry_list);
                        list_del(&r10_bio->retry_list);
+                       if (mddev->degraded)
+                               set_bit(R10BIO_Degraded, &r10_bio->state);
+
+                       if (test_bit(R10BIO_WriteError,
+                                    &r10_bio->state))
+                               close_write(r10_bio);
                        raid_end_bio_io(r10_bio);
                }
        }
@@ -3387,7 +3397,7 @@ static int setup_geo(struct geom *geo, struct mddev *mddev, enum geo_type new)
                disks = mddev->raid_disks + mddev->delta_disks;
                break;
        }
-       if (layout >> 18)
+       if (layout >> 19)
                return -1;
        if (chunk < (PAGE_SIZE >> 9) ||
            !is_power_of_2(chunk))
@@ -3399,7 +3409,22 @@ static int setup_geo(struct geom *geo, struct mddev *mddev, enum geo_type new)
        geo->near_copies = nc;
        geo->far_copies = fc;
        geo->far_offset = fo;
-       geo->far_set_size = (layout & (1<<17)) ? disks / fc : disks;
+       switch (layout >> 17) {
+       case 0: /* original layout.  simple but not always optimal */
+               geo->far_set_size = disks;
+               break;
+       case 1: /* "improved" layout which was buggy.  Hopefully no-one is
+                * actually using this, but leave code here just in case.*/
+               geo->far_set_size = disks/fc;
+               WARN(geo->far_set_size < fc,
+                    "This RAID10 layout does not provide data safety - please backup and create new array\n");
+               break;
+       case 2: /* "improved" layout fixed to match documentation */
+               geo->far_set_size = fc * nc;
+               break;
+       default: /* Not a valid layout */
+               return -1;
+       }
        geo->chunk_mask = chunk - 1;
        geo->chunk_shift = ffz(~chunk);
        return nc*fc;
@@ -3486,8 +3511,7 @@ static struct r10conf *setup_conf(struct mddev *mddev)
                printk(KERN_ERR "md/raid10:%s: couldn't allocate memory.\n",
                       mdname(mddev));
        if (conf) {
-               if (conf->r10bio_pool)
-                       mempool_destroy(conf->r10bio_pool);
+               mempool_destroy(conf->r10bio_pool);
                kfree(conf->mirrors);
                safe_put_page(conf->tmppage);
                kfree(conf);
@@ -3682,8 +3706,7 @@ static int run(struct mddev *mddev)
 
 out_free_conf:
        md_unregister_thread(&mddev->thread);
-       if (conf->r10bio_pool)
-               mempool_destroy(conf->r10bio_pool);
+       mempool_destroy(conf->r10bio_pool);
        safe_put_page(conf->tmppage);
        kfree(conf->mirrors);
        kfree(conf);
@@ -3696,8 +3719,7 @@ static void raid10_free(struct mddev *mddev, void *priv)
 {
        struct r10conf *conf = priv;
 
-       if (conf->r10bio_pool)
-               mempool_destroy(conf->r10bio_pool);
+       mempool_destroy(conf->r10bio_pool);
        safe_put_page(conf->tmppage);
        kfree(conf->mirrors);
        kfree(conf->mirrors_old);
index 15ef2c641b2b93e96004d073463fdcfaaaaceab4..45933c1606972c007fee4393b82c05db7b24f7ec 100644 (file)
@@ -2271,8 +2271,7 @@ static void shrink_stripes(struct r5conf *conf)
               drop_one_stripe(conf))
                ;
 
-       if (conf->slab_cache)
-               kmem_cache_destroy(conf->slab_cache);
+       kmem_cache_destroy(conf->slab_cache);
        conf->slab_cache = NULL;
 }
 
@@ -3150,6 +3149,8 @@ handle_failed_stripe(struct r5conf *conf, struct stripe_head *sh,
                        spin_unlock_irq(&sh->stripe_lock);
                        if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
                                wake_up(&conf->wait_for_overlap);
+                       if (bi)
+                               s->to_read--;
                        while (bi && bi->bi_iter.bi_sector <
                               sh->dev[i].sector + STRIPE_SECTORS) {
                                struct bio *nextbi =
@@ -3169,6 +3170,8 @@ handle_failed_stripe(struct r5conf *conf, struct stripe_head *sh,
                 */
                clear_bit(R5_LOCKED, &sh->dev[i].flags);
        }
+       s->to_write = 0;
+       s->written = 0;
 
        if (test_and_clear_bit(STRIPE_FULL_WRITE, &sh->state))
                if (atomic_dec_and_test(&conf->pending_full_writes))
@@ -3300,7 +3303,7 @@ static int need_this_block(struct stripe_head *sh, struct stripe_head_state *s,
                 */
                return 0;
 
-       for (i = 0; i < s->failed; i++) {
+       for (i = 0; i < s->failed && i < 2; i++) {
                if (fdev[i]->towrite &&
                    !test_bit(R5_UPTODATE, &fdev[i]->flags) &&
                    !test_bit(R5_OVERWRITE, &fdev[i]->flags))
@@ -3324,7 +3327,7 @@ static int need_this_block(struct stripe_head *sh, struct stripe_head_state *s,
            sh->sector < sh->raid_conf->mddev->recovery_cp)
                /* reconstruct-write isn't being forced */
                return 0;
-       for (i = 0; i < s->failed; i++) {
+       for (i = 0; i < s->failed && i < 2; i++) {
                if (s->failed_num[i] != sh->pd_idx &&
                    s->failed_num[i] != sh->qd_idx &&
                    !test_bit(R5_UPTODATE, &fdev[i]->flags) &&
@@ -3496,6 +3499,7 @@ returnbi:
                }
        if (!discard_pending &&
            test_bit(R5_Discard, &sh->dev[sh->pd_idx].flags)) {
+               int hash;
                clear_bit(R5_Discard, &sh->dev[sh->pd_idx].flags);
                clear_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags);
                if (sh->qd_idx >= 0) {
@@ -3509,16 +3513,17 @@ returnbi:
                 * no updated data, so remove it from hash list and the stripe
                 * will be reinitialized
                 */
-               spin_lock_irq(&conf->device_lock);
 unhash:
+               hash = sh->hash_lock_index;
+               spin_lock_irq(conf->hash_locks + hash);
                remove_hash(sh);
+               spin_unlock_irq(conf->hash_locks + hash);
                if (head_sh->batch_head) {
                        sh = list_first_entry(&sh->batch_list,
                                              struct stripe_head, batch_list);
                        if (sh != head_sh)
                                        goto unhash;
                }
-               spin_unlock_irq(&conf->device_lock);
                sh = head_sh;
 
                if (test_bit(STRIPE_SYNC_REQUESTED, &sh->state))
index b055319d532edd93ff85f5e68c57e4ae1ac9493a..c1e2d1834b782096ff3e35fefa3db8bb5c2bb786 100644 (file)
@@ -46,8 +46,8 @@ extern struct dvb_frontend *horus3a_attach(struct dvb_frontend *fe,
                                        const struct horus3a_config *config,
                                        struct i2c_adapter *i2c);
 #else
-static inline struct dvb_frontend *horus3a_attach(
-                                       const struct cxd2820r_config *config,
+static inline struct dvb_frontend *horus3a_attach(struct dvb_frontend *fe,
+                                       const struct horus3a_config *config,
                                        struct i2c_adapter *i2c)
 {
        printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
index 69f30e21f6b31f96497c3d6acccc4a0000b7e822..1f329ef05accea6601a093e33078b5104ef2cfa2 100644 (file)
@@ -43,7 +43,7 @@ struct dvb_frontend *lnbh25_attach(
        struct lnbh25_config *cfg,
        struct i2c_adapter *i2c);
 #else
-static inline dvb_frontend *lnbh25_attach(
+static inline struct dvb_frontend *lnbh25_attach(
        struct dvb_frontend *fe,
        struct lnbh25_config *cfg,
        struct i2c_adapter *i2c)
index ff31e7a01ca9aba8f9746e61d5091d2d1f45c255..feeeb70d841ed92a485e4ec630b1133d51c75291 100644 (file)
 
 static struct dvb_frontend_ops m88ds3103_ops;
 
+/* write single register with mask */
+static int m88ds3103_update_bits(struct m88ds3103_dev *dev,
+                               u8 reg, u8 mask, u8 val)
+{
+       int ret;
+       u8 tmp;
+
+       /* no need for read if whole reg is written */
+       if (mask != 0xff) {
+               ret = regmap_bulk_read(dev->regmap, reg, &tmp, 1);
+               if (ret)
+                       return ret;
+
+               val &= mask;
+               tmp &= ~mask;
+               val |= tmp;
+       }
+
+       return regmap_bulk_write(dev->regmap, reg, &val, 1);
+}
+
 /* write reg val table using reg addr auto increment */
 static int m88ds3103_wr_reg_val_tab(struct m88ds3103_dev *dev,
                const struct m88ds3103_reg_val *tab, int tab_len)
@@ -394,10 +415,10 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe)
                        u8tmp2 = 0x00; /* 0b00 */
                        break;
                }
-               ret = regmap_update_bits(dev->regmap, 0x22, 0xc0, u8tmp1 << 6);
+               ret = m88ds3103_update_bits(dev, 0x22, 0xc0, u8tmp1 << 6);
                if (ret)
                        goto err;
-               ret = regmap_update_bits(dev->regmap, 0x24, 0xc0, u8tmp2 << 6);
+               ret = m88ds3103_update_bits(dev, 0x24, 0xc0, u8tmp2 << 6);
                if (ret)
                        goto err;
        }
@@ -455,13 +476,13 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe)
                        if (ret)
                                goto err;
                }
-               ret = regmap_update_bits(dev->regmap, 0x9d, 0x08, 0x08);
+               ret = m88ds3103_update_bits(dev, 0x9d, 0x08, 0x08);
                if (ret)
                        goto err;
                ret = regmap_write(dev->regmap, 0xf1, 0x01);
                if (ret)
                        goto err;
-               ret = regmap_update_bits(dev->regmap, 0x30, 0x80, 0x80);
+               ret = m88ds3103_update_bits(dev, 0x30, 0x80, 0x80);
                if (ret)
                        goto err;
        }
@@ -498,7 +519,7 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe)
        switch (dev->cfg->ts_mode) {
        case M88DS3103_TS_SERIAL:
        case M88DS3103_TS_SERIAL_D7:
-               ret = regmap_update_bits(dev->regmap, 0x29, 0x20, u8tmp1);
+               ret = m88ds3103_update_bits(dev, 0x29, 0x20, u8tmp1);
                if (ret)
                        goto err;
                u8tmp1 = 0;
@@ -567,11 +588,11 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe)
        if (ret)
                goto err;
 
-       ret = regmap_update_bits(dev->regmap, 0x4d, 0x02, dev->cfg->spec_inv << 1);
+       ret = m88ds3103_update_bits(dev, 0x4d, 0x02, dev->cfg->spec_inv << 1);
        if (ret)
                goto err;
 
-       ret = regmap_update_bits(dev->regmap, 0x30, 0x10, dev->cfg->agc_inv << 4);
+       ret = m88ds3103_update_bits(dev, 0x30, 0x10, dev->cfg->agc_inv << 4);
        if (ret)
                goto err;
 
@@ -625,13 +646,13 @@ static int m88ds3103_init(struct dvb_frontend *fe)
        dev->warm = false;
 
        /* wake up device from sleep */
-       ret = regmap_update_bits(dev->regmap, 0x08, 0x01, 0x01);
+       ret = m88ds3103_update_bits(dev, 0x08, 0x01, 0x01);
        if (ret)
                goto err;
-       ret = regmap_update_bits(dev->regmap, 0x04, 0x01, 0x00);
+       ret = m88ds3103_update_bits(dev, 0x04, 0x01, 0x00);
        if (ret)
                goto err;
-       ret = regmap_update_bits(dev->regmap, 0x23, 0x10, 0x00);
+       ret = m88ds3103_update_bits(dev, 0x23, 0x10, 0x00);
        if (ret)
                goto err;
 
@@ -749,18 +770,18 @@ static int m88ds3103_sleep(struct dvb_frontend *fe)
                utmp = 0x29;
        else
                utmp = 0x27;
-       ret = regmap_update_bits(dev->regmap, utmp, 0x01, 0x00);
+       ret = m88ds3103_update_bits(dev, utmp, 0x01, 0x00);
        if (ret)
                goto err;
 
        /* sleep */
-       ret = regmap_update_bits(dev->regmap, 0x08, 0x01, 0x00);
+       ret = m88ds3103_update_bits(dev, 0x08, 0x01, 0x00);
        if (ret)
                goto err;
-       ret = regmap_update_bits(dev->regmap, 0x04, 0x01, 0x01);
+       ret = m88ds3103_update_bits(dev, 0x04, 0x01, 0x01);
        if (ret)
                goto err;
-       ret = regmap_update_bits(dev->regmap, 0x23, 0x10, 0x10);
+       ret = m88ds3103_update_bits(dev, 0x23, 0x10, 0x10);
        if (ret)
                goto err;
 
@@ -992,12 +1013,12 @@ static int m88ds3103_set_tone(struct dvb_frontend *fe,
        }
 
        utmp = tone << 7 | dev->cfg->envelope_mode << 5;
-       ret = regmap_update_bits(dev->regmap, 0xa2, 0xe0, utmp);
+       ret = m88ds3103_update_bits(dev, 0xa2, 0xe0, utmp);
        if (ret)
                goto err;
 
        utmp = 1 << 2;
-       ret = regmap_update_bits(dev->regmap, 0xa1, reg_a1_mask, utmp);
+       ret = m88ds3103_update_bits(dev, 0xa1, reg_a1_mask, utmp);
        if (ret)
                goto err;
 
@@ -1047,7 +1068,7 @@ static int m88ds3103_set_voltage(struct dvb_frontend *fe,
        voltage_dis ^= dev->cfg->lnb_en_pol;
 
        utmp = voltage_dis << 1 | voltage_sel << 0;
-       ret = regmap_update_bits(dev->regmap, 0xa2, 0x03, utmp);
+       ret = m88ds3103_update_bits(dev, 0xa2, 0x03, utmp);
        if (ret)
                goto err;
 
@@ -1080,7 +1101,7 @@ static int m88ds3103_diseqc_send_master_cmd(struct dvb_frontend *fe,
        }
 
        utmp = dev->cfg->envelope_mode << 5;
-       ret = regmap_update_bits(dev->regmap, 0xa2, 0xe0, utmp);
+       ret = m88ds3103_update_bits(dev, 0xa2, 0xe0, utmp);
        if (ret)
                goto err;
 
@@ -1115,12 +1136,12 @@ static int m88ds3103_diseqc_send_master_cmd(struct dvb_frontend *fe,
        } else {
                dev_dbg(&client->dev, "diseqc tx timeout\n");
 
-               ret = regmap_update_bits(dev->regmap, 0xa1, 0xc0, 0x40);
+               ret = m88ds3103_update_bits(dev, 0xa1, 0xc0, 0x40);
                if (ret)
                        goto err;
        }
 
-       ret = regmap_update_bits(dev->regmap, 0xa2, 0xc0, 0x80);
+       ret = m88ds3103_update_bits(dev, 0xa2, 0xc0, 0x80);
        if (ret)
                goto err;
 
@@ -1152,7 +1173,7 @@ static int m88ds3103_diseqc_send_burst(struct dvb_frontend *fe,
        }
 
        utmp = dev->cfg->envelope_mode << 5;
-       ret = regmap_update_bits(dev->regmap, 0xa2, 0xe0, utmp);
+       ret = m88ds3103_update_bits(dev, 0xa2, 0xe0, utmp);
        if (ret)
                goto err;
 
@@ -1194,12 +1215,12 @@ static int m88ds3103_diseqc_send_burst(struct dvb_frontend *fe,
        } else {
                dev_dbg(&client->dev, "diseqc tx timeout\n");
 
-               ret = regmap_update_bits(dev->regmap, 0xa1, 0xc0, 0x40);
+               ret = m88ds3103_update_bits(dev, 0xa1, 0xc0, 0x40);
                if (ret)
                        goto err;
        }
 
-       ret = regmap_update_bits(dev->regmap, 0xa2, 0xc0, 0x80);
+       ret = m88ds3103_update_bits(dev, 0xa2, 0xc0, 0x80);
        if (ret)
                goto err;
 
@@ -1435,13 +1456,13 @@ static int m88ds3103_probe(struct i2c_client *client,
                goto err_kfree;
 
        /* sleep */
-       ret = regmap_update_bits(dev->regmap, 0x08, 0x01, 0x00);
+       ret = m88ds3103_update_bits(dev, 0x08, 0x01, 0x00);
        if (ret)
                goto err_kfree;
-       ret = regmap_update_bits(dev->regmap, 0x04, 0x01, 0x01);
+       ret = m88ds3103_update_bits(dev, 0x04, 0x01, 0x01);
        if (ret)
                goto err_kfree;
-       ret = regmap_update_bits(dev->regmap, 0x23, 0x10, 0x10);
+       ret = m88ds3103_update_bits(dev, 0x23, 0x10, 0x10);
        if (ret)
                goto err_kfree;
 
index 81788c5a44d838dc1f6e27e7c060db174af56913..821a8f481507a14ec3857c66cd7c4744a6ac3efd 100644 (file)
@@ -502,6 +502,10 @@ static int si2168_init(struct dvb_frontend *fe)
                /* firmware is in the new format */
                for (remaining = fw->size; remaining > 0; remaining -= 17) {
                        len = fw->data[fw->size - remaining];
+                       if (len > SI2168_ARGLEN) {
+                               ret = -EINVAL;
+                               break;
+                       }
                        memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len);
                        cmd.wlen = len;
                        cmd.rlen = 1;
index f55b3276f28de0122c3f4e4385cb3a1736d0b430..56773f3893d40e02d6b9cde1a72fcf0108ad350d 100644 (file)
@@ -80,11 +80,9 @@ irqreturn_t netup_spi_interrupt(struct netup_spi *spi)
        u16 reg;
        unsigned long flags;
 
-       if (!spi) {
-               dev_dbg(&spi->master->dev,
-                       "%s(): SPI not initialized\n", __func__);
+       if (!spi)
                return IRQ_NONE;
-       }
+
        spin_lock_irqsave(&spi->lock, flags);
        reg = readw(&spi->regs->control_stat);
        if (!(reg & NETUP_SPI_CTRL_IRQ)) {
@@ -234,11 +232,9 @@ void netup_spi_release(struct netup_unidvb_dev *ndev)
        unsigned long flags;
        struct netup_spi *spi = ndev->spi;
 
-       if (!spi) {
-               dev_dbg(&spi->master->dev,
-                       "%s(): SPI not initialized\n", __func__);
+       if (!spi)
                return;
-       }
+
        spin_lock_irqsave(&spi->lock, flags);
        reg = readw(&spi->regs->control_stat);
        writew(reg | NETUP_SPI_CTRL_IRQ, &spi->regs->control_stat);
index 486aef50d99b23e4753cbd055221cd2dbb4f6097..f922f2e827bcbb2bfe8cd0606fac89d3ec8c5bd6 100644 (file)
@@ -1097,7 +1097,7 @@ static int load_slim_core_fw(const struct firmware *fw, void *context)
        Elf32_Ehdr *ehdr;
        Elf32_Phdr *phdr;
        u8 __iomem *dst;
-       int err, i;
+       int err = 0, i;
 
        if (!fw || !context)
                return -EINVAL;
@@ -1106,7 +1106,7 @@ static int load_slim_core_fw(const struct firmware *fw, void *context)
        phdr = (Elf32_Phdr *)(fw->data + ehdr->e_phoff);
 
        /* go through the available ELF segments */
-       for (i = 0; i < ehdr->e_phnum && !err; i++, phdr++) {
+       for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
 
                /* Only consider LOAD segments */
                if (phdr->p_type != PT_LOAD)
@@ -1192,7 +1192,6 @@ err:
 
 static int load_c8sectpfe_fw_step1(struct c8sectpfei *fei)
 {
-       int ret;
        int err;
 
        dev_info(fei->dev, "Loading firmware: %s\n", FIRMWARE_MEMDMA);
@@ -1207,7 +1206,7 @@ static int load_c8sectpfe_fw_step1(struct c8sectpfei *fei)
        if (err) {
                dev_err(fei->dev, "request_firmware_nowait err: %d.\n", err);
                complete_all(&fei->fw_ack);
-               return ret;
+               return err;
        }
 
        return 0;
index 1c087cb76815a3ab488cb53db85cf98b5b0cac80..d0549fba711c474a1d58e416bbff09dad9a2f328 100644 (file)
@@ -257,7 +257,7 @@ static int hix5hd2_ir_probe(struct platform_device *pdev)
                goto clkerr;
 
        if (devm_request_irq(dev, priv->irq, hix5hd2_ir_rx_interrupt,
-                            IRQF_NO_SUSPEND, pdev->name, priv) < 0) {
+                            0, pdev->name, priv) < 0) {
                dev_err(dev, "IRQ %d register failed\n", priv->irq);
                ret = -EINVAL;
                goto regerr;
index 507382160e5e7524022c782240c36f98c1b54871..ce157edd45fa1adb3dd382037dd421f8b8590091 100644 (file)
@@ -166,6 +166,10 @@ static int si2157_init(struct dvb_frontend *fe)
 
        for (remaining = fw->size; remaining > 0; remaining -= 17) {
                len = fw->data[fw->size - remaining];
+               if (len > SI2157_ARGLEN) {
+                       dev_err(&client->dev, "Bad firmware length\n");
+                       goto err_release_firmware;
+               }
                memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len);
                cmd.wlen = len;
                cmd.rlen = 1;
index c3cac4c12fb3c6c18315ab83941a3454dc5ce9bd..197a4f2e54d2a1c08a3c662b3f983b57bf8190dd 100644 (file)
@@ -34,6 +34,14 @@ static int rtl28xxu_ctrl_msg(struct dvb_usb_device *d, struct rtl28xxu_req *req)
        unsigned int pipe;
        u8 requesttype;
 
+       mutex_lock(&d->usb_mutex);
+
+       if (req->size > sizeof(dev->buf)) {
+               dev_err(&d->intf->dev, "too large message %u\n", req->size);
+               ret = -EINVAL;
+               goto err_mutex_unlock;
+       }
+
        if (req->index & CMD_WR_FLAG) {
                /* write */
                memcpy(dev->buf, req->data, req->size);
@@ -50,14 +58,17 @@ static int rtl28xxu_ctrl_msg(struct dvb_usb_device *d, struct rtl28xxu_req *req)
        dvb_usb_dbg_usb_control_msg(d->udev, 0, requesttype, req->value,
                        req->index, dev->buf, req->size);
        if (ret < 0)
-               goto err;
+               goto err_mutex_unlock;
 
        /* read request, copy returned data to return buf */
        if (requesttype == (USB_TYPE_VENDOR | USB_DIR_IN))
                memcpy(req->data, dev->buf, req->size);
 
+       mutex_unlock(&d->usb_mutex);
+
        return 0;
-err:
+err_mutex_unlock:
+       mutex_unlock(&d->usb_mutex);
        dev_dbg(&d->intf->dev, "failed=%d\n", ret);
        return ret;
 }
index 9f6115a2ee0166d509584d5b5c5fd0b62d5bff06..138062960a7367737521659acc607983c921a685 100644 (file)
@@ -71,7 +71,7 @@
 
 
 struct rtl28xxu_dev {
-       u8 buf[28];
+       u8 buf[128];
        u8 chip_id;
        u8 tuner;
        char *tuner_name;
index 82876a67f1449b62f02142f4a677aee8880c295a..9beece00869bf0e27a99fc641b8f926c0d3bad8f 100644 (file)
@@ -47,7 +47,7 @@ config V4L2_MEM2MEM_DEV
 # Used by LED subsystem flash drivers
 config V4L2_FLASH_LED_CLASS
        tristate "V4L2 flash API for LED flash class devices"
-       depends on VIDEO_V4L2_SUBDEV_API
+       depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
        depends on LEDS_CLASS_FLASH
        ---help---
          Say Y here to enable V4L2 flash API support for LED flash
index c6a644b22af44e53b5cee18fc596df48ff675835..6f3154613dc7174b04a7e91dff0af1d3aae9b31e 100644 (file)
@@ -58,12 +58,18 @@ config OMAP_GPMC
          memory drives like NOR, NAND, OneNAND, SRAM.
 
 config OMAP_GPMC_DEBUG
-       bool
+       bool "Enable GPMC debug output and skip reset of GPMC during init"
        depends on OMAP_GPMC
        help
          Enables verbose debugging mostly to decode the bootloader provided
-         timings. Enable this during development to configure devices
-         connected to the GPMC bus.
+         timings. To preserve the bootloader provided timings, the reset
+         of GPMC is skipped during init. Enable this during development to
+         configure devices connected to the GPMC bus.
+
+         NOTE: In addition to matching the register setup with the bootloader
+         you also need to match the GPMC FCLK frequency used by the
+         bootloader or else the GPMC timings won't be identical with the
+         bootloader timings.
 
 config MVEBU_DEVBUS
        bool "Marvell EBU Device Bus Controller"
index 32ac049f2bc4dbda4418587cc017cc074d5989c9..6515dfc2b805d6c5198756e17bacd23724689dac 100644 (file)
@@ -696,7 +696,6 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t,
        int div;
        u32 l;
 
-       gpmc_cs_show_timings(cs, "before gpmc_cs_set_timings");
        div = gpmc_calc_divider(t->sync_clk);
        if (div < 0)
                return div;
@@ -1988,6 +1987,7 @@ static int gpmc_probe_generic_child(struct platform_device *pdev,
        if (ret < 0)
                goto err;
 
+       gpmc_cs_show_timings(cs, "before gpmc_cs_program_settings");
        ret = gpmc_cs_program_settings(cs, &gpmc_s);
        if (ret < 0)
                goto err;
index 4b54128bc78ed35f07c6d974a4aa420ff5377699..a726f01e3b026931bdf782dd8e00f2838c8d66a3 100644 (file)
@@ -138,7 +138,7 @@ static void asic3_irq_flip_edge(struct asic3 *asic,
        spin_unlock_irqrestore(&asic->lock, flags);
 }
 
-static void asic3_irq_demux(unsigned int irq, struct irq_desc *desc)
+static void asic3_irq_demux(struct irq_desc *desc)
 {
        struct asic3 *asic = irq_desc_get_handler_data(desc);
        struct irq_data *data = irq_desc_get_irq_data(desc);
index a76eb6ef47a042980871be48257d92e1e72c1208..b279205659a4280b3ab2c578b4b7825e2cfb47d4 100644 (file)
@@ -205,7 +205,7 @@ static void pcap_isr_work(struct work_struct *work)
        } while (gpio_get_value(pdata->gpio));
 }
 
-static void pcap_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void pcap_irq_handler(struct irq_desc *desc)
 {
        struct pcap_chip *pcap = irq_desc_get_handler_data(desc);
 
index 9131cdcdc64a4a30ed09dfa2697436e53a7cd14a..6ccaf90d98fd6e1020da79583c076591d683342b 100644 (file)
@@ -98,7 +98,7 @@ static struct irq_chip egpio_muxed_chip = {
        .irq_unmask     = egpio_unmask,
 };
 
-static void egpio_handler(unsigned int irq, struct irq_desc *desc)
+static void egpio_handler(struct irq_desc *desc)
 {
        struct egpio_info *ei = irq_desc_get_handler_data(desc);
        int irqpin;
index f28cb28a62f87073c214d47368355be6c29c6f25..2c7f8d7c0595e2d849183dfd0db91d2d945daa10 100644 (file)
@@ -42,6 +42,8 @@ int intel_lpss_resume(struct device *dev);
        .thaw = intel_lpss_resume,              \
        .poweroff = intel_lpss_suspend,         \
        .restore = intel_lpss_resume,
+#else
+#define INTEL_LPSS_SLEEP_PM_OPS
 #endif
 
 #define INTEL_LPSS_RUNTIME_PM_OPS              \
index 5bb49f08955d03dc4e646d17c1f8e4f026a18170..798e44306382e1bb12dc37a3727d74a912846631 100644 (file)
@@ -65,7 +65,7 @@ struct jz4740_adc {
        spinlock_t lock;
 };
 
-static void jz4740_adc_irq_demux(unsigned int irq, struct irq_desc *desc)
+static void jz4740_adc_irq_demux(struct irq_desc *desc)
 {
        struct irq_chip_generic *gc = irq_desc_get_handler_data(desc);
        uint8_t status;
index c52162ea3d0ab1daf8bd375220669f3ba53db15e..586098f1b233a6d19da9e74e1d2dd2e396408635 100644 (file)
@@ -80,7 +80,7 @@ static int max77843_chg_init(struct max77693_dev *max77843)
        if (!max77843->i2c_chg) {
                dev_err(&max77843->i2c->dev,
                                "Cannot allocate I2C device for Charger\n");
-               return PTR_ERR(max77843->i2c_chg);
+               return -ENODEV;
        }
        i2c_set_clientdata(max77843->i2c_chg, max77843);
 
index 59502d02cd158f3492492ccf96c0451bd7ee19e6..1b7ec0870c2a8e0a8e772bcf93f15d701fa1a1e0 100644 (file)
@@ -156,7 +156,7 @@ static int pm8xxx_irq_master_handler(struct pm_irq_chip *chip, int master)
        return ret;
 }
 
-static void pm8xxx_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void pm8xxx_irq_handler(struct irq_desc *desc)
 {
        struct pm_irq_chip *chip = irq_desc_get_handler_data(desc);
        struct irq_chip *irq_chip = irq_desc_get_chip(desc);
index 16fc1adc4fa36b12b941f6cdd69be0b42ff4ddea..94bd89cb1f0618581d3f190f2decb1e6b8a0ef7e 100644 (file)
@@ -185,7 +185,7 @@ static struct mfd_cell t7l66xb_cells[] = {
 /*--------------------------------------------------------------------------*/
 
 /* Handle the T7L66XB interrupt mux */
-static void t7l66xb_irq(unsigned int irq, struct irq_desc *desc)
+static void t7l66xb_irq(struct irq_desc *desc)
 {
        struct t7l66xb *t7l66xb = irq_desc_get_handler_data(desc);
        unsigned int isr;
index 775b9aca871a30c12403644ac213a5718d0e81aa..8c84a513016b6869e6cb03e0324d5729c18ba16d 100644 (file)
@@ -522,8 +522,7 @@ static int tc6393xb_register_gpio(struct tc6393xb *tc6393xb, int gpio_base)
 
 /*--------------------------------------------------------------------------*/
 
-static void
-tc6393xb_irq(unsigned int irq, struct irq_desc *desc)
+static void tc6393xb_irq(struct irq_desc *desc)
 {
        struct tc6393xb *tc6393xb = irq_desc_get_handler_data(desc);
        unsigned int isr;
index 9a2302129711f92e42c5b030272f15a3aef44997..f691d7ecad526c7acf07272e49a9cc001737bf58 100644 (file)
@@ -282,7 +282,7 @@ void ucb1x00_adc_disable(struct ucb1x00 *ucb)
  * SIBCLK to talk to the chip.  We leave the clock running until
  * we have finished processing all interrupts from the chip.
  */
-static void ucb1x00_irq(unsigned int __irq, struct irq_desc *desc)
+static void ucb1x00_irq(struct irq_desc *desc)
 {
        struct ucb1x00 *ucb = irq_desc_get_handler_data(desc);
        unsigned int isr, i;
index 6f484dfe78f937ce2248b5d9761271d59b258fd2..6982f603fadc51a20154f38cbf1f82d95125f8df 100644 (file)
@@ -1,4 +1,4 @@
-ccflags-y := -Werror
+ccflags-y := -Werror -Wno-unused-const-variable
 
 cxl-y                          += main.o file.o irq.o fault.o native.o
 cxl-y                          += context.o sysfs.o debugfs.o pci.o trace.o
index 8af12c884b04eeb870d21ae2bb4bf15e0cfb76c4..103baf0e0c5bfd9aa23537adf12f6035bb427d86 100644 (file)
@@ -105,6 +105,7 @@ EXPORT_SYMBOL_GPL(cxl_allocate_afu_irqs);
 
 void cxl_free_afu_irqs(struct cxl_context *ctx)
 {
+       afu_irq_name_free(ctx);
        cxl_release_irq_ranges(&ctx->irqs, ctx->afu->adapter);
 }
 EXPORT_SYMBOL_GPL(cxl_free_afu_irqs);
index e762f85ee233a4b510390aa0ce4a5a79266b84c3..2faa1270d085b15f92e185f8f389f5790390fbef 100644 (file)
@@ -275,6 +275,9 @@ static void reclaim_ctx(struct rcu_head *rcu)
        if (ctx->kernelapi)
                kfree(ctx->mapping);
 
+       if (ctx->irq_bitmap)
+               kfree(ctx->irq_bitmap);
+
        kfree(ctx);
 }
 
index 1c30ef77073d607cd250ade57c08b110fffd092f..0cfb9c129f273cbdf0a408c6b5d3008bd308596d 100644 (file)
@@ -677,6 +677,7 @@ int cxl_register_serr_irq(struct cxl_afu *afu);
 void cxl_release_serr_irq(struct cxl_afu *afu);
 int afu_register_irqs(struct cxl_context *ctx, u32 count);
 void afu_release_irqs(struct cxl_context *ctx, void *cookie);
+void afu_irq_name_free(struct cxl_context *ctx);
 irqreturn_t cxl_slice_irq_err(int irq, void *data);
 
 int cxl_debugfs_init(void);
index a30bf285b5bdd75c3f2b357d89dbab251bb98c7c..7ccd2998be92b8b3f7cdca2a0acbf3f9586d0f34 100644 (file)
@@ -120,9 +120,16 @@ int afu_release(struct inode *inode, struct file *file)
                 __func__, ctx->pe);
        cxl_context_detach(ctx);
 
-       mutex_lock(&ctx->mapping_lock);
-       ctx->mapping = NULL;
-       mutex_unlock(&ctx->mapping_lock);
+
+       /*
+        * Delete the context's mapping pointer, unless it's created by the
+        * kernel API, in which case leave it so it can be freed by reclaim_ctx()
+        */
+       if (!ctx->kernelapi) {
+               mutex_lock(&ctx->mapping_lock);
+               ctx->mapping = NULL;
+               mutex_unlock(&ctx->mapping_lock);
+       }
 
        put_device(&ctx->afu->dev);
 
index 583b42afeda2355da2e606f4fbc33546445a8df6..09a406058c4650ddf71114c26201889620003b9e 100644 (file)
@@ -414,7 +414,7 @@ void cxl_release_psl_irq(struct cxl_afu *afu)
        kfree(afu->psl_irq_name);
 }
 
-static void afu_irq_name_free(struct cxl_context *ctx)
+void afu_irq_name_free(struct cxl_context *ctx)
 {
        struct cxl_irq_name *irq_name, *tmp;
 
@@ -524,7 +524,5 @@ void afu_release_irqs(struct cxl_context *ctx, void *cookie)
        afu_irq_name_free(ctx);
        cxl_release_irq_ranges(&ctx->irqs, ctx->afu->adapter);
 
-       kfree(ctx->irq_bitmap);
-       ctx->irq_bitmap = NULL;
        ctx->irq_count = 0;
 }
index b37f2e8004f5bcd58f970ea274ebd29ef4b1eae3..d2e75c88f4d2165762913c27c57e5d4487e431ad 100644 (file)
@@ -457,6 +457,7 @@ static int activate_afu_directed(struct cxl_afu *afu)
 
        dev_info(&afu->dev, "Activating AFU directed mode\n");
 
+       afu->num_procs = afu->max_procs_virtualised;
        if (afu->spa == NULL) {
                if (cxl_alloc_spa(afu))
                        return -ENOMEM;
@@ -468,7 +469,6 @@ static int activate_afu_directed(struct cxl_afu *afu)
        cxl_p1n_write(afu, CXL_PSL_ID_An, CXL_PSL_ID_An_F | CXL_PSL_ID_An_L);
 
        afu->current_mode = CXL_MODE_DIRECTED;
-       afu->num_procs = afu->max_procs_virtualised;
 
        if ((rc = cxl_chardev_m_afu_add(afu)))
                return rc;
index 02c85160bfe9f63400d62435b48721804edf3496..85761d7eb333173040204a7a5593bf2c7cf06485 100644 (file)
@@ -1035,6 +1035,32 @@ static int cxl_read_vsec(struct cxl *adapter, struct pci_dev *dev)
        return 0;
 }
 
+/*
+ * Workaround a PCIe Host Bridge defect on some cards, that can cause
+ * malformed Transaction Layer Packet (TLP) errors to be erroneously
+ * reported. Mask this error in the Uncorrectable Error Mask Register.
+ *
+ * The upper nibble of the PSL revision is used to distinguish between
+ * different cards. The affected ones have it set to 0.
+ */
+static void cxl_fixup_malformed_tlp(struct cxl *adapter, struct pci_dev *dev)
+{
+       int aer;
+       u32 data;
+
+       if (adapter->psl_rev & 0xf000)
+               return;
+       if (!(aer = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR)))
+               return;
+       pci_read_config_dword(dev, aer + PCI_ERR_UNCOR_MASK, &data);
+       if (data & PCI_ERR_UNC_MALF_TLP)
+               if (data & PCI_ERR_UNC_INTN)
+                       return;
+       data |= PCI_ERR_UNC_MALF_TLP;
+       data |= PCI_ERR_UNC_INTN;
+       pci_write_config_dword(dev, aer + PCI_ERR_UNCOR_MASK, data);
+}
+
 static int cxl_vsec_looks_ok(struct cxl *adapter, struct pci_dev *dev)
 {
        if (adapter->vsec_status & CXL_STATUS_SECOND_PORT)
@@ -1134,6 +1160,8 @@ static int cxl_configure_adapter(struct cxl *adapter, struct pci_dev *dev)
        if ((rc = cxl_vsec_looks_ok(adapter, dev)))
                return rc;
 
+       cxl_fixup_malformed_tlp(adapter, dev);
+
        if ((rc = setup_cxl_bars(dev)))
                return rc;
 
@@ -1249,8 +1277,6 @@ static int cxl_probe(struct pci_dev *dev, const struct pci_device_id *id)
        int slice;
        int rc;
 
-       pci_dev_get(dev);
-
        if (cxl_verbose)
                dump_cxl_config_space(dev);
 
index 25868c2ec03ea76287a8681b7d229cc7f223c8cc..02006f7109a802821c3134ec03ed7d8658f23da7 100644 (file)
@@ -592,6 +592,8 @@ int cxl_sysfs_afu_add(struct cxl_afu *afu)
 
        /* conditionally create the add the binary file for error info buffer */
        if (afu->eb_len) {
+               sysfs_attr_init(&afu->attr_eb.attr);
+
                afu->attr_eb.attr.name = "afu_err_buff";
                afu->attr_eb.attr.mode = S_IRUGO;
                afu->attr_eb.size = afu->eb_len;
index 6dd16a6d153f0e55f0f4f7d122b4b27012a3b329..94b520896b18350fdf3c7d59c5789718bc75a58e 100644 (file)
@@ -48,6 +48,12 @@ static bool cxl_pci_enable_device_hook(struct pci_dev *dev)
 
        phb = pci_bus_to_host(dev->bus);
        afu = (struct cxl_afu *)phb->private_data;
+
+       if (!cxl_adapter_link_ok(afu->adapter)) {
+               dev_warn(&dev->dev, "%s: Device link is down, refusing to enable AFU\n", __func__);
+               return false;
+       }
+
        set_dma_ops(&dev->dev, &dma_direct_ops);
        set_dma_offset(&dev->dev, PAGE_OFFSET);
 
index 4b469cf9e60f8d77d07fe64f8cc958b19f2ff0e7..8504dbeacd3b0c5feb64f72a50ad1eb0625fda68 100644 (file)
@@ -204,6 +204,8 @@ int mei_dbgfs_register(struct mei_device *dev, const char *name)
        if (!dir)
                return -ENOMEM;
 
+       dev->dbgfs_dir = dir;
+
        f = debugfs_create_file("meclients", S_IRUSR, dir,
                                dev, &mei_dbgfs_fops_meclients);
        if (!f) {
@@ -228,7 +230,6 @@ int mei_dbgfs_register(struct mei_device *dev, const char *name)
                dev_err(dev->dev, "allow_fixed_address: registration failed\n");
                goto err;
        }
-       dev->dbgfs_dir = dir;
        return 0;
 err:
        mei_dbgfs_deregister(dev);
index 8eec887c8f701ce732a6278a49b1fbe298ca0635..6d7c188fb65c8ce288817e0ffb5728764e2ac133 100644 (file)
@@ -1209,7 +1209,7 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
                 * after the host receives the enum_resp
                 * message clients may be added or removed
                 */
-               if (dev->hbm_state <= MEI_HBM_ENUM_CLIENTS &&
+               if (dev->hbm_state <= MEI_HBM_ENUM_CLIENTS ||
                    dev->hbm_state >= MEI_HBM_STOPPED) {
                        dev_err(dev->dev, "hbm: add client: state mismatch, [%d, %d]\n",
                                dev->dev_state, dev->hbm_state);
index b78cf5d403a33b74244a39245b9df6f9024c4d24..7fc9174d46191a13c77fa4e220bb476a32dfe05e 100644 (file)
@@ -2263,15 +2263,12 @@ static int mmc_test_profile_sglen_r_nonblock_perf(struct mmc_test_card *test)
 /*
  * eMMC hardware reset.
  */
-static int mmc_test_hw_reset(struct mmc_test_card *test)
+static int mmc_test_reset(struct mmc_test_card *test)
 {
        struct mmc_card *card = test->card;
        struct mmc_host *host = card->host;
        int err;
 
-       if (!mmc_card_mmc(card) || !mmc_can_reset(card))
-               return RESULT_UNSUP_CARD;
-
        err = mmc_hw_reset(host);
        if (!err)
                return RESULT_OK;
@@ -2605,8 +2602,8 @@ static const struct mmc_test_case mmc_test_cases[] = {
        },
 
        {
-               .name = "eMMC hardware reset",
-               .run = mmc_test_hw_reset,
+               .name = "Reset test",
+               .run = mmc_test_reset,
        },
 };
 
index 0520064dc33beb164aa9d80642c371e227d599b1..a3eb20bdcd97bf32d7a56d741b1bde5097d65767 100644 (file)
@@ -134,9 +134,11 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
        int err = cmd->error;
 
        /* Flag re-tuning needed on CRC errors */
-       if (err == -EILSEQ || (mrq->sbc && mrq->sbc->error == -EILSEQ) ||
+       if ((cmd->opcode != MMC_SEND_TUNING_BLOCK &&
+           cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200) &&
+           (err == -EILSEQ || (mrq->sbc && mrq->sbc->error == -EILSEQ) ||
            (mrq->data && mrq->data->error == -EILSEQ) ||
-           (mrq->stop && mrq->stop->error == -EILSEQ))
+           (mrq->stop && mrq->stop->error == -EILSEQ)))
                mmc_retune_needed(host);
 
        if (err && cmd->retries && mmc_host_is_spi(host)) {
index abd933b7029bec26b7adebbea2db8fe3be426eb6..5466f25f0281e7b8a83ce4f34d21d1c14a3ebe4a 100644 (file)
@@ -457,7 +457,7 @@ int mmc_of_parse(struct mmc_host *host)
                                           0, &cd_gpio_invert);
                if (!ret)
                        dev_info(host->parent, "Got CD GPIO\n");
-               else if (ret != -ENOENT)
+               else if (ret != -ENOENT && ret != -ENOSYS)
                        return ret;
 
                /*
@@ -481,7 +481,7 @@ int mmc_of_parse(struct mmc_host *host)
        ret = mmc_gpiod_request_ro(host, "wp", 0, false, 0, &ro_gpio_invert);
        if (!ret)
                dev_info(host->parent, "Got WP GPIO\n");
-       else if (ret != -ENOENT)
+       else if (ret != -ENOENT && ret != -ENOSYS)
                return ret;
 
        if (of_property_read_bool(np, "disable-wp"))
index e726903170a828cffd69a1cb2e7f80d59c0d5152..f6cd995dbe920392cce50062ff2e4f080634ee06 100644 (file)
@@ -1924,7 +1924,6 @@ EXPORT_SYMBOL(mmc_can_reset);
 static int mmc_reset(struct mmc_host *host)
 {
        struct mmc_card *card = host->card;
-       u32 status;
 
        if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset)
                return -EOPNOTSUPP;
@@ -1937,12 +1936,6 @@ static int mmc_reset(struct mmc_host *host)
 
        host->ops->hw_reset(host);
 
-       /* If the reset has happened, then a status command will fail */
-       if (!mmc_send_status(card, &status)) {
-               mmc_host_clk_release(host);
-               return -ENOSYS;
-       }
-
        /* Set initial state and call mmc_set_ios */
        mmc_set_initial_state(host);
        mmc_host_clk_release(host);
index 781e4db317671ce6146dea121a56f42f90e7c491..7fb0753abe3041bc1814ebc14c1136d103b254e1 100644 (file)
@@ -182,6 +182,7 @@ struct omap_hsmmc_host {
        struct  clk             *fclk;
        struct  clk             *dbclk;
        struct  regulator       *pbias;
+       bool                    pbias_enabled;
        void    __iomem         *base;
        int                     vqmmc_enabled;
        resource_size_t         mapbase;
@@ -328,20 +329,22 @@ static int omap_hsmmc_set_pbias(struct omap_hsmmc_host *host, bool power_on,
                        return ret;
                }
 
-               if (!regulator_is_enabled(host->pbias)) {
+               if (host->pbias_enabled == 0) {
                        ret = regulator_enable(host->pbias);
                        if (ret) {
                                dev_err(host->dev, "pbias reg enable fail\n");
                                return ret;
                        }
+                       host->pbias_enabled = 1;
                }
        } else {
-               if (regulator_is_enabled(host->pbias)) {
+               if (host->pbias_enabled == 1) {
                        ret = regulator_disable(host->pbias);
                        if (ret) {
                                dev_err(host->dev, "pbias reg disable fail\n");
                                return ret;
                        }
+                       host->pbias_enabled = 0;
                }
        }
 
@@ -475,7 +478,7 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host)
        mmc->supply.vmmc = devm_regulator_get_optional(host->dev, "vmmc");
        if (IS_ERR(mmc->supply.vmmc)) {
                ret = PTR_ERR(mmc->supply.vmmc);
-               if (ret != -ENODEV)
+               if ((ret != -ENODEV) && host->dev->of_node)
                        return ret;
                dev_dbg(host->dev, "unable to get vmmc regulator %ld\n",
                        PTR_ERR(mmc->supply.vmmc));
@@ -490,7 +493,7 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host)
        mmc->supply.vqmmc = devm_regulator_get_optional(host->dev, "vmmc_aux");
        if (IS_ERR(mmc->supply.vqmmc)) {
                ret = PTR_ERR(mmc->supply.vqmmc);
-               if (ret != -ENODEV)
+               if ((ret != -ENODEV) && host->dev->of_node)
                        return ret;
                dev_dbg(host->dev, "unable to get vmmc_aux regulator %ld\n",
                        PTR_ERR(mmc->supply.vqmmc));
@@ -500,7 +503,7 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host)
        host->pbias = devm_regulator_get_optional(host->dev, "pbias");
        if (IS_ERR(host->pbias)) {
                ret = PTR_ERR(host->pbias);
-               if (ret != -ENODEV)
+               if ((ret != -ENODEV) && host->dev->of_node)
                        return ret;
                dev_dbg(host->dev, "unable to get pbias regulator %ld\n",
                        PTR_ERR(host->pbias));
@@ -2053,6 +2056,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
        host->base      = base + pdata->reg_offset;
        host->power_mode = MMC_POWER_OFF;
        host->next_data.cookie = 1;
+       host->pbias_enabled = 0;
        host->vqmmc_enabled = 0;
 
        ret = omap_hsmmc_gpio_init(mmc, host, pdata);
index 1420f29628c70d8e8fdedbfa3fe7d77f1ba0ae0b..8cadd74e8407bb08d7e277a82ac5d80d496f77e4 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/mmc/host.h>
+#include <linux/mmc/slot-gpio.h>
 #include <linux/io.h>
 #include <linux/regulator/consumer.h>
 #include <linux/gpio.h>
@@ -454,12 +455,8 @@ static int pxamci_get_ro(struct mmc_host *mmc)
 {
        struct pxamci_host *host = mmc_priv(mmc);
 
-       if (host->pdata && gpio_is_valid(host->pdata->gpio_card_ro)) {
-               if (host->pdata->gpio_card_ro_invert)
-                       return !gpio_get_value(host->pdata->gpio_card_ro);
-               else
-                       return gpio_get_value(host->pdata->gpio_card_ro);
-       }
+       if (host->pdata && gpio_is_valid(host->pdata->gpio_card_ro))
+               return mmc_gpio_get_ro(mmc);
        if (host->pdata && host->pdata->get_ro)
                return !!host->pdata->get_ro(mmc_dev(mmc));
        /*
@@ -551,6 +548,7 @@ static void pxamci_enable_sdio_irq(struct mmc_host *host, int enable)
 
 static const struct mmc_host_ops pxamci_ops = {
        .request                = pxamci_request,
+       .get_cd                 = mmc_gpio_get_cd,
        .get_ro                 = pxamci_get_ro,
        .set_ios                = pxamci_set_ios,
        .enable_sdio_irq        = pxamci_enable_sdio_irq,
@@ -790,37 +788,31 @@ static int pxamci_probe(struct platform_device *pdev)
                gpio_power = host->pdata->gpio_power;
        }
        if (gpio_is_valid(gpio_power)) {
-               ret = gpio_request(gpio_power, "mmc card power");
+               ret = devm_gpio_request(&pdev->dev, gpio_power,
+                                       "mmc card power");
                if (ret) {
-                       dev_err(&pdev->dev, "Failed requesting gpio_power %d\n", gpio_power);
+                       dev_err(&pdev->dev, "Failed requesting gpio_power %d\n",
+                               gpio_power);
                        goto out;
                }
                gpio_direction_output(gpio_power,
                                      host->pdata->gpio_power_invert);
        }
-       if (gpio_is_valid(gpio_ro)) {
-               ret = gpio_request(gpio_ro, "mmc card read only");
-               if (ret) {
-                       dev_err(&pdev->dev, "Failed requesting gpio_ro %d\n", gpio_ro);
-                       goto err_gpio_ro;
-               }
-               gpio_direction_input(gpio_ro);
+       if (gpio_is_valid(gpio_ro))
+               ret = mmc_gpio_request_ro(mmc, gpio_ro);
+       if (ret) {
+               dev_err(&pdev->dev, "Failed requesting gpio_ro %d\n", gpio_ro);
+               goto out;
+       } else {
+               mmc->caps |= host->pdata->gpio_card_ro_invert ?
+                       MMC_CAP2_RO_ACTIVE_HIGH : 0;
        }
-       if (gpio_is_valid(gpio_cd)) {
-               ret = gpio_request(gpio_cd, "mmc card detect");
-               if (ret) {
-                       dev_err(&pdev->dev, "Failed requesting gpio_cd %d\n", gpio_cd);
-                       goto err_gpio_cd;
-               }
-               gpio_direction_input(gpio_cd);
 
-               ret = request_irq(gpio_to_irq(gpio_cd), pxamci_detect_irq,
-                                 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
-                                 "mmc card detect", mmc);
-               if (ret) {
-                       dev_err(&pdev->dev, "failed to request card detect IRQ\n");
-                       goto err_request_irq;
-               }
+       if (gpio_is_valid(gpio_cd))
+               ret = mmc_gpio_request_cd(mmc, gpio_cd, 0);
+       if (ret) {
+               dev_err(&pdev->dev, "Failed requesting gpio_cd %d\n", gpio_cd);
+               goto out;
        }
 
        if (host->pdata && host->pdata->init)
@@ -835,13 +827,7 @@ static int pxamci_probe(struct platform_device *pdev)
 
        return 0;
 
-err_request_irq:
-       gpio_free(gpio_cd);
-err_gpio_cd:
-       gpio_free(gpio_ro);
-err_gpio_ro:
-       gpio_free(gpio_power);
- out:
+out:
        if (host) {
                if (host->dma_chan_rx)
                        dma_release_channel(host->dma_chan_rx);
@@ -873,14 +859,6 @@ static int pxamci_remove(struct platform_device *pdev)
                        gpio_ro = host->pdata->gpio_card_ro;
                        gpio_power = host->pdata->gpio_power;
                }
-               if (gpio_is_valid(gpio_cd)) {
-                       free_irq(gpio_to_irq(gpio_cd), mmc);
-                       gpio_free(gpio_cd);
-               }
-               if (gpio_is_valid(gpio_ro))
-                       gpio_free(gpio_ro);
-               if (gpio_is_valid(gpio_power))
-                       gpio_free(gpio_power);
                if (host->vcc)
                        regulator_put(host->vcc);
 
index d1556643a41d325abc7b7637ac94c694e778fedc..a0f05de5409f7d0c42f3d2457ff4dc1bb0e74f3c 100644 (file)
@@ -43,6 +43,7 @@ static const struct sdhci_ops sdhci_at91_sama5d2_ops = {
 
 static const struct sdhci_pltfm_data soc_data_sama5d2 = {
        .ops = &sdhci_at91_sama5d2_ops,
+       .quirks2 = SDHCI_QUIRK2_NEED_DELAY_AFTER_INT_CLK_RST,
 };
 
 static const struct of_device_id sdhci_at91_dt_match[] = {
index 946d37f94a31b29e8739304ec71cf7b1468eead6..f5edf9d3a18a2088a2b08705d876c413b1d659b5 100644 (file)
@@ -135,6 +135,7 @@ static int armada_38x_quirks(struct platform_device *pdev,
        struct sdhci_pxa *pxa = pltfm_host->priv;
        struct resource *res;
 
+       host->quirks &= ~SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN;
        host->quirks |= SDHCI_QUIRK_MISSING_CAPS;
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
                                           "conf-sdio3");
@@ -290,6 +291,9 @@ static void pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
                    uhs == MMC_TIMING_UHS_DDR50) {
                        reg_val &= ~SDIO3_CONF_CLK_INV;
                        reg_val |= SDIO3_CONF_SD_FB_CLK;
+               } else if (uhs == MMC_TIMING_MMC_HS) {
+                       reg_val &= ~SDIO3_CONF_CLK_INV;
+                       reg_val &= ~SDIO3_CONF_SD_FB_CLK;
                } else {
                        reg_val |= SDIO3_CONF_CLK_INV;
                        reg_val &= ~SDIO3_CONF_SD_FB_CLK;
@@ -398,7 +402,7 @@ static int sdhci_pxav3_probe(struct platform_device *pdev)
        if (of_device_is_compatible(np, "marvell,armada-380-sdhci")) {
                ret = armada_38x_quirks(pdev, host);
                if (ret < 0)
-                       goto err_clk_get;
+                       goto err_mbus_win;
                ret = mv_conf_mbus_windows(pdev, mv_mbus_dram_info());
                if (ret < 0)
                        goto err_mbus_win;
index 64b7fdbd1a9ccab80034e8a38660ef944daf8bae..fbc7efdddcb5a4cb9c2726b91e2ee29acfa85f08 100644 (file)
@@ -1160,6 +1160,8 @@ void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
        host->mmc->actual_clock = 0;
 
        sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
+       if (host->quirks2 & SDHCI_QUIRK2_NEED_DELAY_AFTER_INT_CLK_RST)
+               mdelay(1);
 
        if (clock == 0)
                return;
index 7c02ff46c8ac3ecdaf37e792fd6bcb43c9bd029e..9d4aa31b683ac2d64e16f31f88d8d0893162a225 100644 (file)
@@ -412,6 +412,11 @@ struct sdhci_host {
 #define SDHCI_QUIRK2_ACMD23_BROKEN                     (1<<14)
 /* Broken Clock divider zero in controller */
 #define SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN             (1<<15)
+/*
+ * When internal clock is disabled, a delay is needed before modifying the
+ * SD clock frequency or enabling back the internal clock.
+ */
+#define SDHCI_QUIRK2_NEED_DELAY_AFTER_INT_CLK_RST      (1<<16)
 
        int irq;                /* Device IRQ */
        void __iomem *ioaddr;   /* Mapped address */
index a7b7a67715986d748d9f880088cc2ae069bd2283..b981b8552e43aad1778e7e7e7277b75d73884c68 100644 (file)
 #define SDXC_IDMAC_DES0_CES    BIT(30) /* card error summary */
 #define SDXC_IDMAC_DES0_OWN    BIT(31) /* 1-idma owns it, 0-host owns it */
 
+#define SDXC_CLK_400K          0
+#define SDXC_CLK_25M           1
+#define SDXC_CLK_50M           2
+#define SDXC_CLK_50M_DDR       3
+
+struct sunxi_mmc_clk_delay {
+       u32 output;
+       u32 sample;
+};
+
 struct sunxi_idma_des {
        u32     config;
        u32     buf_size;
@@ -229,6 +239,7 @@ struct sunxi_mmc_host {
        struct clk      *clk_mmc;
        struct clk      *clk_sample;
        struct clk      *clk_output;
+       const struct sunxi_mmc_clk_delay *clk_delays;
 
        /* irq */
        spinlock_t      lock;
@@ -654,25 +665,19 @@ static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host,
 
        /* determine delays */
        if (rate <= 400000) {
-               oclk_dly = 180;
-               sclk_dly = 42;
+               oclk_dly = host->clk_delays[SDXC_CLK_400K].output;
+               sclk_dly = host->clk_delays[SDXC_CLK_400K].sample;
        } else if (rate <= 25000000) {
-               oclk_dly = 180;
-               sclk_dly = 75;
+               oclk_dly = host->clk_delays[SDXC_CLK_25M].output;
+               sclk_dly = host->clk_delays[SDXC_CLK_25M].sample;
        } else if (rate <= 50000000) {
                if (ios->timing == MMC_TIMING_UHS_DDR50) {
-                       oclk_dly = 60;
-                       sclk_dly = 120;
+                       oclk_dly = host->clk_delays[SDXC_CLK_50M_DDR].output;
+                       sclk_dly = host->clk_delays[SDXC_CLK_50M_DDR].sample;
                } else {
-                       oclk_dly = 90;
-                       sclk_dly = 150;
+                       oclk_dly = host->clk_delays[SDXC_CLK_50M].output;
+                       sclk_dly = host->clk_delays[SDXC_CLK_50M].sample;
                }
-       } else if (rate <= 100000000) {
-               oclk_dly = 6;
-               sclk_dly = 24;
-       } else if (rate <= 200000000) {
-               oclk_dly = 3;
-               sclk_dly = 12;
        } else {
                return -EINVAL;
        }
@@ -871,6 +876,7 @@ static void sunxi_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
 static const struct of_device_id sunxi_mmc_of_match[] = {
        { .compatible = "allwinner,sun4i-a10-mmc", },
        { .compatible = "allwinner,sun5i-a13-mmc", },
+       { .compatible = "allwinner,sun9i-a80-mmc", },
        { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, sunxi_mmc_of_match);
@@ -884,6 +890,20 @@ static struct mmc_host_ops sunxi_mmc_ops = {
        .hw_reset        = sunxi_mmc_hw_reset,
 };
 
+static const struct sunxi_mmc_clk_delay sunxi_mmc_clk_delays[] = {
+       [SDXC_CLK_400K]         = { .output = 180, .sample = 180 },
+       [SDXC_CLK_25M]          = { .output = 180, .sample =  75 },
+       [SDXC_CLK_50M]          = { .output =  90, .sample = 120 },
+       [SDXC_CLK_50M_DDR]      = { .output =  60, .sample = 120 },
+};
+
+static const struct sunxi_mmc_clk_delay sun9i_mmc_clk_delays[] = {
+       [SDXC_CLK_400K]         = { .output = 180, .sample = 180 },
+       [SDXC_CLK_25M]          = { .output = 180, .sample =  75 },
+       [SDXC_CLK_50M]          = { .output = 150, .sample = 120 },
+       [SDXC_CLK_50M_DDR]      = { .output =  90, .sample = 120 },
+};
+
 static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,
                                      struct platform_device *pdev)
 {
@@ -895,6 +915,11 @@ static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,
        else
                host->idma_des_size_bits = 16;
 
+       if (of_device_is_compatible(np, "allwinner,sun9i-a80-mmc"))
+               host->clk_delays = sun9i_mmc_clk_delays;
+       else
+               host->clk_delays = sunxi_mmc_clk_delays;
+
        ret = mmc_regulator_get_supply(host->mmc);
        if (ret) {
                if (ret != -EPROBE_DEFER)
index 2426db88db36bf95f1f247eeae597ff69238c70d..f04445b992f512c537018b81bf0d685a3ee2f62b 100644 (file)
@@ -879,7 +879,7 @@ static void copy_spare(struct mtd_info *mtd, bool bfrom)
                                      oob_chunk_size);
 
                /* the last chunk */
-               memcpy16_toio(&s[oob_chunk_size * sparebuf_size],
+               memcpy16_toio(&s[i * sparebuf_size],
                              &d[i * oob_chunk_size],
                              host->used_oobsize - i * oob_chunk_size);
        }
index f97a58d6aae1bbbacdb29ca86ac30c1f21d19e48..e7d333c162befd274f891b8674b5ca8fd905315e 100644 (file)
 #define NFC_ECC_MODE           GENMASK(15, 12)
 #define NFC_RANDOM_SEED                GENMASK(30, 16)
 
+/* NFC_USER_DATA helper macros */
+#define NFC_BUF_TO_USER_DATA(buf)      ((buf)[0] | ((buf)[1] << 8) | \
+                                       ((buf)[2] << 16) | ((buf)[3] << 24))
+
 #define NFC_DEFAULT_TIMEOUT_MS 1000
 
 #define NFC_SRAM_SIZE          1024
@@ -646,15 +650,9 @@ static int sunxi_nfc_hw_ecc_write_page(struct mtd_info *mtd,
                offset = layout->eccpos[i * ecc->bytes] - 4 + mtd->writesize;
 
                /* Fill OOB data in */
-               if (oob_required) {
-                       tmp = 0xffffffff;
-                       memcpy_toio(nfc->regs + NFC_REG_USER_DATA_BASE, &tmp,
-                                   4);
-               } else {
-                       memcpy_toio(nfc->regs + NFC_REG_USER_DATA_BASE,
-                                   chip->oob_poi + offset - mtd->writesize,
-                                   4);
-               }
+               writel(NFC_BUF_TO_USER_DATA(chip->oob_poi +
+                                           layout->oobfree[i].offset),
+                      nfc->regs + NFC_REG_USER_DATA_BASE);
 
                chip->cmdfunc(mtd, NAND_CMD_RNDIN, offset, -1);
 
@@ -784,14 +782,8 @@ static int sunxi_nfc_hw_syndrome_ecc_write_page(struct mtd_info *mtd,
                offset += ecc->size;
 
                /* Fill OOB data in */
-               if (oob_required) {
-                       tmp = 0xffffffff;
-                       memcpy_toio(nfc->regs + NFC_REG_USER_DATA_BASE, &tmp,
-                                   4);
-               } else {
-                       memcpy_toio(nfc->regs + NFC_REG_USER_DATA_BASE, oob,
-                                   4);
-               }
+               writel(NFC_BUF_TO_USER_DATA(oob),
+                      nfc->regs + NFC_REG_USER_DATA_BASE);
 
                tmp = NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ACCESS_DIR |
                      (1 << 30);
@@ -1389,6 +1381,7 @@ static void sunxi_nand_chips_cleanup(struct sunxi_nfc *nfc)
                                        node);
                nand_release(&chip->mtd);
                sunxi_nand_ecc_cleanup(&chip->nand.ecc);
+               list_del(&chip->node);
        }
 }
 
index 5bbd1f094f4e33dca9c7ad3dca3edc7736b7e0bb..1fc23e48fe8e49fc947c972cca179399a60a37ec 100644 (file)
@@ -926,6 +926,11 @@ static int validate_vid_hdr(const struct ubi_device *ubi,
                goto bad;
        }
 
+       if (data_size > ubi->leb_size) {
+               ubi_err(ubi, "bad data_size");
+               goto bad;
+       }
+
        if (vol_type == UBI_VID_STATIC) {
                /*
                 * Although from high-level point of view static volumes may
index 80bdd5b88bac271fbd01f5496be76bf1b79f0d9a..d85c1976216078d2f1647b34ba5873c9c86439a0 100644 (file)
@@ -649,6 +649,7 @@ static int init_volumes(struct ubi_device *ubi,
                if (ubi->corr_peb_count)
                        ubi_err(ubi, "%d PEBs are corrupted and not used",
                                ubi->corr_peb_count);
+               return -ENOSPC;
        }
        ubi->rsvd_pebs += reserved_pebs;
        ubi->avail_pebs -= reserved_pebs;
index 275d9fb6fe5c541c7253ece5cacc7ae189110eba..eb4489f9082fe84345d2ec68b0f8723888e5c177 100644 (file)
@@ -1601,6 +1601,7 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
                if (ubi->corr_peb_count)
                        ubi_err(ubi, "%d PEBs are corrupted and not used",
                                ubi->corr_peb_count);
+               err = -ENOSPC;
                goto out_free;
        }
        ubi->avail_pebs -= reserved_pebs;
index 10f71c732b5995c9121acf41724848f49994b49f..816d0e94961c9fec79ed48eefe7450a806df7f39 100644 (file)
@@ -326,7 +326,7 @@ static void arcdev_setup(struct net_device *dev)
        dev->type = ARPHRD_ARCNET;
        dev->netdev_ops = &arcnet_netdev_ops;
        dev->header_ops = &arcnet_header_ops;
-       dev->hard_header_len = sizeof(struct archdr);
+       dev->hard_header_len = sizeof(struct arc_hardware);
        dev->mtu = choose_mtu();
 
        dev->addr_len = ARCNET_ALEN;
index e5fac368068a2320eb06d207934c4b969356237b..131026fbc2d77cbc3ccb5903daa10f8920f8ae17 100644 (file)
@@ -87,6 +87,7 @@ static const struct pci_device_id peak_pci_tbl[] = {
        {PEAK_PCI_VENDOR_ID, PEAK_PC_104P_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
        {PEAK_PCI_VENDOR_ID, PEAK_PCI_104E_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
        {PEAK_PCI_VENDOR_ID, PEAK_CPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+       {PEAK_PCI_VENDOR_ID, PEAK_PCIE_OEM_ID, PCI_ANY_ID, PCI_ANY_ID,},
 #ifdef CONFIG_CAN_PEAK_PCIEC
        {PEAK_PCI_VENDOR_ID, PEAK_PCIEC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
        {PEAK_PCI_VENDOR_ID, PEAK_PCIEC34_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
index 6f13f72067621411383bc381e20b314427d6c8e6..1f7dd927cc5ea4777530a8ba23daae631f258bf9 100644 (file)
@@ -2000,6 +2000,7 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
                 */
                reg = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_PCS_CTRL);
                if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) {
+                       reg &= ~PORT_PCS_CTRL_UNFORCED;
                        reg |= PORT_PCS_CTRL_FORCE_LINK |
                                PORT_PCS_CTRL_LINK_UP |
                                PORT_PCS_CTRL_DUPLEX_FULL |
@@ -2050,6 +2051,8 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port)
                                reg |= PORT_CONTROL_FRAME_ETHER_TYPE_DSA;
                        else
                                reg |= PORT_CONTROL_FRAME_MODE_DSA;
+                       reg |= PORT_CONTROL_FORWARD_UNKNOWN |
+                               PORT_CONTROL_FORWARD_UNKNOWN_MC;
                }
 
                if (mv88e6xxx_6352_family(ds) || mv88e6xxx_6351_family(ds) ||
index 48ce83e443c2b12bbcbc2e2545c5ac6b1983f3d0..8d50314ac3eb1f308d1cc556270058aba05c7b60 100644 (file)
@@ -847,21 +847,25 @@ static int emac_probe(struct platform_device *pdev)
        if (ndev->irq == -ENXIO) {
                netdev_err(ndev, "No irq resource\n");
                ret = ndev->irq;
-               goto out;
+               goto out_iounmap;
        }
 
        db->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(db->clk)) {
                ret = PTR_ERR(db->clk);
-               goto out;
+               goto out_iounmap;
        }
 
-       clk_prepare_enable(db->clk);
+       ret = clk_prepare_enable(db->clk);
+       if (ret) {
+               dev_err(&pdev->dev, "Error couldn't enable clock (%d)\n", ret);
+               goto out_iounmap;
+       }
 
        ret = sunxi_sram_claim(&pdev->dev);
        if (ret) {
                dev_err(&pdev->dev, "Error couldn't map SRAM to device\n");
-               goto out;
+               goto out_clk_disable_unprepare;
        }
 
        db->phy_node = of_parse_phandle(np, "phy", 0);
@@ -910,6 +914,10 @@ static int emac_probe(struct platform_device *pdev)
 
 out_release_sram:
        sunxi_sram_release(&pdev->dev);
+out_clk_disable_unprepare:
+       clk_disable_unprepare(db->clk);
+out_iounmap:
+       iounmap(db->membase);
 out:
        dev_err(db->dev, "not found (%d).\n", ret);
 
@@ -921,8 +929,12 @@ out:
 static int emac_remove(struct platform_device *pdev)
 {
        struct net_device *ndev = platform_get_drvdata(pdev);
+       struct emac_board_info *db = netdev_priv(ndev);
 
        unregister_netdev(ndev);
+       sunxi_sram_release(&pdev->dev);
+       clk_disable_unprepare(db->clk);
+       iounmap(db->membase);
        free_netdev(ndev);
 
        dev_dbg(&pdev->dev, "released and freed device\n");
index 2c063b60db4b02bc48246887fb5d98f6b3de0394..96f485ab612e679dc7065b1e214cb9d73c690d43 100644 (file)
@@ -327,9 +327,13 @@ void xgbe_debugfs_init(struct xgbe_prv_data *pdata)
        pdata->debugfs_xpcs_reg = 0;
 
        buf = kasprintf(GFP_KERNEL, "amd-xgbe-%s", pdata->netdev->name);
+       if (!buf)
+               return;
+
        pdata->xgbe_debugfs = debugfs_create_dir(buf, NULL);
        if (!pdata->xgbe_debugfs) {
                netdev_err(pdata->netdev, "debugfs_create_dir failed\n");
+               kfree(buf);
                return;
        }
 
index a4473d8ff4fa0e1ec7bbdb511f9edd51f1871d71..f672dba345f7f73b028741ec60befa6ab012fd04 100644 (file)
@@ -1595,7 +1595,7 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
                                  packet->rdesc_count, 1);
 
        /* Make sure ownership is written to the descriptor */
-       dma_wmb();
+       smp_wmb();
 
        ring->cur = cur_index + 1;
        if (!packet->skb->xmit_more ||
index aae9d5ecd1822b16a2812de3bee503f59113adaa..dde0486667e0cfab87c593283d80a71f873977d3 100644 (file)
@@ -1807,6 +1807,7 @@ static int xgbe_tx_poll(struct xgbe_channel *channel)
        struct netdev_queue *txq;
        int processed = 0;
        unsigned int tx_packets = 0, tx_bytes = 0;
+       unsigned int cur;
 
        DBGPR("-->xgbe_tx_poll\n");
 
@@ -1814,10 +1815,15 @@ static int xgbe_tx_poll(struct xgbe_channel *channel)
        if (!ring)
                return 0;
 
+       cur = ring->cur;
+
+       /* Be sure we get ring->cur before accessing descriptor data */
+       smp_rmb();
+
        txq = netdev_get_tx_queue(netdev, channel->queue_index);
 
        while ((processed < XGBE_TX_DESC_MAX_PROC) &&
-              (ring->dirty != ring->cur)) {
+              (ring->dirty != cur)) {
                rdata = XGBE_GET_DESC_DATA(ring, ring->dirty);
                rdesc = rdata->rdesc;
 
index cfa37041ab715db677f7d986bf45f51bbcae0444..c4bb8027b3fb0824a38f012a02de57d372b76494 100644 (file)
@@ -689,16 +689,24 @@ static int xgene_enet_phy_connect(struct net_device *ndev)
                        netdev_dbg(ndev, "No phy-handle found in DT\n");
                        return -ENODEV;
                }
-               pdata->phy_dev = of_phy_find_device(phy_np);
-       }
 
-       phy_dev = pdata->phy_dev;
+               phy_dev = of_phy_connect(ndev, phy_np, &xgene_enet_adjust_link,
+                                        0, pdata->phy_mode);
+               if (!phy_dev) {
+                       netdev_err(ndev, "Could not connect to PHY\n");
+                       return -ENODEV;
+               }
+
+               pdata->phy_dev = phy_dev;
+       } else {
+               phy_dev = pdata->phy_dev;
 
-       if (!phy_dev ||
-           phy_connect_direct(ndev, phy_dev, &xgene_enet_adjust_link,
-                              pdata->phy_mode)) {
-               netdev_err(ndev, "Could not connect to PHY\n");
-               return  -ENODEV;
+               if (!phy_dev ||
+                   phy_connect_direct(ndev, phy_dev, &xgene_enet_adjust_link,
+                                      pdata->phy_mode)) {
+                       netdev_err(ndev, "Could not connect to PHY\n");
+                       return  -ENODEV;
+               }
        }
 
        pdata->phy_speed = SPEED_UNKNOWN;
index f9cb99bfb511896c0e6b9cb9559a714a72c30e1d..ffd180570920a1ddbd071d46f90056e3ddac43f2 100644 (file)
@@ -78,6 +78,7 @@ static const struct of_device_id emac_arc_dt_ids[] = {
        { .compatible = "snps,arc-emac" },
        { /* Sentinel */ }
 };
+MODULE_DEVICE_TABLE(of, emac_arc_dt_ids);
 
 static struct platform_driver emac_arc_driver = {
        .probe = emac_arc_probe,
index a7f2cc3e485eebfae962fe24cfc1142021a74cde..4183c2abeeeb2dc206f2ca4aa90d88279e2eb6d9 100644 (file)
@@ -2049,7 +2049,7 @@ static void swphy_poll_timer(unsigned long data)
 
        for (i = 0; i < priv->num_ports; i++) {
                struct bcm63xx_enetsw_port *port;
-               int val, j, up, advertise, lpa, lpa2, speed, duplex, media;
+               int val, j, up, advertise, lpa, speed, duplex, media;
                int external_phy = bcm_enet_port_is_rgmii(i);
                u8 override;
 
@@ -2092,22 +2092,27 @@ static void swphy_poll_timer(unsigned long data)
                lpa = bcmenet_sw_mdio_read(priv, external_phy, port->phy_id,
                                           MII_LPA);
 
-               lpa2 = bcmenet_sw_mdio_read(priv, external_phy, port->phy_id,
-                                           MII_STAT1000);
-
                /* figure out media and duplex from advertise and LPA values */
                media = mii_nway_result(lpa & advertise);
                duplex = (media & ADVERTISE_FULL) ? 1 : 0;
-               if (lpa2 & LPA_1000FULL)
-                       duplex = 1;
-
-               if (lpa2 & (LPA_1000FULL | LPA_1000HALF))
-                       speed = 1000;
-               else {
-                       if (media & (ADVERTISE_100FULL | ADVERTISE_100HALF))
-                               speed = 100;
-                       else
-                               speed = 10;
+
+               if (media & (ADVERTISE_100FULL | ADVERTISE_100HALF))
+                       speed = 100;
+               else
+                       speed = 10;
+
+               if (val & BMSR_ESTATEN) {
+                       advertise = bcmenet_sw_mdio_read(priv, external_phy,
+                                               port->phy_id, MII_CTRL1000);
+
+                       lpa = bcmenet_sw_mdio_read(priv, external_phy,
+                                               port->phy_id, MII_STAT1000);
+
+                       if (advertise & (ADVERTISE_1000FULL | ADVERTISE_1000HALF)
+                                       && lpa & (LPA_1000FULL | LPA_1000HALF)) {
+                               speed = 1000;
+                               duplex = (lpa & LPA_1000FULL);
+                       }
                }
 
                dev_info(&priv->pdev->dev,
index b9a5a97ed4dd4abc77c488cabdd0a47e99f0693f..f1b5364f352170236269a4dbe2e805e35b97ce16 100644 (file)
@@ -2079,6 +2079,7 @@ static const struct of_device_id bcm_sysport_of_match[] = {
        { .compatible = "brcm,systemport" },
        { /* sentinel */ }
 };
+MODULE_DEVICE_TABLE(of, bcm_sysport_of_match);
 
 static struct platform_driver bcm_sysport_driver = {
        .probe  = bcm_sysport_probe,
index ba936635322a83eee32f15e49f12e393ed924d38..b5e64b02200cd54e54a64b1812abac55e1674e06 100644 (file)
@@ -1946,6 +1946,7 @@ struct bnx2x {
        u16 vlan_cnt;
        u16 vlan_credit;
        u16 vxlan_dst_port;
+       u8 vxlan_dst_port_count;
        bool accept_any_vlan;
 };
 
index aeb7ce64452e14cd3cbe49325f63bae2d99e3ef2..be628bd9fb18b6f0116125e5a3f9ea16ad1d3561 100644 (file)
@@ -3351,6 +3351,13 @@ static int bnx2x_set_rss_flags(struct bnx2x *bp, struct ethtool_rxnfc *info)
                        udp_rss_requested = 0;
                else
                        return -EINVAL;
+
+               if (CHIP_IS_E1x(bp) && udp_rss_requested) {
+                       DP(BNX2X_MSG_ETHTOOL,
+                          "57710, 57711 boards don't support RSS according to UDP 4-tuple\n");
+                       return -EINVAL;
+               }
+
                if ((info->flow_type == UDP_V4_FLOW) &&
                    (bp->rss_conf_obj.udp_rss_v4 != udp_rss_requested)) {
                        bp->rss_conf_obj.udp_rss_v4 = udp_rss_requested;
index e3da2bddf143f0d68b8dbae7f02bd0d004a753cc..f1d62d5dbaff9a83ccacd0a530c855b14209eb7a 100644 (file)
@@ -3705,16 +3705,14 @@ out:
 
 void bnx2x_update_mfw_dump(struct bnx2x *bp)
 {
-       struct timeval epoc;
        u32 drv_ver;
        u32 valid_dump;
 
        if (!SHMEM2_HAS(bp, drv_info))
                return;
 
-       /* Update Driver load time */
-       do_gettimeofday(&epoc);
-       SHMEM2_WR(bp, drv_info.epoc, epoc.tv_sec);
+       /* Update Driver load time, possibly broken in y2038 */
+       SHMEM2_WR(bp, drv_info.epoc, (u32)ktime_get_real_seconds());
 
        drv_ver = bnx2x_update_mng_version_utility(DRV_MODULE_VERSION, true);
        SHMEM2_WR(bp, drv_info.drv_ver, drv_ver);
@@ -10110,12 +10108,18 @@ static void __bnx2x_add_vxlan_port(struct bnx2x *bp, u16 port)
        if (!netif_running(bp->dev))
                return;
 
-       if (bp->vxlan_dst_port || !IS_PF(bp)) {
+       if (bp->vxlan_dst_port_count && bp->vxlan_dst_port == port) {
+               bp->vxlan_dst_port_count++;
+               return;
+       }
+
+       if (bp->vxlan_dst_port_count || !IS_PF(bp)) {
                DP(BNX2X_MSG_SP, "Vxlan destination port limit reached\n");
                return;
        }
 
        bp->vxlan_dst_port = port;
+       bp->vxlan_dst_port_count = 1;
        bnx2x_schedule_sp_rtnl(bp, BNX2X_SP_RTNL_ADD_VXLAN_PORT, 0);
 }
 
@@ -10130,10 +10134,14 @@ static void bnx2x_add_vxlan_port(struct net_device *netdev,
 
 static void __bnx2x_del_vxlan_port(struct bnx2x *bp, u16 port)
 {
-       if (!bp->vxlan_dst_port || bp->vxlan_dst_port != port || !IS_PF(bp)) {
+       if (!bp->vxlan_dst_port_count || bp->vxlan_dst_port != port ||
+           !IS_PF(bp)) {
                DP(BNX2X_MSG_SP, "Invalid vxlan port\n");
                return;
        }
+       bp->vxlan_dst_port--;
+       if (bp->vxlan_dst_port)
+               return;
 
        if (netif_running(bp->dev)) {
                bnx2x_schedule_sp_rtnl(bp, BNX2X_SP_RTNL_DEL_VXLAN_PORT, 0);
index c9bd7f16018e7616b8cedf03c78c41dce058aa79..ff702a707a91a2065dc7500bfd98f232c3b71dd4 100644 (file)
@@ -4319,8 +4319,16 @@ static int bnx2x_setup_rss(struct bnx2x *bp,
 
        /* RSS keys */
        if (test_bit(BNX2X_RSS_SET_SRCH, &p->rss_flags)) {
-               memcpy(&data->rss_key[0], &p->rss_key[0],
-                      sizeof(data->rss_key));
+               u8 *dst = (u8 *)(data->rss_key) + sizeof(data->rss_key);
+               const u8 *src = (const u8 *)p->rss_key;
+               int i;
+
+               /* Apparently, bnx2x reads this array in reverse order
+                * We need to byte swap rss_key to comply with Toeplitz specs.
+                */
+               for (i = 0; i < sizeof(data->rss_key); i++)
+                       *--dst = *src++;
+
                caps |= ETH_RSS_UPDATE_RAMROD_DATA_UPDATE_RSS_KEY;
        }
 
index fadbd0088d3e6b3fa6b748c419e2586393d7da6f..1805541b4240e72c79445ea6f50bbc2a74ba13c7 100644 (file)
@@ -1683,6 +1683,24 @@ static void bcmgenet_intr_disable(struct bcmgenet_priv *priv)
        bcmgenet_intrl2_1_writel(priv, 0, INTRL2_CPU_MASK_CLEAR);
 }
 
+static void bcmgenet_link_intr_enable(struct bcmgenet_priv *priv)
+{
+       u32 int0_enable = 0;
+
+       /* Monitor cable plug/unplugged event for internal PHY, external PHY
+        * and MoCA PHY
+        */
+       if (priv->internal_phy) {
+               int0_enable |= UMAC_IRQ_LINK_EVENT;
+       } else if (priv->ext_phy) {
+               int0_enable |= UMAC_IRQ_LINK_EVENT;
+       } else if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) {
+               if (priv->hw_params->flags & GENET_HAS_MOCA_LINK_DET)
+                       int0_enable |= UMAC_IRQ_LINK_EVENT;
+       }
+       bcmgenet_intrl2_0_writel(priv, int0_enable, INTRL2_CPU_MASK_CLEAR);
+}
+
 static int init_umac(struct bcmgenet_priv *priv)
 {
        struct device *kdev = &priv->pdev->dev;
@@ -1723,15 +1741,8 @@ static int init_umac(struct bcmgenet_priv *priv)
        /* Enable Tx default queue 16 interrupts */
        int0_enable |= UMAC_IRQ_TXDMA_DONE;
 
-       /* Monitor cable plug/unplugged event for internal PHY */
-       if (priv->internal_phy) {
-               int0_enable |= UMAC_IRQ_LINK_EVENT;
-       } else if (priv->ext_phy) {
-               int0_enable |= UMAC_IRQ_LINK_EVENT;
-       } else if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) {
-               if (priv->hw_params->flags & GENET_HAS_MOCA_LINK_DET)
-                       int0_enable |= UMAC_IRQ_LINK_EVENT;
-
+       /* Configure backpressure vectors for MoCA */
+       if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) {
                reg = bcmgenet_bp_mc_get(priv);
                reg |= BIT(priv->hw_params->bp_in_en_shift);
 
@@ -2645,6 +2656,9 @@ static void bcmgenet_netif_start(struct net_device *dev)
 
        netif_tx_start_all_queues(dev);
 
+       /* Monitor link interrupts now */
+       bcmgenet_link_intr_enable(priv);
+
        phy_start(priv->phydev);
 }
 
@@ -3155,6 +3169,7 @@ static const struct of_device_id bcmgenet_match[] = {
        { .compatible = "brcm,genet-v4", .data = (void *)GENET_V4 },
        { },
 };
+MODULE_DEVICE_TABLE(of, bcmgenet_match);
 
 static int bcmgenet_probe(struct platform_device *pdev)
 {
index b7a0f7879de2d3ee4d2b419a3b26c5e7661224c6..9e59663a6eadb012de6f4a4474484800401fce3b 100644 (file)
@@ -1543,7 +1543,7 @@ bfa_flash_cmd_act_check(void __iomem *pci_bar)
 }
 
 /* Flush FLI data fifo. */
-static u32
+static int
 bfa_flash_fifo_flush(void __iomem *pci_bar)
 {
        u32 i;
@@ -1573,11 +1573,11 @@ bfa_flash_fifo_flush(void __iomem *pci_bar)
 }
 
 /* Read flash status. */
-static u32
+static int
 bfa_flash_status_read(void __iomem *pci_bar)
 {
        union bfa_flash_dev_status_reg  dev_status;
-       u32                             status;
+       int                             status;
        u32                     ret_status;
        int                             i;
 
@@ -1611,11 +1611,11 @@ bfa_flash_status_read(void __iomem *pci_bar)
 }
 
 /* Start flash read operation. */
-static u32
+static int
 bfa_flash_read_start(void __iomem *pci_bar, u32 offset, u32 len,
                     char *buf)
 {
-       u32 status;
+       int status;
 
        /* len must be mutiple of 4 and not exceeding fifo size */
        if (len == 0 || len > BFA_FLASH_FIFO_SIZE || (len & 0x03) != 0)
@@ -1703,7 +1703,8 @@ static enum bfa_status
 bfa_flash_raw_read(void __iomem *pci_bar, u32 offset, char *buf,
                   u32 len)
 {
-       u32 n, status;
+       u32 n;
+       int status;
        u32 off, l, s, residue, fifo_sz;
 
        residue = len;
index 5d0753cc7e735eb11d4228afced69c8afdae3818..04b0d16b210e89dd6eae3aa6704987e8543edeca 100644 (file)
@@ -2400,6 +2400,7 @@ bna_rx_create(struct bna *bna, struct bnad *bnad,
                q0->rcb->id = 0;
                q0->rx_packets = q0->rx_bytes = 0;
                q0->rx_packets_with_error = q0->rxbuf_alloc_failed = 0;
+               q0->rxbuf_map_failed = 0;
 
                bna_rxq_qpt_setup(q0, rxp, dpage_count, PAGE_SIZE,
                        &dqpt_mem[i], &dsqpt_mem[i], &dpage_mem[i]);
@@ -2428,6 +2429,7 @@ bna_rx_create(struct bna *bna, struct bnad *bnad,
                                        : rx_cfg->q1_buf_size;
                        q1->rx_packets = q1->rx_bytes = 0;
                        q1->rx_packets_with_error = q1->rxbuf_alloc_failed = 0;
+                       q1->rxbuf_map_failed = 0;
 
                        bna_rxq_qpt_setup(q1, rxp, hpage_count, PAGE_SIZE,
                                &hqpt_mem[i], &hsqpt_mem[i],
index e0e797f2ea147cd728562b9b9b0d8468d0551d04..c438d032e8bffcce79a2168460510cf385e4e7d5 100644 (file)
@@ -587,6 +587,7 @@ struct bna_rxq {
        u64             rx_bytes;
        u64             rx_packets_with_error;
        u64             rxbuf_alloc_failed;
+       u64             rxbuf_map_failed;
 };
 
 /* RxQ pair */
index 506047c386071db9472d60218faa004fe94849a8..21a0cfc3e7ec7a7b51479b5f3fc300bc0c7a6885 100644 (file)
@@ -399,7 +399,13 @@ bnad_rxq_refill_page(struct bnad *bnad, struct bna_rcb *rcb, u32 nalloc)
                }
 
                dma_addr = dma_map_page(&bnad->pcidev->dev, page, page_offset,
-                               unmap_q->map_size, DMA_FROM_DEVICE);
+                                       unmap_q->map_size, DMA_FROM_DEVICE);
+               if (dma_mapping_error(&bnad->pcidev->dev, dma_addr)) {
+                       put_page(page);
+                       BNAD_UPDATE_CTR(bnad, rxbuf_map_failed);
+                       rcb->rxq->rxbuf_map_failed++;
+                       goto finishing;
+               }
 
                unmap->page = page;
                unmap->page_offset = page_offset;
@@ -454,8 +460,15 @@ bnad_rxq_refill_skb(struct bnad *bnad, struct bna_rcb *rcb, u32 nalloc)
                        rcb->rxq->rxbuf_alloc_failed++;
                        goto finishing;
                }
+
                dma_addr = dma_map_single(&bnad->pcidev->dev, skb->data,
                                          buff_sz, DMA_FROM_DEVICE);
+               if (dma_mapping_error(&bnad->pcidev->dev, dma_addr)) {
+                       dev_kfree_skb_any(skb);
+                       BNAD_UPDATE_CTR(bnad, rxbuf_map_failed);
+                       rcb->rxq->rxbuf_map_failed++;
+                       goto finishing;
+               }
 
                unmap->skb = skb;
                dma_unmap_addr_set(&unmap->vector, dma_addr, dma_addr);
@@ -3025,6 +3038,11 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
        unmap = head_unmap;
        dma_addr = dma_map_single(&bnad->pcidev->dev, skb->data,
                                  len, DMA_TO_DEVICE);
+       if (dma_mapping_error(&bnad->pcidev->dev, dma_addr)) {
+               dev_kfree_skb_any(skb);
+               BNAD_UPDATE_CTR(bnad, tx_skb_map_failed);
+               return NETDEV_TX_OK;
+       }
        BNA_SET_DMA_ADDR(dma_addr, &txqent->vector[0].host_addr);
        txqent->vector[0].length = htons(len);
        dma_unmap_addr_set(&unmap->vectors[0], dma_addr, dma_addr);
@@ -3056,6 +3074,15 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
 
                dma_addr = skb_frag_dma_map(&bnad->pcidev->dev, frag,
                                            0, size, DMA_TO_DEVICE);
+               if (dma_mapping_error(&bnad->pcidev->dev, dma_addr)) {
+                       /* Undo the changes starting at tcb->producer_index */
+                       bnad_tx_buff_unmap(bnad, unmap_q, q_depth,
+                                          tcb->producer_index);
+                       dev_kfree_skb_any(skb);
+                       BNAD_UPDATE_CTR(bnad, tx_skb_map_failed);
+                       return NETDEV_TX_OK;
+               }
+
                dma_unmap_len_set(&unmap->vectors[vect_id], dma_len, size);
                BNA_SET_DMA_ADDR(dma_addr, &txqent->vector[vect_id].host_addr);
                txqent->vector[vect_id].length = htons(size);
index faedbf24777e1f7eb47dd40c12ca6ac1ad32afa1..f4ed816b93ee0dd270d967824cbcbe2f690e7d16 100644 (file)
@@ -175,6 +175,7 @@ struct bnad_drv_stats {
        u64             tx_skb_headlen_zero;
        u64             tx_skb_frag_zero;
        u64             tx_skb_len_mismatch;
+       u64             tx_skb_map_failed;
 
        u64             hw_stats_updates;
        u64             netif_rx_dropped;
@@ -189,6 +190,7 @@ struct bnad_drv_stats {
        u64             rx_unmap_q_alloc_failed;
 
        u64             rxbuf_alloc_failed;
+       u64             rxbuf_map_failed;
 };
 
 /* Complete driver stats */
index 2bdfc5dff4b120df6df6a6df63b0242ce7d59b02..0e4fdc3dd729752fef73f8a268ed795fa1d0a06d 100644 (file)
@@ -90,6 +90,7 @@ static const char *bnad_net_stats_strings[BNAD_ETHTOOL_STATS_NUM] = {
        "tx_skb_headlen_zero",
        "tx_skb_frag_zero",
        "tx_skb_len_mismatch",
+       "tx_skb_map_failed",
        "hw_stats_updates",
        "netif_rx_dropped",
 
@@ -102,6 +103,7 @@ static const char *bnad_net_stats_strings[BNAD_ETHTOOL_STATS_NUM] = {
        "tx_unmap_q_alloc_failed",
        "rx_unmap_q_alloc_failed",
        "rxbuf_alloc_failed",
+       "rxbuf_map_failed",
 
        "mac_stats_clr_cnt",
        "mac_frame_64",
@@ -807,6 +809,7 @@ bnad_per_q_stats_fill(struct bnad *bnad, u64 *buf, int bi)
                                                        rx_packets_with_error;
                                        buf[bi++] = rcb->rxq->
                                                        rxbuf_alloc_failed;
+                                       buf[bi++] = rcb->rxq->rxbuf_map_failed;
                                        buf[bi++] = rcb->producer_index;
                                        buf[bi++] = rcb->consumer_index;
                                }
@@ -821,6 +824,7 @@ bnad_per_q_stats_fill(struct bnad *bnad, u64 *buf, int bi)
                                                        rx_packets_with_error;
                                        buf[bi++] = rcb->rxq->
                                                        rxbuf_alloc_failed;
+                                       buf[bi++] = rcb->rxq->rxbuf_map_failed;
                                        buf[bi++] = rcb->producer_index;
                                        buf[bi++] = rcb->consumer_index;
                                }
index 9b35d142f47accfbaec039f0d8100fb45d68bbf8..8fb84e69c30ec8ddfdf6be710cbfab0a3cd1aa60 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 config NET_VENDOR_CAVIUM
-       tristate "Cavium ethernet drivers"
+       bool "Cavium ethernet drivers"
        depends on PCI
        default y
        ---help---
index b3a5947a2cc03e1675e5895fef39e35b10ea04d0..c561fdcb79a730aeeb890c5a985b05cb873faa45 100644 (file)
@@ -22,7 +22,6 @@
 
 struct nicpf {
        struct pci_dev          *pdev;
-       u8                      rev_id;
        u8                      node;
        unsigned int            flags;
        u8                      num_vf_en;      /* No of VF enabled */
@@ -44,6 +43,7 @@ struct nicpf {
        u8                      duplex[MAX_LMAC];
        u32                     speed[MAX_LMAC];
        u16                     cpi_base[MAX_NUM_VFS_SUPPORTED];
+       u16                     rssi_base[MAX_NUM_VFS_SUPPORTED];
        u16                     rss_ind_tbl_size;
        bool                    mbx_lock[MAX_NUM_VFS_SUPPORTED];
 
@@ -54,6 +54,11 @@ struct nicpf {
        bool                    irq_allocated[NIC_PF_MSIX_VECTORS];
 };
 
+static inline bool pass1_silicon(struct nicpf *nic)
+{
+       return nic->pdev->revision < 8;
+}
+
 /* Supported devices */
 static const struct pci_device_id nic_id_table[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVICE_ID_THUNDER_NIC_PF) },
@@ -117,7 +122,7 @@ static void nic_send_msg_to_vf(struct nicpf *nic, int vf, union nic_mbx *mbx)
         * when PF writes to MBOX(1), in next revisions when
         * PF writes to MBOX(0)
         */
-       if (nic->rev_id == 0) {
+       if (pass1_silicon(nic)) {
                /* see the comment for nic_reg_write()/nic_reg_read()
                 * functions above
                 */
@@ -305,9 +310,6 @@ static void nic_init_hw(struct nicpf *nic)
 {
        int i;
 
-       /* Reset NIC, in case the driver is repeatedly inserted and removed */
-       nic_reg_write(nic, NIC_PF_SOFT_RESET, 1);
-
        /* Enable NIC HW block */
        nic_reg_write(nic, NIC_PF_CFG, 0x3);
 
@@ -395,8 +397,18 @@ static void nic_config_cpi(struct nicpf *nic, struct cpi_cfg_msg *cfg)
                        padd = cpi % 8; /* 3 bits CS out of 6bits DSCP */
 
                /* Leave RSS_SIZE as '0' to disable RSS */
-               nic_reg_write(nic, NIC_PF_CPI_0_2047_CFG | (cpi << 3),
-                             (vnic << 24) | (padd << 16) | (rssi_base + rssi));
+               if (pass1_silicon(nic)) {
+                       nic_reg_write(nic, NIC_PF_CPI_0_2047_CFG | (cpi << 3),
+                                     (vnic << 24) | (padd << 16) |
+                                     (rssi_base + rssi));
+               } else {
+                       /* Set MPI_ALG to '0' to disable MCAM parsing */
+                       nic_reg_write(nic, NIC_PF_CPI_0_2047_CFG | (cpi << 3),
+                                     (padd << 16));
+                       /* MPI index is same as CPI if MPI_ALG is not enabled */
+                       nic_reg_write(nic, NIC_PF_MPI_0_2047_CFG | (cpi << 3),
+                                     (vnic << 24) | (rssi_base + rssi));
+               }
 
                if ((rssi + 1) >= cfg->rq_cnt)
                        continue;
@@ -409,6 +421,7 @@ static void nic_config_cpi(struct nicpf *nic, struct cpi_cfg_msg *cfg)
                        rssi = ((cpi - cpi_base) & 0x38) >> 3;
        }
        nic->cpi_base[cfg->vf_id] = cpi_base;
+       nic->rssi_base[cfg->vf_id] = rssi_base;
 }
 
 /* Responsds to VF with its RSS indirection table size */
@@ -434,10 +447,9 @@ static void nic_config_rss(struct nicpf *nic, struct rss_cfg_msg *cfg)
 {
        u8  qset, idx = 0;
        u64 cpi_cfg, cpi_base, rssi_base, rssi;
+       u64 idx_addr;
 
-       cpi_base = nic->cpi_base[cfg->vf_id];
-       cpi_cfg = nic_reg_read(nic, NIC_PF_CPI_0_2047_CFG | (cpi_base << 3));
-       rssi_base = (cpi_cfg & 0x0FFF) + cfg->tbl_offset;
+       rssi_base = nic->rssi_base[cfg->vf_id] + cfg->tbl_offset;
 
        rssi = rssi_base;
        qset = cfg->vf_id;
@@ -454,9 +466,15 @@ static void nic_config_rss(struct nicpf *nic, struct rss_cfg_msg *cfg)
                idx++;
        }
 
+       cpi_base = nic->cpi_base[cfg->vf_id];
+       if (pass1_silicon(nic))
+               idx_addr = NIC_PF_CPI_0_2047_CFG;
+       else
+               idx_addr = NIC_PF_MPI_0_2047_CFG;
+       cpi_cfg = nic_reg_read(nic, idx_addr | (cpi_base << 3));
        cpi_cfg &= ~(0xFULL << 20);
        cpi_cfg |= (cfg->hash_bits << 20);
-       nic_reg_write(nic, NIC_PF_CPI_0_2047_CFG | (cpi_base << 3), cpi_cfg);
+       nic_reg_write(nic, idx_addr | (cpi_base << 3), cpi_cfg);
 }
 
 /* 4 level transmit side scheduler configutation
@@ -1001,8 +1019,6 @@ static int nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                goto err_release_regions;
        }
 
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &nic->rev_id);
-
        nic->node = nic_get_node_id(pdev);
 
        nic_set_lmac_vf_mapping(nic);
index 58197bb2f80528bf06de0daaa2c406b96d4fc0c4..dd536be20193119c3465cd772a4bff6d649e3319 100644 (file)
 #define   NIC_PF_ECC3_DBE_INT_W1S              (0x2708)
 #define   NIC_PF_ECC3_DBE_ENA_W1C              (0x2710)
 #define   NIC_PF_ECC3_DBE_ENA_W1S              (0x2718)
+#define   NIC_PF_MCAM_0_191_ENA                        (0x100000)
+#define   NIC_PF_MCAM_0_191_M_0_5_DATA         (0x110000)
+#define   NIC_PF_MCAM_CTRL                     (0x120000)
 #define   NIC_PF_CPI_0_2047_CFG                        (0x200000)
+#define   NIC_PF_MPI_0_2047_CFG                        (0x210000)
 #define   NIC_PF_RSSI_0_4097_RQ                        (0x220000)
 #define   NIC_PF_LMAC_0_7_CFG                  (0x240000)
 #define   NIC_PF_LMAC_0_7_SW_XOFF              (0x242000)
index b63e579aeb12d09bbe7f6e3de5badced5b2d44ba..a9377727c11c3fdb18a09f16ce8366ae4ef48057 100644 (file)
@@ -29,7 +29,7 @@
 static const struct pci_device_id nicvf_id_table[] = {
        { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM,
                         PCI_DEVICE_ID_THUNDER_NIC_VF,
-                        PCI_VENDOR_ID_CAVIUM, 0xA11E) },
+                        PCI_VENDOR_ID_CAVIUM, 0xA134) },
        { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM,
                         PCI_DEVICE_ID_THUNDER_PASS1_NIC_VF,
                         PCI_VENDOR_ID_CAVIUM, 0xA11E) },
index 574c49278900943e5584fa9658f7eb6adb2d7452..180aa9fabf4820df042f18cba8c39d5ce1668e9d 100644 (file)
@@ -977,8 +977,10 @@ static int bgx_init_of_phy(struct bgx *bgx)
                SET_NETDEV_DEV(&bgx->lmac[lmac].netdev, &bgx->pdev->dev);
                bgx->lmac[lmac].lmacid = lmac;
                lmac++;
-               if (lmac == MAX_LMAC_PER_BGX)
+               if (lmac == MAX_LMAC_PER_BGX) {
+                       of_node_put(np_child);
                        break;
+               }
        }
        return 0;
 }
index 8353a6cbfcc21edd2dde363fafd06b202611cae4..03ed00c498230d4a0daeeccb3016a863d6445a29 100644 (file)
@@ -157,6 +157,11 @@ CH_PCI_DEVICE_ID_TABLE_DEFINE_BEGIN
        CH_PCI_ID_TABLE_FENTRY(0x5090), /* Custom T540-CR */
        CH_PCI_ID_TABLE_FENTRY(0x5091), /* Custom T522-CR */
        CH_PCI_ID_TABLE_FENTRY(0x5092), /* Custom T520-CR */
+       CH_PCI_ID_TABLE_FENTRY(0x5093), /* Custom T580-LP-CR */
+       CH_PCI_ID_TABLE_FENTRY(0x5094), /* Custom T540-CR */
+       CH_PCI_ID_TABLE_FENTRY(0x5095), /* Custom T540-CR-SO */
+       CH_PCI_ID_TABLE_FENTRY(0x5096), /* Custom T580-CR */
+       CH_PCI_ID_TABLE_FENTRY(0x5097), /* Custom T520-KR */
 
        /* T6 adapters:
         */
index 0a27805cbbbd0e14f2988ffec5f207909628d65b..d463563e1f7039ee5176ca36abfdc6bae3f2ed46 100644 (file)
@@ -582,6 +582,7 @@ struct be_adapter {
        u16 pvid;
        __be16 vxlan_port;
        int vxlan_port_count;
+       int vxlan_port_aliases;
        struct phy_info phy;
        u8 wol_cap;
        bool wol_en;
@@ -591,6 +592,7 @@ struct be_adapter {
        int be_get_temp_freq;
        struct be_hwmon hwmon_info;
        u8 pf_number;
+       u8 pci_func_num;
        struct rss_info rss_info;
        /* Filters for packets that need to be sent to BMC */
        u32 bmc_filt_mask;
index eb323913cd39fb981a8c0cc02140c0c7205ee4f8..1795c935ff023fcf795008a49a9a4cd0fce63d9c 100644 (file)
@@ -851,8 +851,10 @@ static int be_cmd_notify_wait(struct be_adapter *adapter,
                return status;
 
        dest_wrb = be_cmd_copy(adapter, wrb);
-       if (!dest_wrb)
-               return -EBUSY;
+       if (!dest_wrb) {
+               status = -EBUSY;
+               goto unlock;
+       }
 
        if (use_mcc(adapter))
                status = be_mcc_notify_wait(adapter);
@@ -862,6 +864,7 @@ static int be_cmd_notify_wait(struct be_adapter *adapter,
        if (!status)
                memcpy(wrb, dest_wrb, sizeof(*wrb));
 
+unlock:
        be_cmd_unlock(adapter);
        return status;
 }
@@ -1984,6 +1987,8 @@ int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value)
                         be_if_cap_flags(adapter));
        }
        flags &= be_if_cap_flags(adapter);
+       if (!flags)
+               return -ENOTSUPP;
 
        return __be_cmd_rx_filter(adapter, flags, value);
 }
@@ -2887,6 +2892,7 @@ int be_cmd_get_cntl_attributes(struct be_adapter *adapter)
        if (!status) {
                attribs = attribs_cmd.va + sizeof(struct be_cmd_resp_hdr);
                adapter->hba_port_num = attribs->hba_attribs.phy_port;
+               adapter->pci_func_num = attribs->pci_func_num;
                serial_num = attribs->hba_attribs.controller_serial_number;
                for (i = 0; i < CNTL_SERIAL_NUM_WORDS; i++)
                        adapter->serial_num[i] = le32_to_cpu(serial_num[i]) &
@@ -3709,7 +3715,6 @@ int be_cmd_get_func_config(struct be_adapter *adapter, struct be_resources *res)
                        status = -EINVAL;
                        goto err;
                }
-
                adapter->pf_number = desc->pf_num;
                be_copy_nic_desc(res, desc);
        }
@@ -3721,7 +3726,10 @@ err:
        return status;
 }
 
-/* Will use MBOX only if MCCQ has not been created */
+/* Will use MBOX only if MCCQ has not been created
+ * non-zero domain => a PF is querying this on behalf of a VF
+ * zero domain => a PF or a VF is querying this for itself
+ */
 int be_cmd_get_profile_config(struct be_adapter *adapter,
                              struct be_resources *res, u8 query, u8 domain)
 {
@@ -3748,10 +3756,15 @@ int be_cmd_get_profile_config(struct be_adapter *adapter,
                               OPCODE_COMMON_GET_PROFILE_CONFIG,
                               cmd.size, &wrb, &cmd);
 
-       req->hdr.domain = domain;
        if (!lancer_chip(adapter))
                req->hdr.version = 1;
        req->type = ACTIVE_PROFILE_TYPE;
+       /* When a function is querying profile information relating to
+        * itself hdr.pf_number must be set to it's pci_func_num + 1
+        */
+       req->hdr.domain = domain;
+       if (domain == 0)
+               req->hdr.pf_num = adapter->pci_func_num + 1;
 
        /* When QUERY_MODIFIABLE_FIELDS_TYPE bit is set, cmd returns the
         * descriptors with all bits set to "1" for the fields which can be
@@ -3921,12 +3934,16 @@ static void be_fill_vf_res_template(struct be_adapter *adapter,
                        vf_if_cap_flags &= ~(BE_IF_FLAGS_RSS |
                                             BE_IF_FLAGS_DEFQ_RSS);
                }
-
-               nic_vft->cap_flags = cpu_to_le32(vf_if_cap_flags);
        } else {
                num_vf_qs = 1;
        }
 
+       if (res_mod.vf_if_cap_flags & BE_IF_FLAGS_VLAN_PROMISCUOUS) {
+               nic_vft->flags |= BIT(IF_CAPS_FLAGS_VALID_SHIFT);
+               vf_if_cap_flags &= ~BE_IF_FLAGS_VLAN_PROMISCUOUS;
+       }
+
+       nic_vft->cap_flags = cpu_to_le32(vf_if_cap_flags);
        nic_vft->rq_count = cpu_to_le16(num_vf_qs);
        nic_vft->txq_count = cpu_to_le16(num_vf_qs);
        nic_vft->rssq_count = cpu_to_le16(num_vf_qs);
index 7d178bdb112eb7d14d5a62d74ea21ecaa30ba0e9..91155ea74f342e2663f18848c9fe5546635e7c05 100644 (file)
@@ -289,7 +289,9 @@ struct be_cmd_req_hdr {
        u32 timeout;            /* dword 1 */
        u32 request_length;     /* dword 2 */
        u8 version;             /* dword 3 */
-       u8 rsvd[3];             /* dword 3 */
+       u8 rsvd1;               /* dword 3 */
+       u8 pf_num;              /* dword 3 */
+       u8 rsvd2;               /* dword 3 */
 };
 
 #define RESP_HDR_INFO_OPCODE_SHIFT     0       /* bits 0 - 7 */
@@ -1652,7 +1654,11 @@ struct mgmt_hba_attribs {
 
 struct mgmt_controller_attrib {
        struct mgmt_hba_attribs hba_attribs;
-       u32 rsvd0[10];
+       u32 rsvd0[2];
+       u16 rsvd1;
+       u8 pci_func_num;
+       u8 rsvd2;
+       u32 rsvd3[7];
 } __packed;
 
 struct be_cmd_req_cntl_attribs {
index 12687bf52b9518eaa1c4bb538ff26fcc88ce7acc..eb48a977f8daabe78d6d5b6a94f6607bf19287b8 100644 (file)
@@ -1123,11 +1123,12 @@ static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter,
                                           struct sk_buff *skb,
                                           struct be_wrb_params *wrb_params)
 {
-       /* Lancer, SH-R ASICs have a bug wherein Packets that are 32 bytes or
-        * less may cause a transmit stall on that port. So the work-around is
-        * to pad short packets (<= 32 bytes) to a 36-byte length.
+       /* Lancer, SH and BE3 in SRIOV mode have a bug wherein
+        * packets that are 32b or less may cause a transmit stall
+        * on that port. The workaround is to pad such packets
+        * (len <= 32 bytes) to a minimum length of 36b.
         */
-       if (unlikely(!BEx_chip(adapter) && skb->len <= 32)) {
+       if (skb->len <= 32) {
                if (skb_put_padto(skb, 36))
                        return NULL;
        }
@@ -4205,10 +4206,6 @@ static int be_get_config(struct be_adapter *adapter)
        int status, level;
        u16 profile_id;
 
-       status = be_cmd_get_cntl_attributes(adapter);
-       if (status)
-               return status;
-
        status = be_cmd_query_fw_cfg(adapter);
        if (status)
                return status;
@@ -4407,6 +4404,11 @@ static int be_setup(struct be_adapter *adapter)
        if (!lancer_chip(adapter))
                be_cmd_req_native_mode(adapter);
 
+       /* Need to invoke this cmd first to get the PCI Function Number */
+       status = be_cmd_get_cntl_attributes(adapter);
+       if (status)
+               return status;
+
        if (!BE2_chip(adapter) && be_physfn(adapter))
                be_alloc_sriov_res(adapter);
 
@@ -4999,7 +5001,15 @@ static bool be_check_ufi_compatibility(struct be_adapter *adapter,
                return false;
        }
 
-       return (fhdr->asic_type_rev >= adapter->asic_rev);
+       /* In BE3 FW images the "asic_type_rev" field doesn't track the
+        * asic_rev of the chips it is compatible with.
+        * When asic_type_rev is 0 the image is compatible only with
+        * pre-BE3-R chips (asic_rev < 0x10)
+        */
+       if (BEx_chip(adapter) && fhdr->asic_type_rev == 0)
+               return adapter->asic_rev < 0x10;
+       else
+               return (fhdr->asic_type_rev >= adapter->asic_rev);
 }
 
 static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw)
@@ -5176,6 +5186,11 @@ static void be_add_vxlan_port(struct net_device *netdev, sa_family_t sa_family,
        if (lancer_chip(adapter) || BEx_chip(adapter) || be_is_mc(adapter))
                return;
 
+       if (adapter->vxlan_port == port && adapter->vxlan_port_count) {
+               adapter->vxlan_port_aliases++;
+               return;
+       }
+
        if (adapter->flags & BE_FLAGS_VXLAN_OFFLOADS) {
                dev_info(dev,
                         "Only one UDP port supported for VxLAN offloads\n");
@@ -5226,6 +5241,11 @@ static void be_del_vxlan_port(struct net_device *netdev, sa_family_t sa_family,
        if (adapter->vxlan_port != port)
                goto done;
 
+       if (adapter->vxlan_port_aliases) {
+               adapter->vxlan_port_aliases--;
+               return;
+       }
+
        be_disable_vxlan_offloads(adapter);
 
        dev_info(&adapter->pdev->dev,
index 3c40f6b9922436a32d255aa627e9d94db45f8477..55c36230e17634c3e063bdb20f4bb6a896bce4a6 100644 (file)
@@ -198,17 +198,28 @@ static int fsl_pq_mdio_reset(struct mii_bus *bus)
 
 #if defined(CONFIG_GIANFAR) || defined(CONFIG_GIANFAR_MODULE)
 /*
+ * Return the TBIPA address, starting from the address
+ * of the mapped GFAR MDIO registers (struct gfar)
  * This is mildly evil, but so is our hardware for doing this.
  * Also, we have to cast back to struct gfar because of
  * definition weirdness done in gianfar.h.
  */
-static uint32_t __iomem *get_gfar_tbipa(void __iomem *p)
+static uint32_t __iomem *get_gfar_tbipa_from_mdio(void __iomem *p)
 {
        struct gfar __iomem *enet_regs = p;
 
        return &enet_regs->tbipa;
 }
 
+/*
+ * Return the TBIPA address, starting from the address
+ * of the mapped GFAR MII registers (gfar_mii_regs[] within struct gfar)
+ */
+static uint32_t __iomem *get_gfar_tbipa_from_mii(void __iomem *p)
+{
+       return get_gfar_tbipa_from_mdio(container_of(p, struct gfar, gfar_mii_regs));
+}
+
 /*
  * Return the TBIPAR address for an eTSEC2 node
  */
@@ -220,11 +231,12 @@ static uint32_t __iomem *get_etsec_tbipa(void __iomem *p)
 
 #if defined(CONFIG_UCC_GETH) || defined(CONFIG_UCC_GETH_MODULE)
 /*
- * Return the TBIPAR address for a QE MDIO node
+ * Return the TBIPAR address for a QE MDIO node, starting from the address
+ * of the mapped MII registers (struct fsl_pq_mii)
  */
 static uint32_t __iomem *get_ucc_tbipa(void __iomem *p)
 {
-       struct fsl_pq_mdio __iomem *mdio = p;
+       struct fsl_pq_mdio __iomem *mdio = container_of(p, struct fsl_pq_mdio, mii);
 
        return &mdio->utbipar;
 }
@@ -300,14 +312,14 @@ static const struct of_device_id fsl_pq_mdio_match[] = {
                .compatible = "fsl,gianfar-tbi",
                .data = &(struct fsl_pq_mdio_data) {
                        .mii_offset = 0,
-                       .get_tbipa = get_gfar_tbipa,
+                       .get_tbipa = get_gfar_tbipa_from_mii,
                },
        },
        {
                .compatible = "fsl,gianfar-mdio",
                .data = &(struct fsl_pq_mdio_data) {
                        .mii_offset = 0,
-                       .get_tbipa = get_gfar_tbipa,
+                       .get_tbipa = get_gfar_tbipa_from_mii,
                },
        },
        {
@@ -315,7 +327,7 @@ static const struct of_device_id fsl_pq_mdio_match[] = {
                .compatible = "gianfar",
                .data = &(struct fsl_pq_mdio_data) {
                        .mii_offset = offsetof(struct fsl_pq_mdio, mii),
-                       .get_tbipa = get_gfar_tbipa,
+                       .get_tbipa = get_gfar_tbipa_from_mdio,
                },
        },
        {
@@ -445,6 +457,16 @@ static int fsl_pq_mdio_probe(struct platform_device *pdev)
 
                        tbipa = data->get_tbipa(priv->map);
 
+                       /*
+                        * Add consistency check to make sure TBI is contained
+                        * within the mapped range (not because we would get a
+                        * segfault, rather to catch bugs in computing TBI
+                        * address). Print error message but continue anyway.
+                        */
+                       if ((void *)tbipa > priv->map + resource_size(&res) - 4)
+                               dev_err(&pdev->dev, "invalid register map (should be at least 0x%04x to contain TBI address)\n",
+                                       ((void *)tbipa - priv->map) + 4);
+
                        iowrite32be(be32_to_cpup(prop), tbipa);
                }
        }
index 4b69d061d90f7983fb0ee4929b7f6074922d3690..ce38d266f931c506503b37749823eb388f1dd380 100644 (file)
@@ -341,7 +341,7 @@ static void gfar_rx_offload_en(struct gfar_private *priv)
        if (priv->ndev->features & (NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_RX))
                priv->uses_rxfcb = 1;
 
-       if (priv->hwts_rx_en)
+       if (priv->hwts_rx_en || priv->rx_filer_enable)
                priv->uses_rxfcb = 1;
 }
 
@@ -351,7 +351,7 @@ static void gfar_mac_rx_config(struct gfar_private *priv)
        u32 rctrl = 0;
 
        if (priv->rx_filer_enable) {
-               rctrl |= RCTRL_FILREN;
+               rctrl |= RCTRL_FILREN | RCTRL_PRSDEP_INIT;
                /* Program the RIR0 reg with the required distribution */
                if (priv->poll_mode == GFAR_SQ_POLLING)
                        gfar_write(&regs->rir0, DEFAULT_2RXQ_RIR0);
@@ -1710,8 +1710,10 @@ static void gfar_configure_serdes(struct net_device *dev)
         * everything for us?  Resetting it takes the link down and requires
         * several seconds for it to come back.
         */
-       if (phy_read(tbiphy, MII_BMSR) & BMSR_LSTATUS)
+       if (phy_read(tbiphy, MII_BMSR) & BMSR_LSTATUS) {
+               put_device(&tbiphy->dev);
                return;
+       }
 
        /* Single clk mode, mii mode off(for serdes communication) */
        phy_write(tbiphy, MII_TBICON, TBICON_CLK_SELECT);
@@ -1723,6 +1725,8 @@ static void gfar_configure_serdes(struct net_device *dev)
        phy_write(tbiphy, MII_BMCR,
                  BMCR_ANENABLE | BMCR_ANRESTART | BMCR_FULLDPLX |
                  BMCR_SPEED1000);
+
+       put_device(&tbiphy->dev);
 }
 
 static int __gfar_is_rx_idle(struct gfar_private *priv)
@@ -1970,8 +1974,7 @@ static int register_grp_irqs(struct gfar_priv_grp *grp)
                /* Install our interrupt handlers for Error,
                 * Transmit, and Receive
                 */
-               err = request_irq(gfar_irq(grp, ER)->irq, gfar_error,
-                                 IRQF_NO_SUSPEND,
+               err = request_irq(gfar_irq(grp, ER)->irq, gfar_error, 0,
                                  gfar_irq(grp, ER)->name, grp);
                if (err < 0) {
                        netif_err(priv, intr, dev, "Can't get IRQ %d\n",
@@ -1979,6 +1982,8 @@ static int register_grp_irqs(struct gfar_priv_grp *grp)
 
                        goto err_irq_fail;
                }
+               enable_irq_wake(gfar_irq(grp, ER)->irq);
+
                err = request_irq(gfar_irq(grp, TX)->irq, gfar_transmit, 0,
                                  gfar_irq(grp, TX)->name, grp);
                if (err < 0) {
@@ -1994,14 +1999,14 @@ static int register_grp_irqs(struct gfar_priv_grp *grp)
                        goto rx_irq_fail;
                }
        } else {
-               err = request_irq(gfar_irq(grp, TX)->irq, gfar_interrupt,
-                                 IRQF_NO_SUSPEND,
+               err = request_irq(gfar_irq(grp, TX)->irq, gfar_interrupt, 0,
                                  gfar_irq(grp, TX)->name, grp);
                if (err < 0) {
                        netif_err(priv, intr, dev, "Can't get IRQ %d\n",
                                  gfar_irq(grp, TX)->irq);
                        goto err_irq_fail;
                }
+               enable_irq_wake(gfar_irq(grp, TX)->irq);
        }
 
        return 0;
@@ -3457,11 +3462,9 @@ static irqreturn_t gfar_error(int irq, void *grp_id)
                netif_dbg(priv, tx_err, dev, "Transmit Error\n");
        }
        if (events & IEVENT_BSY) {
-               dev->stats.rx_errors++;
+               dev->stats.rx_over_errors++;
                atomic64_inc(&priv->extra_stats.rx_bsy);
 
-               gfar_receive(irq, grp_id);
-
                netif_dbg(priv, rx_err, dev, "busy error (rstat: %x)\n",
                          gfar_read(&regs->rstat));
        }
index 6bdc89179b72d6487d031ecda8551453b9268cd4..a33e4a8296015d10906b4b0d02d72e6f5b048277 100644 (file)
@@ -676,14 +676,14 @@ static void ethflow_to_filer_rules (struct gfar_private *priv, u64 ethflow)
        u32 fcr = 0x0, fpr = FPR_FILER_MASK;
 
        if (ethflow & RXH_L2DA) {
-               fcr = RQFCR_PID_DAH |RQFCR_CMP_NOMATCH |
+               fcr = RQFCR_PID_DAH | RQFCR_CMP_NOMATCH |
                      RQFCR_HASH | RQFCR_AND | RQFCR_HASHTBL_0;
                priv->ftp_rqfpr[priv->cur_filer_idx] = fpr;
                priv->ftp_rqfcr[priv->cur_filer_idx] = fcr;
                gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr);
                priv->cur_filer_idx = priv->cur_filer_idx - 1;
 
-               fcr = RQFCR_PID_DAL | RQFCR_AND | RQFCR_CMP_NOMATCH |
+               fcr = RQFCR_PID_DAL | RQFCR_CMP_NOMATCH |
                      RQFCR_HASH | RQFCR_AND | RQFCR_HASHTBL_0;
                priv->ftp_rqfpr[priv->cur_filer_idx] = fpr;
                priv->ftp_rqfcr[priv->cur_filer_idx] = fcr;
index 8e3cd77aa347a4136d10e25a934ecc335b0b9301..664d0c261269097bccae55c12dcd7abcab140d5b 100644 (file)
@@ -557,6 +557,7 @@ static const struct of_device_id match_table[] = {
        { .compatible = "fsl,etsec-ptp" },
        {},
 };
+MODULE_DEVICE_TABLE(of, match_table);
 
 static struct platform_driver gianfar_ptp_driver = {
        .driver = {
index 4dd40e057f40035ff6b8a1e236ab80c8ddc5497b..650f7888e32be90f805d10b44e9f8c913c357376 100644 (file)
@@ -1384,6 +1384,8 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth)
                value = phy_read(tbiphy, ENET_TBI_MII_CR);
                value &= ~0x1000;       /* Turn off autonegotiation */
                phy_write(tbiphy, ENET_TBI_MII_CR, value);
+
+               put_device(&tbiphy->dev);
        }
 
        init_check_frame_length_mode(ug_info->lengthCheckRx, &ug_regs->maccfg2);
@@ -1702,8 +1704,10 @@ static void uec_configure_serdes(struct net_device *dev)
         * everything for us?  Resetting it takes the link down and requires
         * several seconds for it to come back.
         */
-       if (phy_read(tbiphy, ENET_TBI_MII_SR) & TBISR_LSTATUS)
+       if (phy_read(tbiphy, ENET_TBI_MII_SR) & TBISR_LSTATUS) {
+               put_device(&tbiphy->dev);
                return;
+       }
 
        /* Single clk mode, mii mode off(for serdes communication) */
        phy_write(tbiphy, ENET_TBI_MII_ANA, TBIANA_SETTINGS);
@@ -1711,6 +1715,8 @@ static void uec_configure_serdes(struct net_device *dev)
        phy_write(tbiphy, ENET_TBI_MII_TBICON, TBICON_CLK_SELECT);
 
        phy_write(tbiphy, ENET_TBI_MII_CR, TBICR_SETTINGS);
+
+       put_device(&tbiphy->dev);
 }
 
 /* Configure the PHY for dev.
index cc2d8b4b18e3e2a99ef303b76809545496089787..253f8ed0537a058778fd08b2c5a0747f53d7eca4 100644 (file)
@@ -816,7 +816,7 @@ static int hip04_mac_probe(struct platform_device *pdev)
        struct net_device *ndev;
        struct hip04_priv *priv;
        struct resource *res;
-       unsigned int irq;
+       int irq;
        int ret;
 
        ndev = alloc_etherdev(sizeof(struct hip04_priv));
index 28df37420da963d5d8f3b3234e4f584442537121..ac02c675c59c4167b4870c892c6afcceb13aec4c 100644 (file)
@@ -460,8 +460,8 @@ struct emac_ethtool_regs_subhdr {
        u32 index;
 };
 
-#define EMAC_ETHTOOL_REGS_VER          0
-#define EMAC4_ETHTOOL_REGS_VER         1
-#define EMAC4SYNC_ETHTOOL_REGS_VER     2
+#define EMAC_ETHTOOL_REGS_VER          3
+#define EMAC4_ETHTOOL_REGS_VER         4
+#define EMAC4SYNC_ETHTOOL_REGS_VER     5
 
 #endif /* __IBM_NEWEMAC_CORE_H */
index 3e0d20037675e84164ae9da793ddc080737e1d81..c0e943aecd1394262757e790b04a6ce1eccda72a 100644 (file)
@@ -386,7 +386,6 @@ static i40e_status i40e_init_asq(struct i40e_hw *hw)
 
        hw->aq.asq.next_to_use = 0;
        hw->aq.asq.next_to_clean = 0;
-       hw->aq.asq.count = hw->aq.num_asq_entries;
 
        /* allocate the ring memory */
        ret_code = i40e_alloc_adminq_asq_ring(hw);
@@ -404,6 +403,7 @@ static i40e_status i40e_init_asq(struct i40e_hw *hw)
                goto init_adminq_free_rings;
 
        /* success! */
+       hw->aq.asq.count = hw->aq.num_asq_entries;
        goto init_adminq_exit;
 
 init_adminq_free_rings:
@@ -445,7 +445,6 @@ static i40e_status i40e_init_arq(struct i40e_hw *hw)
 
        hw->aq.arq.next_to_use = 0;
        hw->aq.arq.next_to_clean = 0;
-       hw->aq.arq.count = hw->aq.num_arq_entries;
 
        /* allocate the ring memory */
        ret_code = i40e_alloc_adminq_arq_ring(hw);
@@ -463,6 +462,7 @@ static i40e_status i40e_init_arq(struct i40e_hw *hw)
                goto init_adminq_free_rings;
 
        /* success! */
+       hw->aq.arq.count = hw->aq.num_arq_entries;
        goto init_adminq_exit;
 
 init_adminq_free_rings:
@@ -946,6 +946,13 @@ i40e_status i40e_clean_arq_element(struct i40e_hw *hw,
        /* take the lock before we start messing with the ring */
        mutex_lock(&hw->aq.arq_mutex);
 
+       if (hw->aq.arq.count == 0) {
+               i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
+                          "AQRX: Admin queue not initialized.\n");
+               ret_code = I40E_ERR_QUEUE_EMPTY;
+               goto clean_arq_element_err;
+       }
+
        /* set next_to_use to head */
        ntu = (rd32(hw, hw->aq.arq.head) & I40E_PF_ARQH_ARQH_MASK);
        if (ntu == ntc) {
@@ -1007,6 +1014,8 @@ clean_arq_element_out:
        /* Set pending if needed, unlock and return */
        if (pending != NULL)
                *pending = (ntc > ntu ? hw->aq.arq.count : 0) + (ntu - ntc);
+
+clean_arq_element_err:
        mutex_unlock(&hw->aq.arq_mutex);
 
        if (i40e_is_nvm_update_op(&e->desc)) {
index e972b5ecbf0b6e1bfb2f11ca93a3f13a18438715..13a5d4cf494bc76e98fd500afe856951703bf244 100644 (file)
@@ -1344,6 +1344,12 @@ static void i40e_get_ethtool_stats(struct net_device *netdev,
                        data[i++] = (i40e_gstrings_veb_stats[j].sizeof_stat ==
                                     sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
                }
+               for (j = 0; j < I40E_MAX_TRAFFIC_CLASS; j++) {
+                       data[i++] = veb->tc_stats.tc_tx_packets[j];
+                       data[i++] = veb->tc_stats.tc_tx_bytes[j];
+                       data[i++] = veb->tc_stats.tc_rx_packets[j];
+                       data[i++] = veb->tc_stats.tc_rx_bytes[j];
+               }
        }
        for (j = 0; j < I40E_GLOBAL_STATS_LEN; j++) {
                p = (char *)pf + i40e_gstrings_stats[j].stat_offset;
index 851c1a159be8a1566d8a792c52bf4e83ea6877d7..3dd26cdd0bf27365ec60d084c027800bee128f93 100644 (file)
@@ -2672,7 +2672,8 @@ static int i40e_configure_rx_ring(struct i40e_ring *ring)
                rx_ctx.lrxqthresh = 2;
        rx_ctx.crcstrip = 1;
        rx_ctx.l2tsel = 1;
-       rx_ctx.showiv = 1;
+       /* this controls whether VLAN is stripped from inner headers */
+       rx_ctx.showiv = 0;
 #ifdef I40E_FCOE
        rx_ctx.fc_ena = (vsi->type == I40E_VSI_FCOE);
 #endif
@@ -7910,6 +7911,7 @@ static int i40e_sw_init(struct i40e_pf *pf)
        if (pf->hw.func_caps.vmdq) {
                pf->num_vmdq_vsis = I40E_DEFAULT_NUM_VMDQ_VSI;
                pf->flags |= I40E_FLAG_VMDQ_ENABLED;
+               pf->num_vmdq_qps = i40e_default_queues_per_vmdq(pf);
        }
 
 #ifdef I40E_FCOE
@@ -8388,6 +8390,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
 
        netdev->hw_enc_features |= NETIF_F_IP_CSUM       |
                                  NETIF_F_GSO_UDP_TUNNEL |
+                                 NETIF_F_GSO_GRE        |
                                  NETIF_F_TSO;
 
        netdev->features = NETIF_F_SG                  |
@@ -8395,6 +8398,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
                           NETIF_F_SCTP_CSUM           |
                           NETIF_F_HIGHDMA             |
                           NETIF_F_GSO_UDP_TUNNEL      |
+                          NETIF_F_GSO_GRE             |
                           NETIF_F_HW_VLAN_CTAG_TX     |
                           NETIF_F_HW_VLAN_CTAG_RX     |
                           NETIF_F_HW_VLAN_CTAG_FILTER |
index f08450b907745afefcdd6da766f7a32ae3aa57c2..a23ebfd5cd254014cd0632979aa441a2a6f6eadf 100644 (file)
@@ -373,7 +373,6 @@ static i40e_status i40e_init_asq(struct i40e_hw *hw)
 
        hw->aq.asq.next_to_use = 0;
        hw->aq.asq.next_to_clean = 0;
-       hw->aq.asq.count = hw->aq.num_asq_entries;
 
        /* allocate the ring memory */
        ret_code = i40e_alloc_adminq_asq_ring(hw);
@@ -391,6 +390,7 @@ static i40e_status i40e_init_asq(struct i40e_hw *hw)
                goto init_adminq_free_rings;
 
        /* success! */
+       hw->aq.asq.count = hw->aq.num_asq_entries;
        goto init_adminq_exit;
 
 init_adminq_free_rings:
@@ -432,7 +432,6 @@ static i40e_status i40e_init_arq(struct i40e_hw *hw)
 
        hw->aq.arq.next_to_use = 0;
        hw->aq.arq.next_to_clean = 0;
-       hw->aq.arq.count = hw->aq.num_arq_entries;
 
        /* allocate the ring memory */
        ret_code = i40e_alloc_adminq_arq_ring(hw);
@@ -450,6 +449,7 @@ static i40e_status i40e_init_arq(struct i40e_hw *hw)
                goto init_adminq_free_rings;
 
        /* success! */
+       hw->aq.arq.count = hw->aq.num_arq_entries;
        goto init_adminq_exit;
 
 init_adminq_free_rings:
@@ -887,6 +887,13 @@ i40e_status i40evf_clean_arq_element(struct i40e_hw *hw,
        /* take the lock before we start messing with the ring */
        mutex_lock(&hw->aq.arq_mutex);
 
+       if (hw->aq.arq.count == 0) {
+               i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
+                          "AQRX: Admin queue not initialized.\n");
+               ret_code = I40E_ERR_QUEUE_EMPTY;
+               goto clean_arq_element_err;
+       }
+
        /* set next_to_use to head */
        ntu = (rd32(hw, hw->aq.arq.head) & I40E_VF_ARQH1_ARQH_MASK);
        if (ntu == ntc) {
@@ -948,6 +955,8 @@ clean_arq_element_out:
        /* Set pending if needed, unlock and return */
        if (pending != NULL)
                *pending = (ntc > ntu ? hw->aq.arq.count : 0) + (ntu - ntc);
+
+clean_arq_element_err:
        mutex_unlock(&hw->aq.arq_mutex);
 
        return ret_code;
index 960169efe636a659241f7e8fae10706fd0503939..dfb6d5f79a1002a0101e4ae7fe2d7bf466f49c6f 100644 (file)
@@ -759,11 +759,23 @@ txq_put_data_tso(struct net_device *dev, struct tx_queue *txq,
 
        desc->l4i_chk = 0;
        desc->byte_cnt = length;
-       desc->buf_ptr = dma_map_single(dev->dev.parent, data,
-                                      length, DMA_TO_DEVICE);
-       if (unlikely(dma_mapping_error(dev->dev.parent, desc->buf_ptr))) {
-               WARN(1, "dma_map_single failed!\n");
-               return -ENOMEM;
+
+       if (length <= 8 && (uintptr_t)data & 0x7) {
+               /* Copy unaligned small data fragment to TSO header data area */
+               memcpy(txq->tso_hdrs + txq->tx_curr_desc * TSO_HEADER_SIZE,
+                      data, length);
+               desc->buf_ptr = txq->tso_hdrs_dma
+                       + txq->tx_curr_desc * TSO_HEADER_SIZE;
+       } else {
+               /* Alignment is okay, map buffer and hand off to hardware */
+               txq->tx_desc_mapping[tx_index] = DESC_DMA_MAP_SINGLE;
+               desc->buf_ptr = dma_map_single(dev->dev.parent, data,
+                       length, DMA_TO_DEVICE);
+               if (unlikely(dma_mapping_error(dev->dev.parent,
+                                              desc->buf_ptr))) {
+                       WARN(1, "dma_map_single failed!\n");
+                       return -ENOMEM;
+               }
        }
 
        cmd_sts = BUFFER_OWNED_BY_DMA;
@@ -779,7 +791,8 @@ txq_put_data_tso(struct net_device *dev, struct tx_queue *txq,
 }
 
 static inline void
-txq_put_hdr_tso(struct sk_buff *skb, struct tx_queue *txq, int length)
+txq_put_hdr_tso(struct sk_buff *skb, struct tx_queue *txq, int length,
+               u32 *first_cmd_sts, bool first_desc)
 {
        struct mv643xx_eth_private *mp = txq_to_mp(txq);
        int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
@@ -788,6 +801,7 @@ txq_put_hdr_tso(struct sk_buff *skb, struct tx_queue *txq, int length)
        int ret;
        u32 cmd_csum = 0;
        u16 l4i_chk = 0;
+       u32 cmd_sts;
 
        tx_index = txq->tx_curr_desc;
        desc = &txq->tx_desc_area[tx_index];
@@ -803,9 +817,17 @@ txq_put_hdr_tso(struct sk_buff *skb, struct tx_queue *txq, int length)
        desc->byte_cnt = hdr_len;
        desc->buf_ptr = txq->tso_hdrs_dma +
                        txq->tx_curr_desc * TSO_HEADER_SIZE;
-       desc->cmd_sts = cmd_csum | BUFFER_OWNED_BY_DMA  | TX_FIRST_DESC |
+       cmd_sts = cmd_csum | BUFFER_OWNED_BY_DMA  | TX_FIRST_DESC |
                                   GEN_CRC;
 
+       /* Defer updating the first command descriptor until all
+        * following descriptors have been written.
+        */
+       if (first_desc)
+               *first_cmd_sts = cmd_sts;
+       else
+               desc->cmd_sts = cmd_sts;
+
        txq->tx_curr_desc++;
        if (txq->tx_curr_desc == txq->tx_ring_size)
                txq->tx_curr_desc = 0;
@@ -819,6 +841,8 @@ static int txq_submit_tso(struct tx_queue *txq, struct sk_buff *skb,
        int desc_count = 0;
        struct tso_t tso;
        int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
+       struct tx_desc *first_tx_desc;
+       u32 first_cmd_sts = 0;
 
        /* Count needed descriptors */
        if ((txq->tx_desc_count + tso_count_descs(skb)) >= txq->tx_ring_size) {
@@ -826,11 +850,14 @@ static int txq_submit_tso(struct tx_queue *txq, struct sk_buff *skb,
                return -EBUSY;
        }
 
+       first_tx_desc = &txq->tx_desc_area[txq->tx_curr_desc];
+
        /* Initialize the TSO handler, and prepare the first payload */
        tso_start(skb, &tso);
 
        total_len = skb->len - hdr_len;
        while (total_len > 0) {
+               bool first_desc = (desc_count == 0);
                char *hdr;
 
                data_left = min_t(int, skb_shinfo(skb)->gso_size, total_len);
@@ -840,7 +867,8 @@ static int txq_submit_tso(struct tx_queue *txq, struct sk_buff *skb,
                /* prepare packet headers: MAC + IP + TCP */
                hdr = txq->tso_hdrs + txq->tx_curr_desc * TSO_HEADER_SIZE;
                tso_build_hdr(skb, hdr, &tso, data_left, total_len == 0);
-               txq_put_hdr_tso(skb, txq, data_left);
+               txq_put_hdr_tso(skb, txq, data_left, &first_cmd_sts,
+                               first_desc);
 
                while (data_left > 0) {
                        int size;
@@ -860,6 +888,10 @@ static int txq_submit_tso(struct tx_queue *txq, struct sk_buff *skb,
        __skb_queue_tail(&txq->tx_skb, skb);
        skb_tx_timestamp(skb);
 
+       /* ensure all other descriptors are written before first cmd_sts */
+       wmb();
+       first_tx_desc->cmd_sts = first_cmd_sts;
+
        /* clear TX_END status */
        mp->work_tx_end &= ~(1 << txq->index);
 
@@ -2785,8 +2817,10 @@ static int mv643xx_eth_shared_of_probe(struct platform_device *pdev)
 
        for_each_available_child_of_node(np, pnp) {
                ret = mv643xx_eth_shared_of_add_port(pdev, pnp);
-               if (ret)
+               if (ret) {
+                       of_node_put(pnp);
                        return ret;
+               }
        }
        return 0;
 }
index fe2299ac4f5c0e43b1ff3cf124381df3a1daecf1..514df76fc70f36430a2d646fbee30997e6767210 100644 (file)
@@ -1479,6 +1479,7 @@ static int mvneta_rx(struct mvneta_port *pp, int rx_todo,
                struct mvneta_rx_desc *rx_desc = mvneta_rxq_next_desc_get(rxq);
                struct sk_buff *skb;
                unsigned char *data;
+               dma_addr_t phys_addr;
                u32 rx_status;
                int rx_bytes, err;
 
@@ -1486,6 +1487,7 @@ static int mvneta_rx(struct mvneta_port *pp, int rx_todo,
                rx_status = rx_desc->status;
                rx_bytes = rx_desc->data_size - (ETH_FCS_LEN + MVNETA_MH_SIZE);
                data = (unsigned char *)rx_desc->buf_cookie;
+               phys_addr = rx_desc->buf_phys_addr;
 
                if (!mvneta_rxq_desc_is_first_last(rx_status) ||
                    (rx_status & MVNETA_RXD_ERR_SUMMARY)) {
@@ -1534,7 +1536,7 @@ static int mvneta_rx(struct mvneta_port *pp, int rx_todo,
                if (!skb)
                        goto err_drop_frame;
 
-               dma_unmap_single(dev->dev.parent, rx_desc->buf_phys_addr,
+               dma_unmap_single(dev->dev.parent, phys_addr,
                                 MVNETA_RX_BUF_SIZE(pp->pkt_size), DMA_FROM_DEVICE);
 
                rcvd_pkts++;
@@ -3173,6 +3175,8 @@ static int mvneta_probe(struct platform_device *pdev)
                struct phy_device *phy = of_phy_find_device(dn);
 
                mvneta_fixed_link_update(pp, phy);
+
+               put_device(&phy->dev);
        }
 
        return 0;
index 0a3202047569c707a28f62376466e72fdcd8cd00..2177e56ed0be7d18ee40d2428b69003bd6f8cca5 100644 (file)
@@ -2398,7 +2398,7 @@ int mlx4_multi_func_init(struct mlx4_dev *dev)
                        }
                }
 
-               memset(&priv->mfunc.master.cmd_eqe, 0, dev->caps.eqe_size);
+               memset(&priv->mfunc.master.cmd_eqe, 0, sizeof(struct mlx4_eqe));
                priv->mfunc.master.cmd_eqe.type = MLX4_EVENT_TYPE_CMD;
                INIT_WORK(&priv->mfunc.master.comm_work,
                          mlx4_master_comm_channel);
index 4402a1e48c9bb9d8153df9e9f9378d5e4ece38b3..e7a5000aa12cd4c49f9dae9283664df921491455 100644 (file)
@@ -1047,13 +1047,15 @@ int mlx4_en_poll_rx_cq(struct napi_struct *napi, int budget)
 
        /* If we used up all the quota - we're probably not done yet... */
        if (done == budget) {
-               int cpu_curr;
                const struct cpumask *aff;
+               struct irq_data *idata;
+               int cpu_curr;
 
                INC_PERF_COUNTER(priv->pstats.napi_quota);
 
                cpu_curr = smp_processor_id();
-               aff = irq_desc_get_irq_data(cq->irq_desc)->affinity;
+               idata = irq_desc_get_irq_data(cq->irq_desc);
+               aff = irq_data_get_affinity_mask(idata);
 
                if (likely(cpumask_test_cpu(cpu_curr, aff)))
                        return budget;
@@ -1268,8 +1270,6 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
                rss_context->hash_fn = MLX4_RSS_HASH_TOP;
                memcpy(rss_context->rss_key, priv->rss_key,
                       MLX4_EN_RSS_KEY_SIZE);
-               netdev_rss_key_fill(rss_context->rss_key,
-                                   MLX4_EN_RSS_KEY_SIZE);
        } else {
                en_err(priv, "Unknown RSS hash function requested\n");
                err = -EINVAL;
index 494e7762fdb19efb83d76f187b88fd37d422d5b5..4421bf5463f67159618c3a4c572b4e9ebc04dd7b 100644 (file)
@@ -964,6 +964,8 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
                        tx_desc->ctrl.ins_vlan = MLX4_WQE_CTRL_INS_SVLAN;
                else if (vlan_proto == ETH_P_8021Q)
                        tx_desc->ctrl.ins_vlan = MLX4_WQE_CTRL_INS_CVLAN;
+               else
+                       tx_desc->ctrl.ins_vlan = 0;
 
                tx_desc->ctrl.fence_size = real_size;
 
index 8e81e53c370e7d54e6367c012212cccc73ee26fd..603d1c3d3b2ea1a8a98de110f1e777f1d751e649 100644 (file)
@@ -196,7 +196,7 @@ static void slave_event(struct mlx4_dev *dev, u8 slave, struct mlx4_eqe *eqe)
                return;
        }
 
-       memcpy(s_eqe, eqe, dev->caps.eqe_size - 1);
+       memcpy(s_eqe, eqe, sizeof(struct mlx4_eqe) - 1);
        s_eqe->slave_id = slave;
        /* ensure all information is written before setting the ownersip bit */
        dma_wmb();
@@ -1364,6 +1364,10 @@ int mlx4_test_interrupts(struct mlx4_dev *dev)
         * and performing a NOP command
         */
        for(i = 0; !err && (i < dev->caps.num_comp_vectors); ++i) {
+               /* Make sure request_irq was called */
+               if (!priv->eq_table.eq[i].have_irq)
+                       continue;
+
                /* Temporary use polling for command completions */
                mlx4_cmd_use_polling(dev);
 
index 006757f80988bcb71cfc352542305b61310ef40f..cc3a9897574c542ee368ab067c109128ce89b290 100644 (file)
@@ -2669,14 +2669,11 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev)
 
        if (msi_x) {
                int nreq = dev->caps.num_ports * num_online_cpus() + 1;
-               bool shared_ports = false;
 
                nreq = min_t(int, dev->caps.num_eqs - dev->caps.reserved_eqs,
                             nreq);
-               if (nreq > MAX_MSIX) {
+               if (nreq > MAX_MSIX)
                        nreq = MAX_MSIX;
-                       shared_ports = true;
-               }
 
                entries = kcalloc(nreq, sizeof *entries, GFP_KERNEL);
                if (!entries)
@@ -2699,9 +2696,6 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev)
                bitmap_zero(priv->eq_table.eq[MLX4_EQ_ASYNC].actv_ports.ports,
                            dev->caps.num_ports);
 
-               if (MLX4_IS_LEGACY_EQ_MODE(dev->caps))
-                       shared_ports = true;
-
                for (i = 0; i < dev->caps.num_comp_vectors + 1; i++) {
                        if (i == MLX4_EQ_ASYNC)
                                continue;
@@ -2709,7 +2703,7 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev)
                        priv->eq_table.eq[i].irq =
                                entries[i + 1 - !!(i > MLX4_EQ_ASYNC)].vector;
 
-                       if (shared_ports) {
+                       if (MLX4_IS_LEGACY_EQ_MODE(dev->caps)) {
                                bitmap_fill(priv->eq_table.eq[i].actv_ports.ports,
                                            dev->caps.num_ports);
                                /* We don't set affinity hint when there
index bd9ea0d01aae4cba296d2eba5e9f7a865b5a0426..1d4e2e054647ae3da57bfad23f4460f622ca85b0 100644 (file)
@@ -1184,10 +1184,11 @@ out:
        if (prot == MLX4_PROT_ETH) {
                /* manage the steering entry for promisc mode */
                if (new_entry)
-                       new_steering_entry(dev, port, steer, index, qp->qpn);
+                       err = new_steering_entry(dev, port, steer,
+                                                index, qp->qpn);
                else
-                       existing_steering_entry(dev, port, steer,
-                                               index, qp->qpn);
+                       err = existing_steering_entry(dev, port, steer,
+                                                     index, qp->qpn);
        }
        if (err && link && index != -1) {
                if (index < dev->caps.num_mgms)
index e71563ce05d1bc34123fd4aa63348d569adf4c57..22d603f7827333e2dce6eab7be6ed6acd5a14cdb 100644 (file)
@@ -598,6 +598,8 @@ void mlx5e_enable_vlan_filter(struct mlx5e_priv *priv)
                return;
 
        priv->vlan.filter_disabled = false;
+       if (priv->netdev->flags & IFF_PROMISC)
+               return;
        mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_VID, 0);
 }
 
@@ -607,6 +609,8 @@ void mlx5e_disable_vlan_filter(struct mlx5e_priv *priv)
                return;
 
        priv->vlan.filter_disabled = true;
+       if (priv->netdev->flags & IFF_PROMISC)
+               return;
        mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_VID, 0);
 }
 
@@ -717,8 +721,12 @@ void mlx5e_set_rx_mode_work(struct work_struct *work)
        bool enable_broadcast  = !ea->broadcast_enabled &&  broadcast_enabled;
        bool disable_broadcast =  ea->broadcast_enabled && !broadcast_enabled;
 
-       if (enable_promisc)
+       if (enable_promisc) {
                mlx5e_add_eth_addr_rule(priv, &ea->promisc, MLX5E_PROMISC);
+               if (!priv->vlan.filter_disabled)
+                       mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_VID,
+                                           0);
+       }
        if (enable_allmulti)
                mlx5e_add_eth_addr_rule(priv, &ea->allmulti, MLX5E_ALLMULTI);
        if (enable_broadcast)
@@ -730,8 +738,12 @@ void mlx5e_set_rx_mode_work(struct work_struct *work)
                mlx5e_del_eth_addr_from_flow_table(priv, &ea->broadcast);
        if (disable_allmulti)
                mlx5e_del_eth_addr_from_flow_table(priv, &ea->allmulti);
-       if (disable_promisc)
+       if (disable_promisc) {
+               if (!priv->vlan.filter_disabled)
+                       mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_VID,
+                                           0);
                mlx5e_del_eth_addr_from_flow_table(priv, &ea->promisc);
+       }
 
        ea->promisc_enabled   = promisc_enabled;
        ea->allmulti_enabled  = allmulti_enabled;
index aa0d5ffe92d8177234c1975d958a76751a9539c6..9335e5ae18ccee954b4cc08eff41a01871b41b2e 100644 (file)
@@ -200,25 +200,3 @@ int mlx5_cmd_teardown_hca(struct mlx5_core_dev *dev)
 
        return err;
 }
-
-int mlx5_core_query_special_context(struct mlx5_core_dev *dev, u32 *rsvd_lkey)
-{
-       struct mlx5_cmd_query_special_contexts_mbox_in in;
-       struct mlx5_cmd_query_special_contexts_mbox_out out;
-       int err;
-
-       memset(&in, 0, sizeof(in));
-       memset(&out, 0, sizeof(out));
-       in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_QUERY_SPECIAL_CONTEXTS);
-       err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out));
-       if (err)
-               return err;
-
-       if (out.hdr.status)
-               err = mlx5_cmd_status_to_err(&out.hdr);
-
-       *rsvd_lkey = be32_to_cpu(out.resd_lkey);
-
-       return err;
-}
-EXPORT_SYMBOL(mlx5_core_query_special_context);
index 821caaab9bfb04697fb0424cb8498bdc9eacabed..3b9480fa3403dee018931c16b678f5ec6c98e913 100644 (file)
@@ -311,7 +311,7 @@ static int mlx5_query_port_pvlc(struct mlx5_core_dev *dev, u32 *pvlc,
        int err;
 
        memset(in, 0, sizeof(in));
-       MLX5_SET(ptys_reg, in, local_port, local_port);
+       MLX5_SET(pvlc_reg, in, local_port, local_port);
 
        err = mlx5_core_access_reg(dev, in, sizeof(in), pvlc,
                                   pvlc_size, MLX5_REG_PVLC, 0, 0);
index dbcaf5df8967e828f85648de4edce281860f2a61..28c19cc1a17c5f44a7b15103ce168651502843d8 100644 (file)
@@ -374,26 +374,31 @@ static int __mlxsw_emad_transmit(struct mlxsw_core *mlxsw_core,
        int err;
        int ret;
 
+       mlxsw_core->emad.trans_active = true;
+
        err = mlxsw_core_skb_transmit(mlxsw_core->driver_priv, skb, tx_info);
        if (err) {
                dev_err(mlxsw_core->bus_info->dev, "Failed to transmit EMAD (tid=%llx)\n",
                        mlxsw_core->emad.tid);
                dev_kfree_skb(skb);
-               return err;
+               goto trans_inactive_out;
        }
 
-       mlxsw_core->emad.trans_active = true;
        ret = wait_event_timeout(mlxsw_core->emad.wait,
                                 !(mlxsw_core->emad.trans_active),
                                 msecs_to_jiffies(MLXSW_EMAD_TIMEOUT_MS));
        if (!ret) {
                dev_warn(mlxsw_core->bus_info->dev, "EMAD timed-out (tid=%llx)\n",
                         mlxsw_core->emad.tid);
-               mlxsw_core->emad.trans_active = false;
-               return -EIO;
+               err = -EIO;
+               goto trans_inactive_out;
        }
 
        return 0;
+
+trans_inactive_out:
+       mlxsw_core->emad.trans_active = false;
+       return err;
 }
 
 static int mlxsw_emad_process_status(struct mlxsw_core *mlxsw_core,
index ffd55d030ce28dbf902f6990a0dfb7f96b08a766..36fb1cec53c98e9c7dad0cb7b9b59051d7e0c352 100644 (file)
@@ -187,6 +187,7 @@ __mlxsw_item_bit_array_offset(struct mlxsw_item *item, u16 index, u8 *shift)
 {
        u16 max_index, be_index;
        u16 offset;             /* byte offset inside the array */
+       u8 in_byte_index;
 
        BUG_ON(index && !item->element_size);
        if (item->offset % sizeof(u32) != 0 ||
@@ -199,7 +200,8 @@ __mlxsw_item_bit_array_offset(struct mlxsw_item *item, u16 index, u8 *shift)
        max_index = (item->size.bytes << 3) / item->element_size - 1;
        be_index = max_index - index;
        offset = be_index * item->element_size >> 3;
-       *shift = index % (BITS_PER_BYTE / item->element_size) << 1;
+       in_byte_index  = index % (BITS_PER_BYTE / item->element_size);
+       *shift = in_byte_index * item->element_size;
 
        return item->offset + offset;
 }
index 462cea31ecbb7be6387512dc741286d7fb56658e..cef866c37648ca0c93d4f109eb9d4f3671fcd890 100644 (file)
@@ -1582,11 +1582,11 @@ static int mlxsw_pci_cmd_exec(void *bus_priv, u16 opcode, u8 opcode_mod,
 
        if (in_mbox)
                memcpy(mlxsw_pci->cmd.in_mbox.buf, in_mbox, in_mbox_size);
-       mlxsw_pci_write32(mlxsw_pci, CIR_IN_PARAM_HI, in_mapaddr >> 32);
-       mlxsw_pci_write32(mlxsw_pci, CIR_IN_PARAM_LO, in_mapaddr);
+       mlxsw_pci_write32(mlxsw_pci, CIR_IN_PARAM_HI, upper_32_bits(in_mapaddr));
+       mlxsw_pci_write32(mlxsw_pci, CIR_IN_PARAM_LO, lower_32_bits(in_mapaddr));
 
-       mlxsw_pci_write32(mlxsw_pci, CIR_OUT_PARAM_HI, out_mapaddr >> 32);
-       mlxsw_pci_write32(mlxsw_pci, CIR_OUT_PARAM_LO, out_mapaddr);
+       mlxsw_pci_write32(mlxsw_pci, CIR_OUT_PARAM_HI, upper_32_bits(out_mapaddr));
+       mlxsw_pci_write32(mlxsw_pci, CIR_OUT_PARAM_LO, lower_32_bits(out_mapaddr));
 
        mlxsw_pci_write32(mlxsw_pci, CIR_IN_MODIFIER, in_mod);
        mlxsw_pci_write32(mlxsw_pci, CIR_TOKEN, 0);
index 3e52ee93438c00188d0efe6482cfbd9f686b8ee9..62cbbd1ada8da6a5d8343beb394b67dc5af6a81c 100644 (file)
@@ -1069,9 +1069,9 @@ static int mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port)
        return 0;
 
 err_register_netdev:
-err_port_admin_status_set:
 err_port_mac_learning_mode_set:
 err_port_stp_state_set:
+err_port_admin_status_set:
 err_port_mtu_set:
 err_port_speed_set:
 err_port_swid_set:
index 66d4ab703f45a20b7949e1bd3e448c9dc182e68f..60f43ec2217532abae6c7d4e9529c7db4eb23b4b 100644 (file)
@@ -1601,6 +1601,7 @@ static const struct of_device_id ks8851_match_table[] = {
        { .compatible = "micrel,ks8851" },
        { }
 };
+MODULE_DEVICE_TABLE(of, ks8851_match_table);
 
 static struct spi_driver ks8851_driver = {
        .driver = {
index becbb5f1f5a7af9a22c20761da1dcf1f7db34ec1..a10c928bbd6b9bf5d192dfc6453395312062fe3f 100644 (file)
@@ -552,6 +552,7 @@ static const struct of_device_id moxart_mac_match[] = {
        { .compatible = "moxa,moxart-mac" },
        { }
 };
+MODULE_DEVICE_TABLE(of, moxart_mac_match);
 
 static struct platform_driver moxart_mac_driver = {
        .probe  = moxart_mac_probe,
index a41bb5e6b954f0e6b40375b76a52ed8a254cdb18..75e88f4c15315c84c20106022f38edc1dccf75e7 100644 (file)
@@ -4076,6 +4076,8 @@ static void nv_do_nic_poll(unsigned long data)
        struct fe_priv *np = netdev_priv(dev);
        u8 __iomem *base = get_hwbase(dev);
        u32 mask = 0;
+       unsigned long flags;
+       unsigned int irq = 0;
 
        /*
         * First disable irq(s) and then
@@ -4085,25 +4087,27 @@ static void nv_do_nic_poll(unsigned long data)
 
        if (!using_multi_irqs(dev)) {
                if (np->msi_flags & NV_MSI_X_ENABLED)
-                       disable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
+                       irq = np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector;
                else
-                       disable_irq_lockdep(np->pci_dev->irq);
+                       irq = np->pci_dev->irq;
                mask = np->irqmask;
        } else {
                if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) {
-                       disable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
+                       irq = np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector;
                        mask |= NVREG_IRQ_RX_ALL;
                }
                if (np->nic_poll_irq & NVREG_IRQ_TX_ALL) {
-                       disable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector);
+                       irq = np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector;
                        mask |= NVREG_IRQ_TX_ALL;
                }
                if (np->nic_poll_irq & NVREG_IRQ_OTHER) {
-                       disable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector);
+                       irq = np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector;
                        mask |= NVREG_IRQ_OTHER;
                }
        }
-       /* disable_irq() contains synchronize_irq, thus no irq handler can run now */
+
+       disable_irq_nosync_lockdep_irqsave(irq, &flags);
+       synchronize_irq(irq);
 
        if (np->recover_error) {
                np->recover_error = 0;
@@ -4156,28 +4160,22 @@ static void nv_do_nic_poll(unsigned long data)
                        nv_nic_irq_optimized(0, dev);
                else
                        nv_nic_irq(0, dev);
-               if (np->msi_flags & NV_MSI_X_ENABLED)
-                       enable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
-               else
-                       enable_irq_lockdep(np->pci_dev->irq);
        } else {
                if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) {
                        np->nic_poll_irq &= ~NVREG_IRQ_RX_ALL;
                        nv_nic_irq_rx(0, dev);
-                       enable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
                }
                if (np->nic_poll_irq & NVREG_IRQ_TX_ALL) {
                        np->nic_poll_irq &= ~NVREG_IRQ_TX_ALL;
                        nv_nic_irq_tx(0, dev);
-                       enable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector);
                }
                if (np->nic_poll_irq & NVREG_IRQ_OTHER) {
                        np->nic_poll_irq &= ~NVREG_IRQ_OTHER;
                        nv_nic_irq_other(0, dev);
-                       enable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector);
                }
        }
 
+       enable_irq_lockdep_irqrestore(irq, &flags);
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
index 66fd868152e579a4ba3483fd4726f0e9d9662436..b159ef8303cc3e65d1e374367d19ca590d934901 100644 (file)
@@ -476,13 +476,12 @@ static void __lpc_get_mac(struct netdata_local *pldat, u8 *mac)
        mac[5] = tmp >> 8;
 }
 
-static void __lpc_eth_clock_enable(struct netdata_local *pldat,
-                                  bool enable)
+static void __lpc_eth_clock_enable(struct netdata_local *pldat, bool enable)
 {
        if (enable)
-               clk_enable(pldat->clk);
+               clk_prepare_enable(pldat->clk);
        else
-               clk_disable(pldat->clk);
+               clk_disable_unprepare(pldat->clk);
 }
 
 static void __lpc_params_setup(struct netdata_local *pldat)
@@ -1494,7 +1493,7 @@ err_out_free_irq:
 err_out_iounmap:
        iounmap(pldat->net_base);
 err_out_disable_clocks:
-       clk_disable(pldat->clk);
+       clk_disable_unprepare(pldat->clk);
        clk_put(pldat->clk);
 err_out_free_dev:
        free_netdev(ndev);
@@ -1519,7 +1518,7 @@ static int lpc_eth_drv_remove(struct platform_device *pdev)
        iounmap(pldat->net_base);
        mdiobus_unregister(pldat->mii_bus);
        mdiobus_free(pldat->mii_bus);
-       clk_disable(pldat->clk);
+       clk_disable_unprepare(pldat->clk);
        clk_put(pldat->clk);
        free_netdev(ndev);
 
@@ -1540,7 +1539,7 @@ static int lpc_eth_drv_suspend(struct platform_device *pdev,
                if (netif_running(ndev)) {
                        netif_device_detach(ndev);
                        __lpc_eth_shutdown(pldat);
-                       clk_disable(pldat->clk);
+                       clk_disable_unprepare(pldat->clk);
 
                        /*
                         * Reset again now clock is disable to be sure
index 06bcc734fe8d8680e4e7eb4be6997cc75fc3fbaf..d6696cfa11d256546d623a0fc331ae6934798a78 100644 (file)
@@ -536,6 +536,7 @@ struct qlcnic_hardware_context {
        u8 extend_lb_time;
        u8 phys_port_id[ETH_ALEN];
        u8 lb_mode;
+       u8 vxlan_port_count;
        u16 vxlan_port;
        struct device *hwmon_dev;
        u32 post_mode;
index 8b08b20e8b305fb5b98b6da2b39047a5f1a5978d..d4481454b5f8d8e6951c942d505f080074edc650 100644 (file)
@@ -483,11 +483,17 @@ static void qlcnic_add_vxlan_port(struct net_device *netdev,
        /* Adapter supports only one VXLAN port. Use very first port
         * for enabling offload
         */
-       if (!qlcnic_encap_rx_offload(adapter) || ahw->vxlan_port)
+       if (!qlcnic_encap_rx_offload(adapter))
                return;
+       if (!ahw->vxlan_port_count) {
+               ahw->vxlan_port_count = 1;
+               ahw->vxlan_port = ntohs(port);
+               adapter->flags |= QLCNIC_ADD_VXLAN_PORT;
+               return;
+       }
+       if (ahw->vxlan_port == ntohs(port))
+               ahw->vxlan_port_count++;
 
-       ahw->vxlan_port = ntohs(port);
-       adapter->flags |= QLCNIC_ADD_VXLAN_PORT;
 }
 
 static void qlcnic_del_vxlan_port(struct net_device *netdev,
@@ -496,11 +502,13 @@ static void qlcnic_del_vxlan_port(struct net_device *netdev,
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
        struct qlcnic_hardware_context *ahw = adapter->ahw;
 
-       if (!qlcnic_encap_rx_offload(adapter) || !ahw->vxlan_port ||
+       if (!qlcnic_encap_rx_offload(adapter) || !ahw->vxlan_port_count ||
            (ahw->vxlan_port != ntohs(port)))
                return;
 
-       adapter->flags |= QLCNIC_DEL_VXLAN_PORT;
+       ahw->vxlan_port_count--;
+       if (!ahw->vxlan_port_count)
+               adapter->flags |= QLCNIC_DEL_VXLAN_PORT;
 }
 
 static netdev_features_t qlcnic_features_check(struct sk_buff *skb,
index d79e33b3c1913ae41caa046860fc74fb2d4c8698..686334f4588dcd928578ed83892fb4febac2d5ea 100644 (file)
@@ -157,6 +157,7 @@ enum {
        NWayAdvert      = 0x66, /* MII ADVERTISE */
        NWayLPAR        = 0x68, /* MII LPA */
        NWayExpansion   = 0x6A, /* MII Expansion */
+       TxDmaOkLowDesc  = 0x82, /* Low 16 bit address of a Tx descriptor. */
        Config5         = 0xD8, /* Config5 */
        TxPoll          = 0xD9, /* Tell chip to check Tx descriptors for work */
        RxMaxSize       = 0xDA, /* Max size of an Rx packet (8169 only) */
@@ -341,6 +342,7 @@ struct cp_private {
        unsigned                tx_tail;
        struct cp_desc          *tx_ring;
        struct sk_buff          *tx_skb[CP_TX_RING_SIZE];
+       u32                     tx_opts[CP_TX_RING_SIZE];
 
        unsigned                rx_buf_sz;
        unsigned                wol_enabled : 1; /* Is Wake-on-LAN enabled? */
@@ -665,7 +667,7 @@ static void cp_tx (struct cp_private *cp)
                BUG_ON(!skb);
 
                dma_unmap_single(&cp->pdev->dev, le64_to_cpu(txd->addr),
-                                le32_to_cpu(txd->opts1) & 0xffff,
+                                cp->tx_opts[tx_tail] & 0xffff,
                                 PCI_DMA_TODEVICE);
 
                if (status & LastFrag) {
@@ -733,7 +735,7 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
 {
        struct cp_private *cp = netdev_priv(dev);
        unsigned entry;
-       u32 eor, flags;
+       u32 eor, opts1;
        unsigned long intr_flags;
        __le32 opts2;
        int mss = 0;
@@ -753,6 +755,21 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
        mss = skb_shinfo(skb)->gso_size;
 
        opts2 = cpu_to_le32(cp_tx_vlan_tag(skb));
+       opts1 = DescOwn;
+       if (mss)
+               opts1 |= LargeSend | ((mss & MSSMask) << MSSShift);
+       else if (skb->ip_summed == CHECKSUM_PARTIAL) {
+               const struct iphdr *ip = ip_hdr(skb);
+               if (ip->protocol == IPPROTO_TCP)
+                       opts1 |= IPCS | TCPCS;
+               else if (ip->protocol == IPPROTO_UDP)
+                       opts1 |= IPCS | UDPCS;
+               else {
+                       WARN_ONCE(1,
+                                 "Net bug: asked to checksum invalid Legacy IP packet\n");
+                       goto out_dma_error;
+               }
+       }
 
        if (skb_shinfo(skb)->nr_frags == 0) {
                struct cp_desc *txd = &cp->tx_ring[entry];
@@ -768,31 +785,20 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
                txd->addr = cpu_to_le64(mapping);
                wmb();
 
-               flags = eor | len | DescOwn | FirstFrag | LastFrag;
-
-               if (mss)
-                       flags |= LargeSend | ((mss & MSSMask) << MSSShift);
-               else if (skb->ip_summed == CHECKSUM_PARTIAL) {
-                       const struct iphdr *ip = ip_hdr(skb);
-                       if (ip->protocol == IPPROTO_TCP)
-                               flags |= IPCS | TCPCS;
-                       else if (ip->protocol == IPPROTO_UDP)
-                               flags |= IPCS | UDPCS;
-                       else
-                               WARN_ON(1);     /* we need a WARN() */
-               }
+               opts1 |= eor | len | FirstFrag | LastFrag;
 
-               txd->opts1 = cpu_to_le32(flags);
+               txd->opts1 = cpu_to_le32(opts1);
                wmb();
 
                cp->tx_skb[entry] = skb;
-               entry = NEXT_TX(entry);
+               cp->tx_opts[entry] = opts1;
+               netif_dbg(cp, tx_queued, cp->dev, "tx queued, slot %d, skblen %d\n",
+                         entry, skb->len);
        } else {
                struct cp_desc *txd;
-               u32 first_len, first_eor;
+               u32 first_len, first_eor, ctrl;
                dma_addr_t first_mapping;
                int frag, first_entry = entry;
-               const struct iphdr *ip = ip_hdr(skb);
 
                /* We must give this initial chunk to the device last.
                 * Otherwise we could race with the device.
@@ -805,14 +811,14 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
                        goto out_dma_error;
 
                cp->tx_skb[entry] = skb;
-               entry = NEXT_TX(entry);
 
                for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
                        const skb_frag_t *this_frag = &skb_shinfo(skb)->frags[frag];
                        u32 len;
-                       u32 ctrl;
                        dma_addr_t mapping;
 
+                       entry = NEXT_TX(entry);
+
                        len = skb_frag_size(this_frag);
                        mapping = dma_map_single(&cp->pdev->dev,
                                                 skb_frag_address(this_frag),
@@ -824,19 +830,7 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
 
                        eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
 
-                       ctrl = eor | len | DescOwn;
-
-                       if (mss)
-                               ctrl |= LargeSend |
-                                       ((mss & MSSMask) << MSSShift);
-                       else if (skb->ip_summed == CHECKSUM_PARTIAL) {
-                               if (ip->protocol == IPPROTO_TCP)
-                                       ctrl |= IPCS | TCPCS;
-                               else if (ip->protocol == IPPROTO_UDP)
-                                       ctrl |= IPCS | UDPCS;
-                               else
-                                       BUG();
-                       }
+                       ctrl = opts1 | eor | len;
 
                        if (frag == skb_shinfo(skb)->nr_frags - 1)
                                ctrl |= LastFrag;
@@ -849,8 +843,8 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
                        txd->opts1 = cpu_to_le32(ctrl);
                        wmb();
 
+                       cp->tx_opts[entry] = ctrl;
                        cp->tx_skb[entry] = skb;
-                       entry = NEXT_TX(entry);
                }
 
                txd = &cp->tx_ring[first_entry];
@@ -858,27 +852,17 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
                txd->addr = cpu_to_le64(first_mapping);
                wmb();
 
-               if (skb->ip_summed == CHECKSUM_PARTIAL) {
-                       if (ip->protocol == IPPROTO_TCP)
-                               txd->opts1 = cpu_to_le32(first_eor | first_len |
-                                                        FirstFrag | DescOwn |
-                                                        IPCS | TCPCS);
-                       else if (ip->protocol == IPPROTO_UDP)
-                               txd->opts1 = cpu_to_le32(first_eor | first_len |
-                                                        FirstFrag | DescOwn |
-                                                        IPCS | UDPCS);
-                       else
-                               BUG();
-               } else
-                       txd->opts1 = cpu_to_le32(first_eor | first_len |
-                                                FirstFrag | DescOwn);
+               ctrl = opts1 | first_eor | first_len | FirstFrag;
+               txd->opts1 = cpu_to_le32(ctrl);
                wmb();
+
+               cp->tx_opts[first_entry] = ctrl;
+               netif_dbg(cp, tx_queued, cp->dev, "tx queued, slots %d-%d, skblen %d\n",
+                         first_entry, entry, skb->len);
        }
-       cp->tx_head = entry;
+       cp->tx_head = NEXT_TX(entry);
 
        netdev_sent_queue(dev, skb->len);
-       netif_dbg(cp, tx_queued, cp->dev, "tx queued, slot %d, skblen %d\n",
-                 entry, skb->len);
        if (TX_BUFFS_AVAIL(cp) <= (MAX_SKB_FRAGS + 1))
                netif_stop_queue(dev);
 
@@ -1115,6 +1099,7 @@ static int cp_init_rings (struct cp_private *cp)
 {
        memset(cp->tx_ring, 0, sizeof(struct cp_desc) * CP_TX_RING_SIZE);
        cp->tx_ring[CP_TX_RING_SIZE - 1].opts1 = cpu_to_le32(RingEnd);
+       memset(cp->tx_opts, 0, sizeof(cp->tx_opts));
 
        cp_init_rings_index(cp);
 
@@ -1151,7 +1136,7 @@ static void cp_clean_rings (struct cp_private *cp)
                        desc = cp->rx_ring + i;
                        dma_unmap_single(&cp->pdev->dev,le64_to_cpu(desc->addr),
                                         cp->rx_buf_sz, PCI_DMA_FROMDEVICE);
-                       dev_kfree_skb(cp->rx_skb[i]);
+                       dev_kfree_skb_any(cp->rx_skb[i]);
                }
        }
 
@@ -1164,7 +1149,7 @@ static void cp_clean_rings (struct cp_private *cp)
                                         le32_to_cpu(desc->opts1) & 0xffff,
                                         PCI_DMA_TODEVICE);
                        if (le32_to_cpu(desc->opts1) & LastFrag)
-                               dev_kfree_skb(skb);
+                               dev_kfree_skb_any(skb);
                        cp->dev->stats.tx_dropped++;
                }
        }
@@ -1172,6 +1157,7 @@ static void cp_clean_rings (struct cp_private *cp)
 
        memset(cp->rx_ring, 0, sizeof(struct cp_desc) * CP_RX_RING_SIZE);
        memset(cp->tx_ring, 0, sizeof(struct cp_desc) * CP_TX_RING_SIZE);
+       memset(cp->tx_opts, 0, sizeof(cp->tx_opts));
 
        memset(cp->rx_skb, 0, sizeof(struct sk_buff *) * CP_RX_RING_SIZE);
        memset(cp->tx_skb, 0, sizeof(struct sk_buff *) * CP_TX_RING_SIZE);
@@ -1249,7 +1235,7 @@ static void cp_tx_timeout(struct net_device *dev)
 {
        struct cp_private *cp = netdev_priv(dev);
        unsigned long flags;
-       int rc;
+       int rc, i;
 
        netdev_warn(dev, "Transmit timeout, status %2x %4x %4x %4x\n",
                    cpr8(Cmd), cpr16(CpCmd),
@@ -1257,13 +1243,26 @@ static void cp_tx_timeout(struct net_device *dev)
 
        spin_lock_irqsave(&cp->lock, flags);
 
+       netif_dbg(cp, tx_err, cp->dev, "TX ring head %d tail %d desc %x\n",
+                 cp->tx_head, cp->tx_tail, cpr16(TxDmaOkLowDesc));
+       for (i = 0; i < CP_TX_RING_SIZE; i++) {
+               netif_dbg(cp, tx_err, cp->dev,
+                         "TX slot %d @%p: %08x (%08x) %08x %llx %p\n",
+                         i, &cp->tx_ring[i], le32_to_cpu(cp->tx_ring[i].opts1),
+                         cp->tx_opts[i], le32_to_cpu(cp->tx_ring[i].opts2),
+                         le64_to_cpu(cp->tx_ring[i].addr),
+                         cp->tx_skb[i]);
+       }
+
        cp_stop_hw(cp);
        cp_clean_rings(cp);
        rc = cp_init_rings(cp);
        cp_start_hw(cp);
-       cp_enable_irq(cp);
+       __cp_set_rx_mode(dev);
+       cpw16_f(IntrMask, cp_norx_intr_mask);
 
        netif_wake_queue(dev);
+       napi_schedule_irqoff(&cp->napi);
 
        spin_unlock_irqrestore(&cp->lock, flags);
 }
index 2b32e0c5a0b46bcdb4e50d1931c676f2f65503d0..b4f21232019a98c7e0afd9e5a43a5a160da765fe 100644 (file)
@@ -6081,7 +6081,7 @@ static void rtl_hw_start_8168h_1(struct rtl8169_private *tp)
 {
        void __iomem *ioaddr = tp->mmio_addr;
        struct pci_dev *pdev = tp->pci_dev;
-       u16 rg_saw_cnt;
+       int rg_saw_cnt;
        u32 data;
        static const struct ephy_info e_info_8168h_1[] = {
                { 0x1e, 0x0800, 0x0001 },
index 257ea713b4c1564fa680acfcf7ad760268ea0df6..a484d8beb8557935b30251dc70bf3ef3d3b64dbc 100644 (file)
@@ -1127,7 +1127,7 @@ static void sh_eth_ring_format(struct net_device *ndev)
        struct sh_eth_txdesc *txdesc = NULL;
        int rx_ringsize = sizeof(*rxdesc) * mdp->num_rx_ring;
        int tx_ringsize = sizeof(*txdesc) * mdp->num_tx_ring;
-       int skbuff_size = mdp->rx_buf_sz + SH_ETH_RX_ALIGN - 1;
+       int skbuff_size = mdp->rx_buf_sz + SH_ETH_RX_ALIGN + 32 - 1;
        dma_addr_t dma_addr;
 
        mdp->cur_rx = 0;
@@ -1148,8 +1148,8 @@ static void sh_eth_ring_format(struct net_device *ndev)
 
                /* RX descriptor */
                rxdesc = &mdp->rx_ring[i];
-               /* The size of the buffer is a multiple of 16 bytes. */
-               rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16);
+               /* The size of the buffer is a multiple of 32 bytes. */
+               rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 32);
                dma_addr = dma_map_single(&ndev->dev, skb->data,
                                          rxdesc->buffer_length,
                                          DMA_FROM_DEVICE);
@@ -1450,7 +1450,7 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
        struct sk_buff *skb;
        u16 pkt_len = 0;
        u32 desc_status;
-       int skbuff_size = mdp->rx_buf_sz + SH_ETH_RX_ALIGN - 1;
+       int skbuff_size = mdp->rx_buf_sz + SH_ETH_RX_ALIGN + 32 - 1;
        dma_addr_t dma_addr;
 
        boguscnt = min(boguscnt, *quota);
@@ -1506,7 +1506,7 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
                        if (mdp->cd->rpadir)
                                skb_reserve(skb, NET_IP_ALIGN);
                        dma_unmap_single(&ndev->dev, rxdesc->addr,
-                                        ALIGN(mdp->rx_buf_sz, 16),
+                                        ALIGN(mdp->rx_buf_sz, 32),
                                         DMA_FROM_DEVICE);
                        skb_put(skb, pkt_len);
                        skb->protocol = eth_type_trans(skb, ndev);
@@ -1524,8 +1524,8 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
        for (; mdp->cur_rx - mdp->dirty_rx > 0; mdp->dirty_rx++) {
                entry = mdp->dirty_rx % mdp->num_rx_ring;
                rxdesc = &mdp->rx_ring[entry];
-               /* The size of the buffer is 16 byte boundary. */
-               rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16);
+               /* The size of the buffer is 32 byte boundary. */
+               rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 32);
 
                if (mdp->rx_skbuff[entry] == NULL) {
                        skb = netdev_alloc_skb(ndev, skbuff_size);
index b735fa22ac95a95fa7bef8b4c4672637bb356148..ebf6abc4853f300392677614d6f45be0f95e8fca 100644 (file)
@@ -161,11 +161,16 @@ int stmmac_mdio_reset(struct mii_bus *bus)
 
                if (!gpio_request(reset_gpio, "mdio-reset")) {
                        gpio_direction_output(reset_gpio, active_low ? 1 : 0);
-                       udelay(data->delays[0]);
+                       if (data->delays[0])
+                               msleep(DIV_ROUND_UP(data->delays[0], 1000));
+
                        gpio_set_value(reset_gpio, active_low ? 0 : 1);
-                       udelay(data->delays[1]);
+                       if (data->delays[1])
+                               msleep(DIV_ROUND_UP(data->delays[1], 1000));
+
                        gpio_set_value(reset_gpio, active_low ? 1 : 0);
-                       udelay(data->delays[2]);
+                       if (data->delays[2])
+                               msleep(DIV_ROUND_UP(data->delays[2], 1000));
                }
        }
 #endif
index 53fe200e0b7949b810071c23a08af49167ccdf63..cc106d892e2975c924eafc8e850a4da8188ef227 100644 (file)
@@ -1756,7 +1756,8 @@ static const struct net_device_ops vnet_ops = {
 #endif
 };
 
-static struct vnet *vnet_new(const u64 *local_mac)
+static struct vnet *vnet_new(const u64 *local_mac,
+                            struct vio_dev *vdev)
 {
        struct net_device *dev;
        struct vnet *vp;
@@ -1790,6 +1791,8 @@ static struct vnet *vnet_new(const u64 *local_mac)
                           NETIF_F_HW_CSUM | NETIF_F_SG;
        dev->features = dev->hw_features;
 
+       SET_NETDEV_DEV(dev, &vdev->dev);
+
        err = register_netdev(dev);
        if (err) {
                pr_err("Cannot register net device, aborting\n");
@@ -1808,7 +1811,8 @@ err_out_free_dev:
        return ERR_PTR(err);
 }
 
-static struct vnet *vnet_find_or_create(const u64 *local_mac)
+static struct vnet *vnet_find_or_create(const u64 *local_mac,
+                                       struct vio_dev *vdev)
 {
        struct vnet *iter, *vp;
 
@@ -1821,7 +1825,7 @@ static struct vnet *vnet_find_or_create(const u64 *local_mac)
                }
        }
        if (!vp)
-               vp = vnet_new(local_mac);
+               vp = vnet_new(local_mac, vdev);
        mutex_unlock(&vnet_list_mutex);
 
        return vp;
@@ -1848,7 +1852,8 @@ static void vnet_cleanup(void)
 static const char *local_mac_prop = "local-mac-address";
 
 static struct vnet *vnet_find_parent(struct mdesc_handle *hp,
-                                               u64 port_node)
+                                    u64 port_node,
+                                    struct vio_dev *vdev)
 {
        const u64 *local_mac = NULL;
        u64 a;
@@ -1869,7 +1874,7 @@ static struct vnet *vnet_find_parent(struct mdesc_handle *hp,
        if (!local_mac)
                return ERR_PTR(-ENODEV);
 
-       return vnet_find_or_create(local_mac);
+       return vnet_find_or_create(local_mac, vdev);
 }
 
 static struct ldc_channel_config vnet_ldc_cfg = {
@@ -1923,7 +1928,7 @@ static int vnet_port_probe(struct vio_dev *vdev, const struct vio_device_id *id)
 
        hp = mdesc_grab();
 
-       vp = vnet_find_parent(hp, vdev->mp);
+       vp = vnet_find_parent(hp, vdev->mp, vdev);
        if (IS_ERR(vp)) {
                pr_err("Cannot find port parent vnet\n");
                err = PTR_ERR(vp);
index 8fc90f1c872c6fe5afe2105aae62c54d8283800f..874fb297e96c563525a5d275a8e2239b6ab41725 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/delay.h>
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
+#include <linux/of_mdio.h>
 #include <linux/of_net.h>
 #include <linux/of_device.h>
 #include <linux/if_vlan.h>
@@ -365,6 +366,7 @@ struct cpsw_priv {
        spinlock_t                      lock;
        struct platform_device          *pdev;
        struct net_device               *ndev;
+       struct device_node              *phy_node;
        struct napi_struct              napi_rx;
        struct napi_struct              napi_tx;
        struct device                   *dev;
@@ -1145,7 +1147,11 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
                cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
                                   1 << slave_port, 0, 0, ALE_MCAST_FWD_2);
 
-       slave->phy = phy_connect(priv->ndev, slave->data->phy_id,
+       if (priv->phy_node)
+               slave->phy = of_phy_connect(priv->ndev, priv->phy_node,
+                                &cpsw_adjust_link, 0, slave->data->phy_if);
+       else
+               slave->phy = phy_connect(priv->ndev, slave->data->phy_id,
                                 &cpsw_adjust_link, slave->data->phy_if);
        if (IS_ERR(slave->phy)) {
                dev_err(priv->dev, "phy %s not found on slave %d\n",
@@ -1934,11 +1940,12 @@ static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv,
        slave->port_vlan = data->dual_emac_res_vlan;
 }
 
-static int cpsw_probe_dt(struct cpsw_platform_data *data,
+static int cpsw_probe_dt(struct cpsw_priv *priv,
                         struct platform_device *pdev)
 {
        struct device_node *node = pdev->dev.of_node;
        struct device_node *slave_node;
+       struct cpsw_platform_data *data = &priv->data;
        int i = 0, ret;
        u32 prop;
 
@@ -2029,6 +2036,7 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
                if (strcmp(slave_node->name, "slave"))
                        continue;
 
+               priv->phy_node = of_parse_phandle(slave_node, "phy-handle", 0);
                parp = of_get_property(slave_node, "phy_id", &lenp);
                if ((parp == NULL) || (lenp != (sizeof(void *) * 2))) {
                        dev_err(&pdev->dev, "Missing slave[%d] phy_id property\n", i);
@@ -2044,7 +2052,6 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
                }
                snprintf(slave_data->phy_id, sizeof(slave_data->phy_id),
                         PHY_ID_FMT, mdio->name, phyid);
-
                slave_data->phy_if = of_get_phy_mode(slave_node);
                if (slave_data->phy_if < 0) {
                        dev_err(&pdev->dev, "Missing or malformed slave[%d] phy-mode property\n",
@@ -2240,7 +2247,7 @@ static int cpsw_probe(struct platform_device *pdev)
        /* Select default pin state */
        pinctrl_pm_select_default_state(&pdev->dev);
 
-       if (cpsw_probe_dt(&priv->data, pdev)) {
+       if (cpsw_probe_dt(priv, pdev)) {
                dev_err(&pdev->dev, "cpsw: platform data missing\n");
                ret = -ENODEV;
                goto clean_runtime_disable_ret;
index 1a5aca55ea9f1764e59624ddf0703c4f1d2ecb5a..9f9832f0dea9545d619cf335cce22d412ec0d882 100644 (file)
@@ -291,13 +291,6 @@ static int netcp_module_probe(struct netcp_device *netcp_device,
                            interface_list) {
                struct netcp_intf_modpriv *intf_modpriv;
 
-               /* If interface not registered then register now */
-               if (!netcp_intf->netdev_registered)
-                       ret = netcp_register_interface(netcp_intf);
-
-               if (ret)
-                       return -ENODEV;
-
                intf_modpriv = devm_kzalloc(dev, sizeof(*intf_modpriv),
                                            GFP_KERNEL);
                if (!intf_modpriv)
@@ -306,6 +299,11 @@ static int netcp_module_probe(struct netcp_device *netcp_device,
                interface = of_parse_phandle(netcp_intf->node_interface,
                                             module->name, 0);
 
+               if (!interface) {
+                       devm_kfree(dev, intf_modpriv);
+                       continue;
+               }
+
                intf_modpriv->netcp_priv = netcp_intf;
                intf_modpriv->netcp_module = module;
                list_add_tail(&intf_modpriv->intf_list,
@@ -323,6 +321,18 @@ static int netcp_module_probe(struct netcp_device *netcp_device,
                        continue;
                }
        }
+
+       /* Now register the interface with netdev */
+       list_for_each_entry(netcp_intf,
+                           &netcp_device->interface_head,
+                           interface_list) {
+               /* If interface not registered then register now */
+               if (!netcp_intf->netdev_registered) {
+                       ret = netcp_register_interface(netcp_intf);
+                       if (ret)
+                               return -ENODEV;
+               }
+       }
        return 0;
 }
 
@@ -357,7 +367,6 @@ int netcp_register_module(struct netcp_module *module)
                if (ret < 0)
                        goto fail;
        }
-
        mutex_unlock(&netcp_modules_lock);
        return 0;
 
@@ -796,7 +805,7 @@ static void netcp_rxpool_free(struct netcp_intf *netcp)
        netcp->rx_pool = NULL;
 }
 
-static void netcp_allocate_rx_buf(struct netcp_intf *netcp, int fdq)
+static int netcp_allocate_rx_buf(struct netcp_intf *netcp, int fdq)
 {
        struct knav_dma_desc *hwdesc;
        unsigned int buf_len, dma_sz;
@@ -810,7 +819,7 @@ static void netcp_allocate_rx_buf(struct netcp_intf *netcp, int fdq)
        hwdesc = knav_pool_desc_get(netcp->rx_pool);
        if (IS_ERR_OR_NULL(hwdesc)) {
                dev_dbg(netcp->ndev_dev, "out of rx pool desc\n");
-               return;
+               return -ENOMEM;
        }
 
        if (likely(fdq == 0)) {
@@ -862,25 +871,26 @@ static void netcp_allocate_rx_buf(struct netcp_intf *netcp, int fdq)
        knav_pool_desc_map(netcp->rx_pool, hwdesc, sizeof(*hwdesc), &dma,
                           &dma_sz);
        knav_queue_push(netcp->rx_fdq[fdq], dma, sizeof(*hwdesc), 0);
-       return;
+       return 0;
 
 fail:
        knav_pool_desc_put(netcp->rx_pool, hwdesc);
+       return -ENOMEM;
 }
 
 /* Refill Rx FDQ with descriptors & attached buffers */
 static void netcp_rxpool_refill(struct netcp_intf *netcp)
 {
        u32 fdq_deficit[KNAV_DMA_FDQ_PER_CHAN] = {0};
-       int i;
+       int i, ret = 0;
 
        /* Calculate the FDQ deficit and refill */
        for (i = 0; i < KNAV_DMA_FDQ_PER_CHAN && netcp->rx_fdq[i]; i++) {
                fdq_deficit[i] = netcp->rx_queue_depths[i] -
                                 knav_queue_get_count(netcp->rx_fdq[i]);
 
-               while (fdq_deficit[i]--)
-                       netcp_allocate_rx_buf(netcp, i);
+               while (fdq_deficit[i]-- && !ret)
+                       ret = netcp_allocate_rx_buf(netcp, i);
        } /* end for fdqs */
 }
 
@@ -893,12 +903,12 @@ static int netcp_rx_poll(struct napi_struct *napi, int budget)
 
        packets = netcp_process_rx_packets(netcp, budget);
 
+       netcp_rxpool_refill(netcp);
        if (packets < budget) {
                napi_complete(&netcp->rx_napi);
                knav_queue_enable_notify(netcp->rx_queue);
        }
 
-       netcp_rxpool_refill(netcp);
        return packets;
 }
 
@@ -1384,7 +1394,6 @@ static void netcp_addr_sweep_del(struct netcp_intf *netcp)
                        continue;
                dev_dbg(netcp->ndev_dev, "deleting address %pM, type %x\n",
                        naddr->addr, naddr->type);
-               mutex_lock(&netcp_modules_lock);
                for_each_module(netcp, priv) {
                        module = priv->netcp_module;
                        if (!module->del_addr)
@@ -1393,7 +1402,6 @@ static void netcp_addr_sweep_del(struct netcp_intf *netcp)
                                                 naddr);
                        WARN_ON(error);
                }
-               mutex_unlock(&netcp_modules_lock);
                netcp_addr_del(netcp, naddr);
        }
 }
@@ -1410,7 +1418,7 @@ static void netcp_addr_sweep_add(struct netcp_intf *netcp)
                        continue;
                dev_dbg(netcp->ndev_dev, "adding address %pM, type %x\n",
                        naddr->addr, naddr->type);
-               mutex_lock(&netcp_modules_lock);
+
                for_each_module(netcp, priv) {
                        module = priv->netcp_module;
                        if (!module->add_addr)
@@ -1418,7 +1426,6 @@ static void netcp_addr_sweep_add(struct netcp_intf *netcp)
                        error = module->add_addr(priv->module_priv, naddr);
                        WARN_ON(error);
                }
-               mutex_unlock(&netcp_modules_lock);
        }
 }
 
@@ -1432,6 +1439,7 @@ static void netcp_set_rx_mode(struct net_device *ndev)
                   ndev->flags & IFF_ALLMULTI ||
                   netdev_mc_count(ndev) > NETCP_MAX_MCAST_ADDR);
 
+       spin_lock(&netcp->lock);
        /* first clear all marks */
        netcp_addr_clear_mark(netcp);
 
@@ -1450,6 +1458,7 @@ static void netcp_set_rx_mode(struct net_device *ndev)
        /* finally sweep and callout into modules */
        netcp_addr_sweep_del(netcp);
        netcp_addr_sweep_add(netcp);
+       spin_unlock(&netcp->lock);
 }
 
 static void netcp_free_navigator_resources(struct netcp_intf *netcp)
@@ -1614,7 +1623,6 @@ static int netcp_ndo_open(struct net_device *ndev)
                goto fail;
        }
 
-       mutex_lock(&netcp_modules_lock);
        for_each_module(netcp, intf_modpriv) {
                module = intf_modpriv->netcp_module;
                if (module->open) {
@@ -1625,7 +1633,6 @@ static int netcp_ndo_open(struct net_device *ndev)
                        }
                }
        }
-       mutex_unlock(&netcp_modules_lock);
 
        napi_enable(&netcp->rx_napi);
        napi_enable(&netcp->tx_napi);
@@ -1642,7 +1649,6 @@ fail_open:
                if (module->close)
                        module->close(intf_modpriv->module_priv, ndev);
        }
-       mutex_unlock(&netcp_modules_lock);
 
 fail:
        netcp_free_navigator_resources(netcp);
@@ -1666,7 +1672,6 @@ static int netcp_ndo_stop(struct net_device *ndev)
        napi_disable(&netcp->rx_napi);
        napi_disable(&netcp->tx_napi);
 
-       mutex_lock(&netcp_modules_lock);
        for_each_module(netcp, intf_modpriv) {
                module = intf_modpriv->netcp_module;
                if (module->close) {
@@ -1675,7 +1680,6 @@ static int netcp_ndo_stop(struct net_device *ndev)
                                dev_err(netcp->ndev_dev, "Close failed\n");
                }
        }
-       mutex_unlock(&netcp_modules_lock);
 
        /* Recycle Rx descriptors from completion queue */
        netcp_empty_rx_queue(netcp);
@@ -1703,7 +1707,6 @@ static int netcp_ndo_ioctl(struct net_device *ndev,
        if (!netif_running(ndev))
                return -EINVAL;
 
-       mutex_lock(&netcp_modules_lock);
        for_each_module(netcp, intf_modpriv) {
                module = intf_modpriv->netcp_module;
                if (!module->ioctl)
@@ -1719,7 +1722,6 @@ static int netcp_ndo_ioctl(struct net_device *ndev,
        }
 
 out:
-       mutex_unlock(&netcp_modules_lock);
        return (ret == 0) ? 0 : err;
 }
 
@@ -1754,11 +1756,12 @@ static int netcp_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid)
        struct netcp_intf *netcp = netdev_priv(ndev);
        struct netcp_intf_modpriv *intf_modpriv;
        struct netcp_module *module;
+       unsigned long flags;
        int err = 0;
 
        dev_dbg(netcp->ndev_dev, "adding rx vlan id: %d\n", vid);
 
-       mutex_lock(&netcp_modules_lock);
+       spin_lock_irqsave(&netcp->lock, flags);
        for_each_module(netcp, intf_modpriv) {
                module = intf_modpriv->netcp_module;
                if ((module->add_vid) && (vid != 0)) {
@@ -1770,7 +1773,8 @@ static int netcp_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid)
                        }
                }
        }
-       mutex_unlock(&netcp_modules_lock);
+       spin_unlock_irqrestore(&netcp->lock, flags);
+
        return err;
 }
 
@@ -1779,11 +1783,12 @@ static int netcp_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vid)
        struct netcp_intf *netcp = netdev_priv(ndev);
        struct netcp_intf_modpriv *intf_modpriv;
        struct netcp_module *module;
+       unsigned long flags;
        int err = 0;
 
        dev_dbg(netcp->ndev_dev, "removing rx vlan id: %d\n", vid);
 
-       mutex_lock(&netcp_modules_lock);
+       spin_lock_irqsave(&netcp->lock, flags);
        for_each_module(netcp, intf_modpriv) {
                module = intf_modpriv->netcp_module;
                if (module->del_vid) {
@@ -1795,7 +1800,7 @@ static int netcp_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vid)
                        }
                }
        }
-       mutex_unlock(&netcp_modules_lock);
+       spin_unlock_irqrestore(&netcp->lock, flags);
        return err;
 }
 
@@ -2040,7 +2045,6 @@ static int netcp_probe(struct platform_device *pdev)
        struct device_node *child, *interfaces;
        struct netcp_device *netcp_device;
        struct device *dev = &pdev->dev;
-       struct netcp_module *module;
        int ret;
 
        if (!node) {
@@ -2087,14 +2091,6 @@ static int netcp_probe(struct platform_device *pdev)
        /* Add the device instance to the list */
        list_add_tail(&netcp_device->device_list, &netcp_devices);
 
-       /* Probe & attach any modules already registered */
-       mutex_lock(&netcp_modules_lock);
-       for_each_netcp_module(module) {
-               ret = netcp_module_probe(netcp_device, module);
-               if (ret < 0)
-                       dev_err(dev, "module(%s) probe failed\n", module->name);
-       }
-       mutex_unlock(&netcp_modules_lock);
        return 0;
 
 probe_quit_interface:
index 6f16d6aaf7b76cdf5da3445b1a7c639f04e46200..4e70e7586a0918a045008b7e54e807f0f11e2de9 100644 (file)
@@ -77,6 +77,7 @@
 #define GBENU_ALE_OFFSET               0x1e000
 #define GBENU_HOST_PORT_NUM            0
 #define GBENU_NUM_ALE_ENTRIES          1024
+#define GBENU_SGMII_MODULE_SIZE                0x100
 
 /* 10G Ethernet SS defines */
 #define XGBE_MODULE_NAME               "netcp-xgbe"
 #define XGBE_STATS2_MODULE                     2
 
 /* s: 0-based slave_port */
-#define SGMII_BASE(s) \
-       (((s) < 2) ? gbe_dev->sgmii_port_regs : gbe_dev->sgmii_port34_regs)
+#define SGMII_BASE(d, s) \
+       (((s) < 2) ? (d)->sgmii_port_regs : (d)->sgmii_port34_regs)
 
 #define GBE_TX_QUEUE                           648
 #define        GBE_TXHOOK_ORDER                        0
@@ -1997,13 +1998,8 @@ static void netcp_ethss_update_link_state(struct gbe_priv *gbe_dev,
                return;
 
        if (!SLAVE_LINK_IS_XGMII(slave)) {
-               if (gbe_dev->ss_version == GBE_SS_VERSION_14)
-                       sgmii_link_state =
-                               netcp_sgmii_get_port_link(SGMII_BASE(sp), sp);
-               else
-                       sgmii_link_state =
-                               netcp_sgmii_get_port_link(
-                                               gbe_dev->sgmii_port_regs, sp);
+               sgmii_link_state =
+                       netcp_sgmii_get_port_link(SGMII_BASE(gbe_dev, sp), sp);
        }
 
        phy_link_state = gbe_phy_link_status(slave);
@@ -2100,17 +2096,11 @@ static void gbe_port_config(struct gbe_priv *gbe_dev, struct gbe_slave *slave,
 static void gbe_sgmii_rtreset(struct gbe_priv *priv,
                              struct gbe_slave *slave, bool set)
 {
-       void __iomem *sgmii_port_regs;
-
        if (SLAVE_LINK_IS_XGMII(slave))
                return;
 
-       if ((priv->ss_version == GBE_SS_VERSION_14) && (slave->slave_num >= 2))
-               sgmii_port_regs = priv->sgmii_port34_regs;
-       else
-               sgmii_port_regs = priv->sgmii_port_regs;
-
-       netcp_sgmii_rtreset(sgmii_port_regs, slave->slave_num, set);
+       netcp_sgmii_rtreset(SGMII_BASE(priv, slave->slave_num),
+                           slave->slave_num, set);
 }
 
 static void gbe_slave_stop(struct gbe_intf *intf)
@@ -2136,17 +2126,12 @@ static void gbe_slave_stop(struct gbe_intf *intf)
 
 static void gbe_sgmii_config(struct gbe_priv *priv, struct gbe_slave *slave)
 {
-       void __iomem *sgmii_port_regs;
-
-       sgmii_port_regs = priv->sgmii_port_regs;
-       if ((priv->ss_version == GBE_SS_VERSION_14) && (slave->slave_num >= 2))
-               sgmii_port_regs = priv->sgmii_port34_regs;
+       if (SLAVE_LINK_IS_XGMII(slave))
+               return;
 
-       if (!SLAVE_LINK_IS_XGMII(slave)) {
-               netcp_sgmii_reset(sgmii_port_regs, slave->slave_num);
-               netcp_sgmii_config(sgmii_port_regs, slave->slave_num,
-                                  slave->link_interface);
-       }
+       netcp_sgmii_reset(SGMII_BASE(priv, slave->slave_num), slave->slave_num);
+       netcp_sgmii_config(SGMII_BASE(priv, slave->slave_num), slave->slave_num,
+                          slave->link_interface);
 }
 
 static int gbe_slave_open(struct gbe_intf *gbe_intf)
@@ -2652,8 +2637,10 @@ static void init_secondary_ports(struct gbe_priv *gbe_dev,
                        mac_phy_link = true;
 
                slave->open = true;
-               if (gbe_dev->num_slaves >= gbe_dev->max_num_slaves)
+               if (gbe_dev->num_slaves >= gbe_dev->max_num_slaves) {
+                       of_node_put(port);
                        break;
+               }
        }
 
        /* of_phy_connect() is needed only for MAC-PHY interface */
@@ -2997,6 +2984,14 @@ static int set_gbenu_ethss_priv(struct gbe_priv *gbe_dev,
        gbe_dev->switch_regs = regs;
 
        gbe_dev->sgmii_port_regs = gbe_dev->ss_regs + GBENU_SGMII_MODULE_OFFSET;
+
+       /* Although sgmii modules are mem mapped to one contiguous
+        * region on GBENU devices, setting sgmii_port34_regs allows
+        * consistent code when accessing sgmii api
+        */
+       gbe_dev->sgmii_port34_regs = gbe_dev->sgmii_port_regs +
+                                    (2 * GBENU_SGMII_MODULE_SIZE);
+
        gbe_dev->host_port_regs = gbe_dev->switch_regs + GBENU_HOST_PORT_OFFSET;
 
        for (i = 0; i < (gbe_dev->max_num_ports); i++)
@@ -3144,8 +3139,10 @@ static int gbe_probe(struct netcp_device *netcp_device, struct device *dev,
                        continue;
                }
                gbe_dev->num_slaves++;
-               if (gbe_dev->num_slaves >= gbe_dev->max_num_slaves)
+               if (gbe_dev->num_slaves >= gbe_dev->max_num_slaves) {
+                       of_node_put(interface);
                        break;
+               }
        }
        of_node_put(interfaces);
 
index 2f1264b882b9555f02e0b1cb50aa914d13c929fa..d3d094742a7e35a11b97cc6fe64a202ec86f5144 100644 (file)
@@ -17,7 +17,7 @@ if NET_VENDOR_VIA
 
 config VIA_RHINE
        tristate "VIA Rhine support"
-       depends on (PCI || OF_IRQ)
+       depends on PCI || (OF_IRQ && GENERIC_PCI_IOMAP)
        depends on HAS_DMA
        select CRC32
        select MII
index a83263743665411eacb0ca845e23f52db612866c..2b7550c43f7800fe36e54fafacabfcd921c408f4 100644 (file)
@@ -2134,10 +2134,11 @@ static int rhine_rx(struct net_device *dev, int limit)
                        }
 
                        skb_put(skb, pkt_len);
-                       skb->protocol = eth_type_trans(skb, dev);
 
                        rhine_rx_vlan_tag(skb, desc, data_size);
 
+                       skb->protocol = eth_type_trans(skb, dev);
+
                        netif_receive_skb(skb);
 
                        u64_stats_update_begin(&rp->rx_stats.syncp);
index 6008eee01a33a7a9e62918627443874eae56813a..cf468c87ce57e0954fe2d55d953968e64a2db74d 100644 (file)
@@ -828,6 +828,8 @@ static int xemaclite_mdio_setup(struct net_local *lp, struct device *dev)
                if (!phydev)
                        dev_info(dev,
                                 "MDIO of the phy is not registered yet\n");
+               else
+                       put_device(&phydev->dev);
                return 0;
        }
 
index b5f4a78da8283a408cbe030f96d22e0ad4882302..2d3848c9dc35a7f0047fb0189c0669b70dc776dc 100644 (file)
@@ -1011,11 +1011,11 @@ static void fjes_hw_update_zone_task(struct work_struct *work)
                                        set_bit(epidx, &irq_bit);
                                break;
                        }
-               }
-
-               hw->ep_shm_info[epidx].es_status = info[epidx].es_status;
-               hw->ep_shm_info[epidx].zone = info[epidx].zone;
 
+                       hw->ep_shm_info[epidx].es_status =
+                               info[epidx].es_status;
+                       hw->ep_shm_info[epidx].zone = info[epidx].zone;
+               }
                break;
        }
 
index da3259ce7c8d036b3178dbca24030797be5526b9..445071c163cb3b45412af65e58353a7eae26842a 100644 (file)
@@ -126,6 +126,8 @@ static void geneve_rx(struct geneve_sock *gs, struct sk_buff *skb)
        __be32 addr;
        int err;
 
+       iph = ip_hdr(skb); /* outer IP header... */
+
        if (gs->collect_md) {
                static u8 zero_vni[3];
 
@@ -133,7 +135,6 @@ static void geneve_rx(struct geneve_sock *gs, struct sk_buff *skb)
                addr = 0;
        } else {
                vni = gnvh->vni;
-               iph = ip_hdr(skb); /* Still outer IP header... */
                addr = iph->saddr;
        }
 
@@ -178,7 +179,6 @@ static void geneve_rx(struct geneve_sock *gs, struct sk_buff *skb)
 
        skb_reset_network_header(skb);
 
-       iph = ip_hdr(skb); /* Now inner IP header... */
        err = IP_ECN_decapsulate(iph, skb);
 
        if (unlikely(err)) {
@@ -594,14 +594,12 @@ static struct rtable *geneve_get_rt(struct sk_buff *skb,
        rt = ip_route_output_key(geneve->net, fl4);
        if (IS_ERR(rt)) {
                netdev_dbg(dev, "no route to %pI4\n", &fl4->daddr);
-               dev->stats.tx_carrier_errors++;
-               return rt;
+               return ERR_PTR(-ENETUNREACH);
        }
        if (rt->dst.dev == dev) { /* is this necessary? */
                netdev_dbg(dev, "circular route to %pI4\n", &fl4->daddr);
-               dev->stats.collisions++;
                ip_rt_put(rt);
-               return ERR_PTR(-EINVAL);
+               return ERR_PTR(-ELOOP);
        }
        return rt;
 }
@@ -626,12 +624,13 @@ static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev)
        struct geneve_sock *gs = geneve->sock;
        struct ip_tunnel_info *info = NULL;
        struct rtable *rt = NULL;
+       const struct iphdr *iip; /* interior IP header */
+       int err = -EINVAL;
        struct flowi4 fl4;
        __u8 tos, ttl;
        __be16 sport;
        bool udp_csum;
        __be16 df;
-       int err;
 
        if (geneve->collect_md) {
                info = skb_tunnel_info(skb);
@@ -646,13 +645,15 @@ static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev)
        rt = geneve_get_rt(skb, dev, &fl4, info);
        if (IS_ERR(rt)) {
                netdev_dbg(dev, "no route to %pI4\n", &fl4.daddr);
-               dev->stats.tx_carrier_errors++;
+               err = PTR_ERR(rt);
                goto tx_error;
        }
 
        sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
        skb_reset_mac_header(skb);
 
+       iip = ip_hdr(skb);
+
        if (info) {
                const struct ip_tunnel_key *key = &info->key;
                u8 *opts = NULL;
@@ -668,19 +669,16 @@ static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev)
                if (unlikely(err))
                        goto err;
 
-               tos = key->tos;
+               tos = ip_tunnel_ecn_encap(key->tos, iip, skb);
                ttl = key->ttl;
                df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
        } else {
-               const struct iphdr *iip; /* interior IP header */
-
                udp_csum = false;
                err = geneve_build_skb(rt, skb, 0, geneve->vni,
                                       0, NULL, udp_csum);
                if (unlikely(err))
                        goto err;
 
-               iip = ip_hdr(skb);
                tos = ip_tunnel_ecn_encap(fl4.flowi4_tos, iip, skb);
                ttl = geneve->ttl;
                if (!ttl && IN_MULTICAST(ntohl(fl4.daddr)))
@@ -699,10 +697,37 @@ static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev)
 tx_error:
        dev_kfree_skb(skb);
 err:
-       dev->stats.tx_errors++;
+       if (err == -ELOOP)
+               dev->stats.collisions++;
+       else if (err == -ENETUNREACH)
+               dev->stats.tx_carrier_errors++;
+       else
+               dev->stats.tx_errors++;
        return NETDEV_TX_OK;
 }
 
+static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
+{
+       struct ip_tunnel_info *info = skb_tunnel_info(skb);
+       struct geneve_dev *geneve = netdev_priv(dev);
+       struct rtable *rt;
+       struct flowi4 fl4;
+
+       if (ip_tunnel_info_af(info) != AF_INET)
+               return -EINVAL;
+
+       rt = geneve_get_rt(skb, dev, &fl4, info);
+       if (IS_ERR(rt))
+               return PTR_ERR(rt);
+
+       ip_rt_put(rt);
+       info->key.u.ipv4.src = fl4.saddr;
+       info->key.tp_src = udp_flow_src_port(geneve->net, skb,
+                                            1, USHRT_MAX, true);
+       info->key.tp_dst = geneve->dst_port;
+       return 0;
+}
+
 static const struct net_device_ops geneve_netdev_ops = {
        .ndo_init               = geneve_init,
        .ndo_uninit             = geneve_uninit,
@@ -713,6 +738,7 @@ static const struct net_device_ops geneve_netdev_ops = {
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_fill_metadata_dst  = geneve_fill_metadata_dst,
 };
 
 static void geneve_get_drvinfo(struct net_device *dev,
@@ -748,12 +774,8 @@ static void geneve_setup(struct net_device *dev)
        dev->features    |= NETIF_F_RXCSUM;
        dev->features    |= NETIF_F_GSO_SOFTWARE;
 
-       dev->vlan_features = dev->features;
-       dev->features    |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX;
-
        dev->hw_features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
        dev->hw_features |= NETIF_F_GSO_SOFTWARE;
-       dev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX;
 
        netif_keep_dst(dev);
        dev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_NO_QUEUE;
@@ -819,7 +841,7 @@ static struct geneve_dev *geneve_find_dev(struct geneve_net *gn,
 
 static int geneve_configure(struct net *net, struct net_device *dev,
                            __be32 rem_addr, __u32 vni, __u8 ttl, __u8 tos,
-                           __u16 dst_port, bool metadata)
+                           __be16 dst_port, bool metadata)
 {
        struct geneve_net *gn = net_generic(net, geneve_net_id);
        struct geneve_dev *t, *geneve = netdev_priv(dev);
@@ -844,10 +866,10 @@ static int geneve_configure(struct net *net, struct net_device *dev,
 
        geneve->ttl = ttl;
        geneve->tos = tos;
-       geneve->dst_port = htons(dst_port);
+       geneve->dst_port = dst_port;
        geneve->collect_md = metadata;
 
-       t = geneve_find_dev(gn, htons(dst_port), rem_addr, geneve->vni,
+       t = geneve_find_dev(gn, dst_port, rem_addr, geneve->vni,
                            &tun_on_same_port, &tun_collect_md);
        if (t)
                return -EBUSY;
@@ -871,17 +893,17 @@ static int geneve_configure(struct net *net, struct net_device *dev,
 static int geneve_newlink(struct net *net, struct net_device *dev,
                          struct nlattr *tb[], struct nlattr *data[])
 {
-       __u16 dst_port = GENEVE_UDP_PORT;
+       __be16 dst_port = htons(GENEVE_UDP_PORT);
        __u8 ttl = 0, tos = 0;
        bool metadata = false;
-       __be32 rem_addr;
-       __u32 vni;
+       __be32 rem_addr = 0;
+       __u32 vni = 0;
 
-       if (!data[IFLA_GENEVE_ID] || !data[IFLA_GENEVE_REMOTE])
-               return -EINVAL;
+       if (data[IFLA_GENEVE_ID])
+               vni = nla_get_u32(data[IFLA_GENEVE_ID]);
 
-       vni = nla_get_u32(data[IFLA_GENEVE_ID]);
-       rem_addr = nla_get_in_addr(data[IFLA_GENEVE_REMOTE]);
+       if (data[IFLA_GENEVE_REMOTE])
+               rem_addr = nla_get_in_addr(data[IFLA_GENEVE_REMOTE]);
 
        if (data[IFLA_GENEVE_TTL])
                ttl = nla_get_u8(data[IFLA_GENEVE_TTL]);
@@ -890,7 +912,7 @@ static int geneve_newlink(struct net *net, struct net_device *dev,
                tos = nla_get_u8(data[IFLA_GENEVE_TOS]);
 
        if (data[IFLA_GENEVE_PORT])
-               dst_port = nla_get_u16(data[IFLA_GENEVE_PORT]);
+               dst_port = nla_get_be16(data[IFLA_GENEVE_PORT]);
 
        if (data[IFLA_GENEVE_COLLECT_METADATA])
                metadata = true;
@@ -913,7 +935,7 @@ static size_t geneve_get_size(const struct net_device *dev)
                nla_total_size(sizeof(struct in_addr)) + /* IFLA_GENEVE_REMOTE */
                nla_total_size(sizeof(__u8)) +  /* IFLA_GENEVE_TTL */
                nla_total_size(sizeof(__u8)) +  /* IFLA_GENEVE_TOS */
-               nla_total_size(sizeof(__u16)) +  /* IFLA_GENEVE_PORT */
+               nla_total_size(sizeof(__be16)) +  /* IFLA_GENEVE_PORT */
                nla_total_size(0) +      /* IFLA_GENEVE_COLLECT_METADATA */
                0;
 }
@@ -935,7 +957,7 @@ static int geneve_fill_info(struct sk_buff *skb, const struct net_device *dev)
            nla_put_u8(skb, IFLA_GENEVE_TOS, geneve->tos))
                goto nla_put_failure;
 
-       if (nla_put_u16(skb, IFLA_GENEVE_PORT, ntohs(geneve->dst_port)))
+       if (nla_put_be16(skb, IFLA_GENEVE_PORT, geneve->dst_port))
                goto nla_put_failure;
 
        if (geneve->collect_md) {
@@ -975,7 +997,7 @@ struct net_device *geneve_dev_create_fb(struct net *net, const char *name,
        if (IS_ERR(dev))
                return dev;
 
-       err = geneve_configure(net, dev, 0, 0, 0, 0, dst_port, true);
+       err = geneve_configure(net, dev, 0, 0, 0, 0, htons(dst_port), true);
        if (err) {
                free_netdev(dev);
                return ERR_PTR(err);
index 58ae11a14bb6f9ea51f322faaafee10b357ddddf..64bb44d5d8672a2f078a69074a1c9e6e9d4fda27 100644 (file)
@@ -1031,7 +1031,6 @@ static void ali_ircc_fir_change_speed(struct ali_ircc_cb *priv, __u32 baud)
 static void ali_ircc_sir_change_speed(struct ali_ircc_cb *priv, __u32 speed)
 {
        struct ali_ircc_cb *self = priv;
-       unsigned long flags;
        int iobase; 
        int fcr;    /* FIFO control reg */
        int lcr;    /* Line control reg */
@@ -1061,8 +1060,6 @@ static void ali_ircc_sir_change_speed(struct ali_ircc_cb *priv, __u32 speed)
        /* Update accounting for new speed */
        self->io.speed = speed;
 
-       spin_lock_irqsave(&self->lock, flags);
-
        divisor = 115200/speed;
        
        fcr = UART_FCR_ENABLE_FIFO;
@@ -1089,9 +1086,6 @@ static void ali_ircc_sir_change_speed(struct ali_ircc_cb *priv, __u32 speed)
        /* without this, the connection will be broken after come back from FIR speed,
           but with this, the SIR connection is harder to established */
        outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase+UART_MCR);
-       
-       spin_unlock_irqrestore(&self->lock, flags);
-       
 }
 
 static void ali_ircc_change_dongle_speed(struct ali_ircc_cb *priv, int speed)
index edd77342773a8d4ef0713717adfa5bcf6bdf44f7..197c93937c2d577e56cf7fab8dcef07313bf75f4 100644 (file)
@@ -137,7 +137,7 @@ static const struct proto_ops macvtap_socket_ops;
 #define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \
                      NETIF_F_TSO6 | NETIF_F_UFO)
 #define RX_OFFLOADS (NETIF_F_GRO | NETIF_F_LRO)
-#define TAP_FEATURES (NETIF_F_GSO | NETIF_F_SG)
+#define TAP_FEATURES (NETIF_F_GSO | NETIF_F_SG | NETIF_F_FRAGLIST)
 
 static struct macvlan_dev *macvtap_get_vlan_rcu(const struct net_device *dev)
 {
@@ -1111,10 +1111,10 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd,
                return 0;
 
        case TUNSETSNDBUF:
-               if (get_user(u, up))
+               if (get_user(s, sp))
                        return -EFAULT;
 
-               q->sk.sk_sndbuf = u;
+               q->sk.sk_sndbuf = s;
                return 0;
 
        case TUNGETVNETHDRSZ:
index c5ad98ace5d0abeff5d6ef8f3f028e537b241a8e..436972b2a746a23d27bac9ebb4e23d17b6d54715 100644 (file)
@@ -122,6 +122,11 @@ config MICREL_PHY
        ---help---
          Supports the KSZ9021, VSC8201, KS8001 PHYs.
 
+config DP83848_PHY
+       tristate "Driver for Texas Instruments DP83848 PHY"
+       ---help---
+         Supports the DP83848 PHY.
+
 config DP83867_PHY
        tristate "Drivers for Texas Instruments DP83867 Gigabit PHY"
        ---help---
@@ -168,8 +173,6 @@ config MDIO_OCTEON
          busses. It is required by the Octeon and ThunderX ethernet device
          drivers.
 
-         If in doubt, say Y.
-
 config MDIO_SUN4I
        tristate "Allwinner sun4i MDIO interface support"
        depends on ARCH_SUNXI
index 87f079c4b2c7ab16e5577b0b86fdd8509f9b7c8f..b74822463930051f60151beec04c5ccfe0e7bd0b 100644 (file)
@@ -24,6 +24,7 @@ obj-$(CONFIG_MDIO_BITBANG)    += mdio-bitbang.o
 obj-$(CONFIG_MDIO_GPIO)                += mdio-gpio.o
 obj-$(CONFIG_NATIONAL_PHY)     += national.o
 obj-$(CONFIG_DP83640_PHY)      += dp83640.o
+obj-$(CONFIG_DP83848_PHY)      += dp83848.o
 obj-$(CONFIG_DP83867_PHY)      += dp83867.o
 obj-$(CONFIG_STE10XP)          += ste10Xp.o
 obj-$(CONFIG_MICREL_PHY)       += micrel.o
diff --git a/drivers/net/phy/dp83848.c b/drivers/net/phy/dp83848.c
new file mode 100644 (file)
index 0000000..5ce9bef
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Driver for the Texas Instruments DP83848 PHY
+ *
+ * Copyright (C) 2015 Texas Instruments Inc.
+ *
+ * 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.
+ *
+ * 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 <linux/module.h>
+#include <linux/phy.h>
+
+#define DP83848_PHY_ID                 0x20005c90
+
+/* Registers */
+#define DP83848_MICR                   0x11
+#define DP83848_MISR                   0x12
+
+/* MICR Register Fields */
+#define DP83848_MICR_INT_OE            BIT(0) /* Interrupt Output Enable */
+#define DP83848_MICR_INTEN             BIT(1) /* Interrupt Enable */
+
+/* MISR Register Fields */
+#define DP83848_MISR_RHF_INT_EN                BIT(0) /* Receive Error Counter */
+#define DP83848_MISR_FHF_INT_EN                BIT(1) /* False Carrier Counter */
+#define DP83848_MISR_ANC_INT_EN                BIT(2) /* Auto-negotiation complete */
+#define DP83848_MISR_DUP_INT_EN                BIT(3) /* Duplex Status */
+#define DP83848_MISR_SPD_INT_EN                BIT(4) /* Speed status */
+#define DP83848_MISR_LINK_INT_EN       BIT(5) /* Link status */
+#define DP83848_MISR_ED_INT_EN         BIT(6) /* Energy detect */
+#define DP83848_MISR_LQM_INT_EN                BIT(7) /* Link Quality Monitor */
+
+static int dp83848_ack_interrupt(struct phy_device *phydev)
+{
+       int err = phy_read(phydev, DP83848_MISR);
+
+       return err < 0 ? err : 0;
+}
+
+static int dp83848_config_intr(struct phy_device *phydev)
+{
+       int err;
+
+       if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
+               err = phy_write(phydev, DP83848_MICR,
+                               DP83848_MICR_INT_OE |
+                               DP83848_MICR_INTEN);
+               if (err < 0)
+                       return err;
+
+               return phy_write(phydev, DP83848_MISR,
+                                DP83848_MISR_ANC_INT_EN |
+                                DP83848_MISR_DUP_INT_EN |
+                                DP83848_MISR_SPD_INT_EN |
+                                DP83848_MISR_LINK_INT_EN);
+       }
+
+       return phy_write(phydev, DP83848_MICR, 0x0);
+}
+
+static struct mdio_device_id __maybe_unused dp83848_tbl[] = {
+       { DP83848_PHY_ID, 0xfffffff0 },
+       { }
+};
+MODULE_DEVICE_TABLE(mdio, dp83848_tbl);
+
+static struct phy_driver dp83848_driver[] = {
+       {
+               .phy_id         = DP83848_PHY_ID,
+               .phy_id_mask    = 0xfffffff0,
+               .name           = "TI DP83848",
+               .features       = PHY_BASIC_FEATURES,
+               .flags          = PHY_HAS_INTERRUPT,
+
+               .soft_reset     = genphy_soft_reset,
+               .config_init    = genphy_config_init,
+               .suspend        = genphy_suspend,
+               .resume         = genphy_resume,
+               .config_aneg    = genphy_config_aneg,
+               .read_status    = genphy_read_status,
+
+               /* IRQ related */
+               .ack_interrupt  = dp83848_ack_interrupt,
+               .config_intr    = dp83848_config_intr,
+
+               .driver         = { .owner = THIS_MODULE, },
+       },
+};
+module_phy_driver(dp83848_driver);
+
+MODULE_DESCRIPTION("Texas Instruments DP83848 PHY driver");
+MODULE_AUTHOR("Andrew F. Davis <afd@ti.com");
+MODULE_LICENSE("GPL");
index fb1299c6326ec1f388d5c544e4607645274cbb08..e23bf5b90e17325060f4e4900b66ac2c086ec6dd 100644 (file)
@@ -220,7 +220,7 @@ int fixed_phy_update_state(struct phy_device *phydev,
        struct fixed_mdio_bus *fmb = &platform_fmb;
        struct fixed_phy *fp;
 
-       if (!phydev || !phydev->bus)
+       if (!phydev || phydev->bus != fmb->mii_bus)
                return -EINVAL;
 
        list_for_each_entry(fp, &fmb->phys, node) {
index e6897b6a8a53190dd0cea06d863fb88f397fd197..5de8d5827536b1c196b4dabe95f3815964dd0296 100644 (file)
@@ -785,6 +785,7 @@ static int marvell_read_status(struct phy_device *phydev)
        int adv;
        int err;
        int lpa;
+       int lpagb;
        int status = 0;
 
        /* Update the link, but return if there
@@ -802,10 +803,17 @@ static int marvell_read_status(struct phy_device *phydev)
                if (lpa < 0)
                        return lpa;
 
+               lpagb = phy_read(phydev, MII_STAT1000);
+               if (lpagb < 0)
+                       return lpagb;
+
                adv = phy_read(phydev, MII_ADVERTISE);
                if (adv < 0)
                        return adv;
 
+               phydev->lp_advertising = mii_stat1000_to_ethtool_lpa_t(lpagb) |
+                                        mii_lpa_to_ethtool_lpa_t(lpa);
+
                lpa &= adv;
 
                if (status & MII_M1011_PHY_STATUS_FULLDUPLEX)
@@ -853,6 +861,7 @@ static int marvell_read_status(struct phy_device *phydev)
                        phydev->speed = SPEED_10;
 
                phydev->pause = phydev->asym_pause = 0;
+               phydev->lp_advertising = 0;
        }
 
        return 0;
index 6a52a7f0fa0dc5cace471b118a9e989d8c2713ea..4bde5e728fe0a3ef2aa3c0c3934cb97c34d02c49 100644 (file)
@@ -244,6 +244,7 @@ static const struct of_device_id unimac_mdio_ids[] = {
        { .compatible = "brcm,unimac-mdio", },
        { /* sentinel */ },
 };
+MODULE_DEVICE_TABLE(of, unimac_mdio_ids);
 
 static struct platform_driver unimac_mdio_driver = {
        .driver = {
index 7dc21e56a7aa805c42f1a1624a704d807efa08f5..3bc9f03349f3a47d1c724cb50bd05e345f025f3e 100644 (file)
@@ -261,6 +261,7 @@ static const struct of_device_id mdio_gpio_of_match[] = {
        { .compatible = "virtual,mdio-gpio", },
        { /* sentinel */ }
 };
+MODULE_DEVICE_TABLE(of, mdio_gpio_of_match);
 
 static struct platform_driver mdio_gpio_driver = {
        .probe = mdio_gpio_probe,
index 2377c1341172f6ac6fb56eeaf835b7fc577e1593..7fde454fbc4f1762b2c0bb35cf41f60580fd16ed 100644 (file)
@@ -113,12 +113,14 @@ static int mdio_mux_mmioreg_probe(struct platform_device *pdev)
                if (!iprop || len != sizeof(uint32_t)) {
                        dev_err(&pdev->dev, "mdio-mux child node %s is "
                                "missing a 'reg' property\n", np2->full_name);
+                       of_node_put(np2);
                        return -ENODEV;
                }
                if (be32_to_cpup(iprop) & ~s->mask) {
                        dev_err(&pdev->dev, "mdio-mux child node %s has "
                                "a 'reg' value with unmasked bits\n",
                                np2->full_name);
+                       of_node_put(np2);
                        return -ENODEV;
                }
        }
index 4d4d25efc1e10a2b87e3c8ab993ae3ba6167a7dd..908e8d4863429fb6c11f4a625449500f3be36ce1 100644 (file)
@@ -113,18 +113,18 @@ int mdio_mux_init(struct device *dev,
        if (!parent_bus_node)
                return -ENODEV;
 
-       parent_bus = of_mdio_find_bus(parent_bus_node);
-       if (parent_bus == NULL) {
-               ret_val = -EPROBE_DEFER;
-               goto err_parent_bus;
-       }
-
        pb = devm_kzalloc(dev, sizeof(*pb), GFP_KERNEL);
        if (pb == NULL) {
                ret_val = -ENOMEM;
                goto err_parent_bus;
        }
 
+       parent_bus = of_mdio_find_bus(parent_bus_node);
+       if (parent_bus == NULL) {
+               ret_val = -EPROBE_DEFER;
+               goto err_parent_bus;
+       }
+
        pb->switch_data = data;
        pb->switch_fn = switch_fn;
        pb->current_child = -1;
@@ -144,6 +144,7 @@ int mdio_mux_init(struct device *dev,
                        dev_err(dev,
                                "Error: Failed to allocate memory for child\n");
                        ret_val = -ENOMEM;
+                       of_node_put(child_bus_node);
                        break;
                }
                cb->bus_number = v;
@@ -173,6 +174,10 @@ int mdio_mux_init(struct device *dev,
                dev_info(dev, "Version " DRV_VERSION "\n");
                return 0;
        }
+
+       /* balance the reference of_mdio_find_bus() took */
+       put_device(&pb->mii_bus->dev);
+
 err_parent_bus:
        of_node_put(parent_bus_node);
        return ret_val;
@@ -189,6 +194,9 @@ void mdio_mux_uninit(void *mux_handle)
                mdiobus_free(cb->mii_bus);
                cb = cb->next;
        }
+
+       /* balance the reference of_mdio_find_bus() in mdio_mux_init() took */
+       put_device(&pb->mii_bus->dev);
 }
 EXPORT_SYMBOL_GPL(mdio_mux_uninit);
 
index 02a4615b65f87565af9eb32ecad500f33c3cff24..12f44c53cc8ebca7cba92119c26b01b249e31846 100644 (file)
@@ -167,7 +167,9 @@ static int of_mdio_bus_match(struct device *dev, const void *mdio_bus_np)
  * of_mdio_find_bus - Given an mii_bus node, find the mii_bus.
  * @mdio_bus_np: Pointer to the mii_bus.
  *
- * Returns a pointer to the mii_bus, or NULL if none found.
+ * Returns a reference to the mii_bus, or NULL if none found.  The
+ * embedded struct device will have its reference count incremented,
+ * and this must be put once the bus is finished with.
  *
  * Because the association of a device_node and mii_bus is made via
  * of_mdiobus_register(), the mii_bus cannot be found before it is
@@ -234,15 +236,18 @@ static inline void of_mdiobus_link_phydev(struct mii_bus *mdio,
 #endif
 
 /**
- * mdiobus_register - bring up all the PHYs on a given bus and attach them to bus
+ * __mdiobus_register - bring up all the PHYs on a given bus and attach them to bus
  * @bus: target mii_bus
+ * @owner: module containing bus accessor functions
  *
  * Description: Called by a bus driver to bring up all the PHYs
- *   on a given bus, and attach them to the bus.
+ *   on a given bus, and attach them to the bus. Drivers should use
+ *   mdiobus_register() rather than __mdiobus_register() unless they
+ *   need to pass a specific owner module.
  *
  * Returns 0 on success or < 0 on error.
  */
-int mdiobus_register(struct mii_bus *bus)
+int __mdiobus_register(struct mii_bus *bus, struct module *owner)
 {
        int i, err;
 
@@ -253,6 +258,7 @@ int mdiobus_register(struct mii_bus *bus)
        BUG_ON(bus->state != MDIOBUS_ALLOCATED &&
               bus->state != MDIOBUS_UNREGISTERED);
 
+       bus->owner = owner;
        bus->dev.parent = bus->parent;
        bus->dev.class = &mdio_bus_class;
        bus->dev.groups = NULL;
@@ -288,13 +294,16 @@ int mdiobus_register(struct mii_bus *bus)
 
 error:
        while (--i >= 0) {
-               if (bus->phy_map[i])
-                       device_unregister(&bus->phy_map[i]->dev);
+               struct phy_device *phydev = bus->phy_map[i];
+               if (phydev) {
+                       phy_device_remove(phydev);
+                       phy_device_free(phydev);
+               }
        }
        device_del(&bus->dev);
        return err;
 }
-EXPORT_SYMBOL(mdiobus_register);
+EXPORT_SYMBOL(__mdiobus_register);
 
 void mdiobus_unregister(struct mii_bus *bus)
 {
@@ -304,9 +313,11 @@ void mdiobus_unregister(struct mii_bus *bus)
        bus->state = MDIOBUS_UNREGISTERED;
 
        for (i = 0; i < PHY_MAX_ADDR; i++) {
-               if (bus->phy_map[i])
-                       device_unregister(&bus->phy_map[i]->dev);
-               bus->phy_map[i] = NULL;
+               struct phy_device *phydev = bus->phy_map[i];
+               if (phydev) {
+                       phy_device_remove(phydev);
+                       phy_device_free(phydev);
+               }
        }
        device_del(&bus->dev);
 }
index 499185eaf413ba08b1447fbebf1f60080c643329..cf6312fafea545fbc3efb96e8ff6c63b35c7420e 100644 (file)
@@ -514,6 +514,27 @@ static int ksz8873mll_read_status(struct phy_device *phydev)
        return 0;
 }
 
+static int ksz9031_read_status(struct phy_device *phydev)
+{
+       int err;
+       int regval;
+
+       err = genphy_read_status(phydev);
+       if (err)
+               return err;
+
+       /* Make sure the PHY is not broken. Read idle error count,
+        * and reset the PHY if it is maxed out.
+        */
+       regval = phy_read(phydev, MII_STAT1000);
+       if ((regval & 0xFF) == 0xFF) {
+               phy_init_hw(phydev);
+               phydev->link = 0;
+       }
+
+       return 0;
+}
+
 static int ksz8873mll_config_aneg(struct phy_device *phydev)
 {
        return 0;
@@ -772,7 +793,7 @@ static struct phy_driver ksphy_driver[] = {
        .driver_data    = &ksz9021_type,
        .config_init    = ksz9031_config_init,
        .config_aneg    = genphy_config_aneg,
-       .read_status    = genphy_read_status,
+       .read_status    = ksz9031_read_status,
        .ack_interrupt  = kszphy_ack_interrupt,
        .config_intr    = kszphy_config_intr,
        .suspend        = genphy_suspend,
index c0f21112727446a3879584116e2caa80661ace48..f761288abe660b7d49b0a9a7dbd92b11efdbbbba 100644 (file)
@@ -383,6 +383,24 @@ int phy_device_register(struct phy_device *phydev)
 }
 EXPORT_SYMBOL(phy_device_register);
 
+/**
+ * phy_device_remove - Remove a previously registered phy device from the MDIO bus
+ * @phydev: phy_device structure to remove
+ *
+ * This doesn't free the phy_device itself, it merely reverses the effects
+ * of phy_device_register(). Use phy_device_free() to free the device
+ * after calling this function.
+ */
+void phy_device_remove(struct phy_device *phydev)
+{
+       struct mii_bus *bus = phydev->bus;
+       int addr = phydev->addr;
+
+       device_del(&phydev->dev);
+       bus->phy_map[addr] = NULL;
+}
+EXPORT_SYMBOL(phy_device_remove);
+
 /**
  * phy_find_first - finds the first PHY device on the bus
  * @bus: the target MII bus
@@ -578,14 +596,22 @@ EXPORT_SYMBOL(phy_init_hw);
  *     generic driver is used.  The phy_device is given a ptr to
  *     the attaching device, and given a callback for link status
  *     change.  The phy_device is returned to the attaching driver.
+ *     This function takes a reference on the phy device.
  */
 int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
                      u32 flags, phy_interface_t interface)
 {
+       struct mii_bus *bus = phydev->bus;
        struct device *d = &phydev->dev;
-       struct module *bus_module;
        int err;
 
+       if (!try_module_get(bus->owner)) {
+               dev_err(&dev->dev, "failed to get the bus module\n");
+               return -EIO;
+       }
+
+       get_device(d);
+
        /* Assume that if there is no driver, that it doesn't
         * exist, and we should use the genphy driver.
         */
@@ -600,20 +626,13 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
                        err = device_bind_driver(d);
 
                if (err)
-                       return err;
+                       goto error;
        }
 
        if (phydev->attached_dev) {
                dev_err(&dev->dev, "PHY already attached\n");
-               return -EBUSY;
-       }
-
-       /* Increment the bus module reference count */
-       bus_module = phydev->bus->dev.driver ?
-                    phydev->bus->dev.driver->owner : NULL;
-       if (!try_module_get(bus_module)) {
-               dev_err(&dev->dev, "failed to get the bus module\n");
-               return -EIO;
+               err = -EBUSY;
+               goto error;
        }
 
        phydev->attached_dev = dev;
@@ -636,6 +655,11 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
                phy_resume(phydev);
 
        return err;
+
+error:
+       put_device(d);
+       module_put(bus->owner);
+       return err;
 }
 EXPORT_SYMBOL(phy_attach_direct);
 
@@ -677,14 +701,15 @@ EXPORT_SYMBOL(phy_attach);
 /**
  * phy_detach - detach a PHY device from its network device
  * @phydev: target phy_device struct
+ *
+ * This detaches the phy device from its network device and the phy
+ * driver, and drops the reference count taken in phy_attach_direct().
  */
 void phy_detach(struct phy_device *phydev)
 {
+       struct mii_bus *bus;
        int i;
 
-       if (phydev->bus->dev.driver)
-               module_put(phydev->bus->dev.driver->owner);
-
        phydev->attached_dev->phydev = NULL;
        phydev->attached_dev = NULL;
        phy_suspend(phydev);
@@ -700,6 +725,15 @@ void phy_detach(struct phy_device *phydev)
                        break;
                }
        }
+
+       /*
+        * The phydev might go away on the put_device() below, so avoid
+        * a use-after-free bug by reading the underlying bus first.
+        */
+       bus = phydev->bus;
+
+       put_device(&phydev->dev);
+       module_put(bus->owner);
 }
 EXPORT_SYMBOL(phy_detach);
 
index 70b08958763a129fff47ad00a1db130c1334f254..dc2da87709185870f808ef626e8446893c658db6 100644 (file)
@@ -43,16 +43,25 @@ static int smsc_phy_ack_interrupt(struct phy_device *phydev)
 
 static int smsc_phy_config_init(struct phy_device *phydev)
 {
+       int __maybe_unused len;
+       struct device *dev __maybe_unused = &phydev->dev;
+       struct device_node *of_node __maybe_unused = dev->of_node;
        int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
+       int enable_energy = 1;
 
        if (rc < 0)
                return rc;
 
-       /* Enable energy detect mode for this SMSC Transceivers */
-       rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
-                      rc | MII_LAN83C185_EDPWRDOWN);
-       if (rc < 0)
-               return rc;
+       if (of_find_property(of_node, "smsc,disable-energy-detect", &len))
+               enable_energy = 0;
+
+       if (enable_energy) {
+               /* Enable energy detect mode for this SMSC Transceivers */
+               rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
+                              rc | MII_LAN83C185_EDPWRDOWN);
+               if (rc < 0)
+                       return rc;
+       }
 
        return smsc_phy_ack_interrupt(phydev);
 }
index 17cad185169dd28fd3cae12e69d918371fe9d06f..76cad712ddb2c7c6bc2794389380e4e0a862d5f5 100644 (file)
@@ -66,7 +66,6 @@
 #define PHY_ID_VSC8244                 0x000fc6c0
 #define PHY_ID_VSC8514                 0x00070670
 #define PHY_ID_VSC8574                 0x000704a0
-#define PHY_ID_VSC8641                 0x00070431
 #define PHY_ID_VSC8662                 0x00070660
 #define PHY_ID_VSC8221                 0x000fc550
 #define PHY_ID_VSC8211                 0x000fc4b0
@@ -272,18 +271,6 @@ static struct phy_driver vsc82xx_driver[] = {
        .ack_interrupt  = &vsc824x_ack_interrupt,
        .config_intr    = &vsc82xx_config_intr,
        .driver         = { .owner = THIS_MODULE,},
-}, {
-       .phy_id         = PHY_ID_VSC8641,
-       .name           = "Vitesse VSC8641",
-       .phy_id_mask    = 0x000ffff0,
-       .features       = PHY_GBIT_FEATURES,
-       .flags          = PHY_HAS_INTERRUPT,
-       .config_init    = &vsc824x_config_init,
-       .config_aneg    = &vsc82x4_config_aneg,
-       .read_status    = &genphy_read_status,
-       .ack_interrupt  = &vsc824x_ack_interrupt,
-       .config_intr    = &vsc82xx_config_intr,
-       .driver         = { .owner = THIS_MODULE,},
 }, {
        .phy_id         = PHY_ID_VSC8662,
        .name           = "Vitesse VSC8662",
@@ -331,7 +318,6 @@ static struct mdio_device_id __maybe_unused vitesse_tbl[] = {
        { PHY_ID_VSC8244, 0x000fffc0 },
        { PHY_ID_VSC8514, 0x000ffff0 },
        { PHY_ID_VSC8574, 0x000ffff0 },
-       { PHY_ID_VSC8641, 0x000ffff0 },
        { PHY_ID_VSC8662, 0x000ffff0 },
        { PHY_ID_VSC8221, 0x000ffff0 },
        { PHY_ID_VSC8211, 0x000ffff0 },
index 0481daf9201a28eafbdde2798907bc0318a13ed1..ed00446759b2546d9026010d8b5148bc03ae2d95 100644 (file)
@@ -2755,6 +2755,7 @@ static struct ppp *ppp_create_interface(struct net *net, int unit,
         */
        dev_net_set(dev, net);
 
+       rtnl_lock();
        mutex_lock(&pn->all_ppp_mutex);
 
        if (unit < 0) {
@@ -2785,7 +2786,7 @@ static struct ppp *ppp_create_interface(struct net *net, int unit,
        ppp->file.index = unit;
        sprintf(dev->name, "ppp%d", unit);
 
-       ret = register_netdev(dev);
+       ret = register_netdevice(dev);
        if (ret != 0) {
                unit_put(&pn->units_idr, unit);
                netdev_err(ppp->dev, "PPP: couldn't register device %s (%d)\n",
@@ -2797,6 +2798,7 @@ static struct ppp *ppp_create_interface(struct net *net, int unit,
 
        atomic_inc(&ppp_unit_count);
        mutex_unlock(&pn->all_ppp_mutex);
+       rtnl_unlock();
 
        *retp = 0;
        return ppp;
index 3837ae344f63b9d69a5dd958d0e7b7dc202ff316..5e0b43283bce2c4f5251e5c5db982ca679526d07 100644 (file)
@@ -313,7 +313,6 @@ static void pppoe_flush_dev(struct net_device *dev)
                        if (po->pppoe_dev == dev &&
                            sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) {
                                pppox_unbind_sock(sk);
-                               sk->sk_state = PPPOX_ZOMBIE;
                                sk->sk_state_change(sk);
                                po->pppoe_dev = NULL;
                                dev_put(dev);
@@ -590,7 +589,7 @@ static int pppoe_release(struct socket *sock)
 
        po = pppox_sk(sk);
 
-       if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) {
+       if (po->pppoe_dev) {
                dev_put(po->pppoe_dev);
                po->pppoe_dev = NULL;
        }
index 1610b79ae3866725a12f9af8a2ed83255999217a..e66805eeffb45f014a9c61d20e0bd6f3b473098b 100644 (file)
@@ -164,6 +164,7 @@ config USB_NET_AX8817X
            * Aten UC210T
            * ASIX AX88172
            * Billionton Systems, USB2AR
+           * Billionton Systems, GUSB2AM-1G-B
            * Buffalo LUA-U2-KTX
            * Corega FEther USB2-TX
            * D-Link DUB-E100
@@ -583,4 +584,15 @@ config USB_VL600
 
          http://ubuntuforums.org/showpost.php?p=10589647&postcount=17
 
+config USB_NET_CH9200
+       tristate "QingHeng CH9200 USB ethernet support"
+       depends on USB_USBNET
+       select MII
+       help
+         Choose this option if you have a USB ethernet adapter with a QinHeng
+         CH9200 chipset.
+
+         To compile this driver as a module, choose M here: the
+         module will be called ch9200.
+
 endif # USB_NET_DRIVERS
index cf6a0e610a7fcd8665ec93324997ed1db0486f69..b5f04068dbe4859fb9581304c8bd893addaaeb1d 100644 (file)
@@ -38,4 +38,4 @@ obj-$(CONFIG_USB_NET_HUAWEI_CDC_NCM)  += huawei_cdc_ncm.o
 obj-$(CONFIG_USB_VL600)                += lg-vl600.o
 obj-$(CONFIG_USB_NET_QMI_WWAN) += qmi_wwan.o
 obj-$(CONFIG_USB_NET_CDC_MBIM) += cdc_mbim.o
-
+obj-$(CONFIG_USB_NET_CH9200)   += ch9200.o
index 75d6f26729a30e34cdaaf8334a9cc0aaa2a01c82..079069a060a62fdb42cb9dff9acbcd55148277b8 100644 (file)
@@ -91,8 +91,10 @@ int asix_rx_fixup_internal(struct usbnet *dev, struct sk_buff *skb,
                        }
                        rx->ax_skb = netdev_alloc_skb_ip_align(dev->net,
                                                               rx->size);
-                       if (!rx->ax_skb)
+                       if (!rx->ax_skb) {
+                               rx->size = 0;
                                return 0;
+                       }
                }
 
                if (rx->size > dev->net->mtu + ETH_HLEN + VLAN_HLEN) {
index 1173a24feda38c3af236c84acaf8982f39c0e0b1..5cabefc2349438f26cddde0022d52acf6e967116 100644 (file)
@@ -958,6 +958,10 @@ static const struct usb_device_id  products [] = {
        // Billionton Systems, USB2AR
        USB_DEVICE (0x08dd, 0x90ff),
        .driver_info =  (unsigned long) &ax8817x_info,
+}, {
+       // Billionton Systems, GUSB2AM-1G-B
+       USB_DEVICE(0x08dd, 0x0114),
+       .driver_info =  (unsigned long) &ax88178_info,
 }, {
        // ATEN UC210T
        USB_DEVICE (0x0557, 0x2009),
diff --git a/drivers/net/usb/ch9200.c b/drivers/net/usb/ch9200.c
new file mode 100644 (file)
index 0000000..5e151e6
--- /dev/null
@@ -0,0 +1,432 @@
+/*
+ * USB 10M/100M ethernet adapter
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+#include <linux/crc32.h>
+#include <linux/usb/usbnet.h>
+#include <linux/slab.h>
+
+#define CH9200_VID             0x1A86
+#define CH9200_PID_E092                0xE092
+
+#define CTRL_TIMEOUT_MS                1000
+
+#define CONTROL_TIMEOUT_MS 1000
+
+#define REQUEST_READ   0x0E
+#define REQUEST_WRITE  0x0F
+
+/* Address space:
+ * 00-63 : MII
+ * 64-128: MAC
+ *
+ * Note: all accesses must be 16-bit
+ */
+
+#define MAC_REG_CTRL 64
+#define MAC_REG_STATUS 66
+#define MAC_REG_INTERRUPT_MASK 68
+#define MAC_REG_PHY_COMMAND 70
+#define MAC_REG_PHY_DATA 72
+#define MAC_REG_STATION_L 74
+#define MAC_REG_STATION_M 76
+#define MAC_REG_STATION_H 78
+#define MAC_REG_HASH_L 80
+#define MAC_REG_HASH_M1 82
+#define MAC_REG_HASH_M2 84
+#define MAC_REG_HASH_H 86
+#define MAC_REG_THRESHOLD 88
+#define MAC_REG_FIFO_DEPTH 90
+#define MAC_REG_PAUSE 92
+#define MAC_REG_FLOW_CONTROL 94
+
+/* Control register bits
+ *
+ * Note: bits 13 and 15 are reserved
+ */
+#define LOOPBACK               (0x01 << 14)
+#define BASE100X               (0x01 << 12)
+#define MBPS_10                        (0x01 << 11)
+#define DUPLEX_MODE            (0x01 << 10)
+#define PAUSE_FRAME            (0x01 << 9)
+#define PROMISCUOUS            (0x01 << 8)
+#define MULTICAST              (0x01 << 7)
+#define BROADCAST              (0x01 << 6)
+#define HASH                   (0x01 << 5)
+#define APPEND_PAD             (0x01 << 4)
+#define APPEND_CRC             (0x01 << 3)
+#define TRANSMITTER_ACTION     (0x01 << 2)
+#define RECEIVER_ACTION                (0x01 << 1)
+#define DMA_ACTION             (0x01 << 0)
+
+/* Status register bits
+ *
+ * Note: bits 7-15 are reserved
+ */
+#define ALIGNMENT              (0x01 << 6)
+#define FIFO_OVER_RUN          (0x01 << 5)
+#define FIFO_UNDER_RUN         (0x01 << 4)
+#define RX_ERROR               (0x01 << 3)
+#define RX_COMPLETE            (0x01 << 2)
+#define TX_ERROR               (0x01 << 1)
+#define TX_COMPLETE            (0x01 << 0)
+
+/* FIFO depth register bits
+ *
+ * Note: bits 6 and 14 are reserved
+ */
+
+#define ETH_TXBD               (0x01 << 15)
+#define ETN_TX_FIFO_DEPTH      (0x01 << 8)
+#define ETH_RXBD               (0x01 << 7)
+#define ETH_RX_FIFO_DEPTH      (0x01 << 0)
+
+static int control_read(struct usbnet *dev,
+                       unsigned char request, unsigned short value,
+                       unsigned short index, void *data, unsigned short size,
+                       int timeout)
+{
+       unsigned char *buf = NULL;
+       unsigned char request_type;
+       int err = 0;
+
+       if (request == REQUEST_READ)
+               request_type = (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER);
+       else
+               request_type = (USB_DIR_IN | USB_TYPE_VENDOR |
+                               USB_RECIP_DEVICE);
+
+       netdev_dbg(dev->net, "Control_read() index=0x%02x size=%d\n",
+                  index, size);
+
+       buf = kmalloc(size, GFP_KERNEL);
+       if (!buf) {
+               err = -ENOMEM;
+               goto err_out;
+       }
+
+       err = usb_control_msg(dev->udev,
+                             usb_rcvctrlpipe(dev->udev, 0),
+                             request, request_type, value, index, buf, size,
+                             timeout);
+       if (err == size)
+               memcpy(data, buf, size);
+       else if (err >= 0)
+               err = -EINVAL;
+       kfree(buf);
+
+       return err;
+
+err_out:
+       return err;
+}
+
+static int control_write(struct usbnet *dev, unsigned char request,
+                        unsigned short value, unsigned short index,
+                        void *data, unsigned short size, int timeout)
+{
+       unsigned char *buf = NULL;
+       unsigned char request_type;
+       int err = 0;
+
+       if (request == REQUEST_WRITE)
+               request_type = (USB_DIR_OUT | USB_TYPE_VENDOR |
+                               USB_RECIP_OTHER);
+       else
+               request_type = (USB_DIR_OUT | USB_TYPE_VENDOR |
+                               USB_RECIP_DEVICE);
+
+       netdev_dbg(dev->net, "Control_write() index=0x%02x size=%d\n",
+                  index, size);
+
+       if (data) {
+               buf = kmalloc(size, GFP_KERNEL);
+               if (!buf) {
+                       err = -ENOMEM;
+                       goto err_out;
+               }
+               memcpy(buf, data, size);
+       }
+
+       err = usb_control_msg(dev->udev,
+                             usb_sndctrlpipe(dev->udev, 0),
+                             request, request_type, value, index, buf, size,
+                             timeout);
+       if (err >= 0 && err < size)
+               err = -EINVAL;
+       kfree(buf);
+
+       return 0;
+
+err_out:
+       return err;
+}
+
+static int ch9200_mdio_read(struct net_device *netdev, int phy_id, int loc)
+{
+       struct usbnet *dev = netdev_priv(netdev);
+       unsigned char buff[2];
+
+       netdev_dbg(netdev, "ch9200_mdio_read phy_id:%02x loc:%02x\n",
+                  phy_id, loc);
+
+       if (phy_id != 0)
+               return -ENODEV;
+
+       control_read(dev, REQUEST_READ, 0, loc * 2, buff, 0x02,
+                    CONTROL_TIMEOUT_MS);
+
+       return (buff[0] | buff[1] << 8);
+}
+
+static void ch9200_mdio_write(struct net_device *netdev,
+                             int phy_id, int loc, int val)
+{
+       struct usbnet *dev = netdev_priv(netdev);
+       unsigned char buff[2];
+
+       netdev_dbg(netdev, "ch9200_mdio_write() phy_id=%02x loc:%02x\n",
+                  phy_id, loc);
+
+       if (phy_id != 0)
+               return;
+
+       buff[0] = (unsigned char)val;
+       buff[1] = (unsigned char)(val >> 8);
+
+       control_write(dev, REQUEST_WRITE, 0, loc * 2, buff, 0x02,
+                     CONTROL_TIMEOUT_MS);
+}
+
+static int ch9200_link_reset(struct usbnet *dev)
+{
+       struct ethtool_cmd ecmd;
+
+       mii_check_media(&dev->mii, 1, 1);
+       mii_ethtool_gset(&dev->mii, &ecmd);
+
+       netdev_dbg(dev->net, "link_reset() speed:%d duplex:%d\n",
+                  ecmd.speed, ecmd.duplex);
+
+       return 0;
+}
+
+static void ch9200_status(struct usbnet *dev, struct urb *urb)
+{
+       int link;
+       unsigned char *buf;
+
+       if (urb->actual_length < 16)
+               return;
+
+       buf = urb->transfer_buffer;
+       link = !!(buf[0] & 0x01);
+
+       if (link) {
+               netif_carrier_on(dev->net);
+               usbnet_defer_kevent(dev, EVENT_LINK_RESET);
+       } else {
+               netif_carrier_off(dev->net);
+       }
+}
+
+static struct sk_buff *ch9200_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
+                                      gfp_t flags)
+{
+       int i = 0;
+       int len = 0;
+       int tx_overhead = 0;
+
+       tx_overhead = 0x40;
+
+       len = skb->len;
+       if (skb_headroom(skb) < tx_overhead) {
+               struct sk_buff *skb2;
+
+               skb2 = skb_copy_expand(skb, tx_overhead, 0, flags);
+               dev_kfree_skb_any(skb);
+               skb = skb2;
+               if (!skb)
+                       return NULL;
+       }
+
+       __skb_push(skb, tx_overhead);
+       /* usbnet adds padding if length is a multiple of packet size
+        * if so, adjust length value in header
+        */
+       if ((skb->len % dev->maxpacket) == 0)
+               len++;
+
+       skb->data[0] = len;
+       skb->data[1] = len >> 8;
+       skb->data[2] = 0x00;
+       skb->data[3] = 0x80;
+
+       for (i = 4; i < 48; i++)
+               skb->data[i] = 0x00;
+
+       skb->data[48] = len;
+       skb->data[49] = len >> 8;
+       skb->data[50] = 0x00;
+       skb->data[51] = 0x80;
+
+       for (i = 52; i < 64; i++)
+               skb->data[i] = 0x00;
+
+       return skb;
+}
+
+static int ch9200_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+       int len = 0;
+       int rx_overhead = 0;
+
+       rx_overhead = 64;
+
+       if (unlikely(skb->len < rx_overhead)) {
+               dev_err(&dev->udev->dev, "unexpected tiny rx frame\n");
+               return 0;
+       }
+
+       len = (skb->data[skb->len - 16] | skb->data[skb->len - 15] << 8);
+       skb_trim(skb, len);
+
+       return 1;
+}
+
+static int get_mac_address(struct usbnet *dev, unsigned char *data)
+{
+       int err = 0;
+       unsigned char mac_addr[0x06];
+       int rd_mac_len = 0;
+
+       netdev_dbg(dev->net, "get_mac_address:\n\tusbnet VID:%0x PID:%0x\n",
+                  dev->udev->descriptor.idVendor,
+                  dev->udev->descriptor.idProduct);
+
+       memset(mac_addr, 0, sizeof(mac_addr));
+       rd_mac_len = control_read(dev, REQUEST_READ, 0,
+                                 MAC_REG_STATION_L, mac_addr, 0x02,
+                                 CONTROL_TIMEOUT_MS);
+       rd_mac_len += control_read(dev, REQUEST_READ, 0, MAC_REG_STATION_M,
+                                  mac_addr + 2, 0x02, CONTROL_TIMEOUT_MS);
+       rd_mac_len += control_read(dev, REQUEST_READ, 0, MAC_REG_STATION_H,
+                                  mac_addr + 4, 0x02, CONTROL_TIMEOUT_MS);
+       if (rd_mac_len != ETH_ALEN)
+               err = -EINVAL;
+
+       data[0] = mac_addr[5];
+       data[1] = mac_addr[4];
+       data[2] = mac_addr[3];
+       data[3] = mac_addr[2];
+       data[4] = mac_addr[1];
+       data[5] = mac_addr[0];
+
+       return err;
+}
+
+static int ch9200_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+       int retval = 0;
+       unsigned char data[2];
+
+       retval = usbnet_get_endpoints(dev, intf);
+       if (retval)
+               return retval;
+
+       dev->mii.dev = dev->net;
+       dev->mii.mdio_read = ch9200_mdio_read;
+       dev->mii.mdio_write = ch9200_mdio_write;
+       dev->mii.reg_num_mask = 0x1f;
+
+       dev->mii.phy_id_mask = 0x1f;
+
+       dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
+       dev->rx_urb_size = 24 * 64 + 16;
+       mii_nway_restart(&dev->mii);
+
+       data[0] = 0x01;
+       data[1] = 0x0F;
+       retval = control_write(dev, REQUEST_WRITE, 0, MAC_REG_THRESHOLD, data,
+                              0x02, CONTROL_TIMEOUT_MS);
+
+       data[0] = 0xA0;
+       data[1] = 0x90;
+       retval = control_write(dev, REQUEST_WRITE, 0, MAC_REG_FIFO_DEPTH, data,
+                              0x02, CONTROL_TIMEOUT_MS);
+
+       data[0] = 0x30;
+       data[1] = 0x00;
+       retval = control_write(dev, REQUEST_WRITE, 0, MAC_REG_PAUSE, data,
+                              0x02, CONTROL_TIMEOUT_MS);
+
+       data[0] = 0x17;
+       data[1] = 0xD8;
+       retval = control_write(dev, REQUEST_WRITE, 0, MAC_REG_FLOW_CONTROL,
+                              data, 0x02, CONTROL_TIMEOUT_MS);
+
+       /* Undocumented register */
+       data[0] = 0x01;
+       data[1] = 0x00;
+       retval = control_write(dev, REQUEST_WRITE, 0, 254, data, 0x02,
+                              CONTROL_TIMEOUT_MS);
+
+       data[0] = 0x5F;
+       data[1] = 0x0D;
+       retval = control_write(dev, REQUEST_WRITE, 0, MAC_REG_CTRL, data, 0x02,
+                              CONTROL_TIMEOUT_MS);
+
+       retval = get_mac_address(dev, dev->net->dev_addr);
+
+       return retval;
+}
+
+static const struct driver_info ch9200_info = {
+       .description = "CH9200 USB to Network Adaptor",
+       .flags = FLAG_ETHER,
+       .bind = ch9200_bind,
+       .rx_fixup = ch9200_rx_fixup,
+       .tx_fixup = ch9200_tx_fixup,
+       .status = ch9200_status,
+       .link_reset = ch9200_link_reset,
+       .reset = ch9200_link_reset,
+};
+
+static const struct usb_device_id ch9200_products[] = {
+       {
+        USB_DEVICE(0x1A86, 0xE092),
+        .driver_info = (unsigned long)&ch9200_info,
+        },
+       {},
+};
+
+MODULE_DEVICE_TABLE(usb, ch9200_products);
+
+static struct usb_driver ch9200_driver = {
+       .name = "ch9200",
+       .id_table = ch9200_products,
+       .probe = usbnet_probe,
+       .disconnect = usbnet_disconnect,
+       .suspend = usbnet_suspend,
+       .resume = usbnet_resume,
+};
+
+module_usb_driver(ch9200_driver);
+
+MODULE_DESCRIPTION("QinHeng CH9200 USB Network device");
+MODULE_LICENSE("GPL");
index 355842b85ee906a434477b325f32199ec315eae8..2a7c1be23c4f2aea38e2ec99384be91e7f9d0f62 100644 (file)
@@ -765,6 +765,10 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x1199, 0x9056, 8)},    /* Sierra Wireless Modem */
        {QMI_FIXED_INTF(0x1199, 0x9057, 8)},
        {QMI_FIXED_INTF(0x1199, 0x9061, 8)},    /* Sierra Wireless Modem */
+       {QMI_FIXED_INTF(0x1199, 0x9070, 8)},    /* Sierra Wireless MC74xx/EM74xx */
+       {QMI_FIXED_INTF(0x1199, 0x9070, 10)},   /* Sierra Wireless MC74xx/EM74xx */
+       {QMI_FIXED_INTF(0x1199, 0x9071, 8)},    /* Sierra Wireless MC74xx/EM74xx */
+       {QMI_FIXED_INTF(0x1199, 0x9071, 10)},   /* Sierra Wireless MC74xx/EM74xx */
        {QMI_FIXED_INTF(0x1bbb, 0x011e, 4)},    /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */
        {QMI_FIXED_INTF(0x1bbb, 0x0203, 2)},    /* Alcatel L800MA */
        {QMI_FIXED_INTF(0x2357, 0x0201, 4)},    /* TP-LINK HSUPA Modem MA180 */
index e7094fbd75685998bb5ee492367e686c133a2e15..488c6f50df736968cee60af48d0360924a9f2e2b 100644 (file)
@@ -193,7 +193,8 @@ static netdev_tx_t vrf_process_v4_outbound(struct sk_buff *skb,
                .flowi4_oif = vrf_dev->ifindex,
                .flowi4_iif = LOOPBACK_IFINDEX,
                .flowi4_tos = RT_TOS(ip4h->tos),
-               .flowi4_flags = FLOWI_FLAG_ANYSRC | FLOWI_FLAG_VRFSRC,
+               .flowi4_flags = FLOWI_FLAG_ANYSRC | FLOWI_FLAG_VRFSRC |
+                               FLOWI_FLAG_SKIP_NH_OIF,
                .daddr = ip4h->daddr,
        };
 
index cf8b7f0473b3985af3c6afc68ecf856e704fbc16..c1587ece28cfffeb3c7c3011bf087215edb77662 100644 (file)
@@ -2337,6 +2337,46 @@ static int vxlan_change_mtu(struct net_device *dev, int new_mtu)
        return 0;
 }
 
+static int egress_ipv4_tun_info(struct net_device *dev, struct sk_buff *skb,
+                               struct ip_tunnel_info *info,
+                               __be16 sport, __be16 dport)
+{
+       struct vxlan_dev *vxlan = netdev_priv(dev);
+       struct rtable *rt;
+       struct flowi4 fl4;
+
+       memset(&fl4, 0, sizeof(fl4));
+       fl4.flowi4_tos = RT_TOS(info->key.tos);
+       fl4.flowi4_mark = skb->mark;
+       fl4.flowi4_proto = IPPROTO_UDP;
+       fl4.daddr = info->key.u.ipv4.dst;
+
+       rt = ip_route_output_key(vxlan->net, &fl4);
+       if (IS_ERR(rt))
+               return PTR_ERR(rt);
+       ip_rt_put(rt);
+
+       info->key.u.ipv4.src = fl4.saddr;
+       info->key.tp_src = sport;
+       info->key.tp_dst = dport;
+       return 0;
+}
+
+static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
+{
+       struct vxlan_dev *vxlan = netdev_priv(dev);
+       struct ip_tunnel_info *info = skb_tunnel_info(skb);
+       __be16 sport, dport;
+
+       sport = udp_flow_src_port(dev_net(dev), skb, vxlan->cfg.port_min,
+                                 vxlan->cfg.port_max, true);
+       dport = info->key.tp_dst ? : vxlan->cfg.dst_port;
+
+       if (ip_tunnel_info_af(info) == AF_INET)
+               return egress_ipv4_tun_info(dev, skb, info, sport, dport);
+       return -EINVAL;
+}
+
 static const struct net_device_ops vxlan_netdev_ops = {
        .ndo_init               = vxlan_init,
        .ndo_uninit             = vxlan_uninit,
@@ -2351,6 +2391,7 @@ static const struct net_device_ops vxlan_netdev_ops = {
        .ndo_fdb_add            = vxlan_fdb_add,
        .ndo_fdb_del            = vxlan_fdb_delete,
        .ndo_fdb_dump           = vxlan_fdb_dump,
+       .ndo_fill_metadata_dst  = vxlan_fill_metadata_dst,
 };
 
 /* Info for udev, that this is a virtual tunnel endpoint */
@@ -2392,10 +2433,6 @@ static void vxlan_setup(struct net_device *dev)
 
        eth_hw_addr_random(dev);
        ether_setup(dev);
-       if (vxlan->default_dst.remote_ip.sa.sa_family == AF_INET6)
-               dev->needed_headroom = ETH_HLEN + VXLAN6_HEADROOM;
-       else
-               dev->needed_headroom = ETH_HLEN + VXLAN_HEADROOM;
 
        dev->netdev_ops = &vxlan_netdev_ops;
        dev->destructor = free_netdev;
@@ -2640,8 +2677,11 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev,
                dst->remote_ip.sa.sa_family = AF_INET;
 
        if (dst->remote_ip.sa.sa_family == AF_INET6 ||
-           vxlan->cfg.saddr.sa.sa_family == AF_INET6)
+           vxlan->cfg.saddr.sa.sa_family == AF_INET6) {
+               if (!IS_ENABLED(CONFIG_IPV6))
+                       return -EPFNOSUPPORT;
                use_ipv6 = true;
+       }
 
        if (conf->remote_ifindex) {
                struct net_device *lowerdev
@@ -2670,8 +2710,12 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev,
 
                dev->needed_headroom = lowerdev->hard_header_len +
                                       (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM);
-       } else if (use_ipv6)
+       } else if (use_ipv6) {
                vxlan->flags |= VXLAN_F_IPV6;
+               dev->needed_headroom = ETH_HLEN + VXLAN6_HEADROOM;
+       } else {
+               dev->needed_headroom = ETH_HLEN + VXLAN_HEADROOM;
+       }
 
        memcpy(&vxlan->cfg, conf, sizeof(*conf));
        if (!vxlan->cfg.dst_port)
@@ -2742,11 +2786,10 @@ static int vxlan_newlink(struct net *src_net, struct net_device *dev,
        struct vxlan_config conf;
        int err;
 
-       if (!data[IFLA_VXLAN_ID])
-               return -EINVAL;
-
        memset(&conf, 0, sizeof(conf));
-       conf.vni = nla_get_u32(data[IFLA_VXLAN_ID]);
+
+       if (data[IFLA_VXLAN_ID])
+               conf.vni = nla_get_u32(data[IFLA_VXLAN_ID]);
 
        if (data[IFLA_VXLAN_GROUP]) {
                conf.remote_ip.sin.sin_addr.s_addr = nla_get_in_addr(data[IFLA_VXLAN_GROUP]);
index 23afcda2de967637d73c7039d0f2cdb5f3b777ff..678d72af4a9df73976b7513d9af17888bc1ef7d1 100644 (file)
@@ -337,7 +337,7 @@ enum ath10k_hw_rate_cck {
 #define TARGET_10X_MAX_FRAG_ENTRIES            0
 
 /* 10.2 parameters */
-#define TARGET_10_2_DMA_BURST_SIZE             1
+#define TARGET_10_2_DMA_BURST_SIZE             0
 
 /* Target specific defines for WMI-TLV firmware */
 #define TARGET_TLV_NUM_VDEVS                   4
@@ -391,7 +391,7 @@ enum ath10k_hw_rate_cck {
 
 #define TARGET_10_4_TX_DBG_LOG_SIZE            1024
 #define TARGET_10_4_NUM_WDS_ENTRIES            32
-#define TARGET_10_4_DMA_BURST_SIZE             1
+#define TARGET_10_4_DMA_BURST_SIZE             0
 #define TARGET_10_4_MAC_AGGR_DELIM             0
 #define TARGET_10_4_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK 1
 #define TARGET_10_4_VOW_CONFIG                 0
index 6e473fa4b13cae0df30a33fd9162729afaf76f6b..12241b1c57cd28023d0278c57f347457583bc017 100644 (file)
@@ -715,6 +715,7 @@ static bool check_device_tree(struct ath6kl *ar)
                                   board_filename, ret);
                        continue;
                }
+               of_node_put(node);
                return true;
        }
        return false;
index 57f95f2dca5b072ac294b2c76122ec1b952a2a80..90eb75012e4f4818a03481d98cb9b137a89393fa 100644 (file)
@@ -880,6 +880,7 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
        hw->max_rate_tries = 10;
        hw->sta_data_size = sizeof(struct ath_node);
        hw->vif_data_size = sizeof(struct ath_vif);
+       hw->extra_tx_headroom = 4;
 
        hw->wiphy->available_antennas_rx = BIT(ah->caps.max_rxchains) - 1;
        hw->wiphy->available_antennas_tx = BIT(ah->caps.max_txchains) - 1;
index 28490702124a0da53bb2834f1ca880a452d6523b..71d3e9adbf3c02b4d5ff50843a2b4b06cd96b6a5 100644 (file)
@@ -120,6 +120,7 @@ MODULE_PARM_DESC(allhwsupport, "Enable support for all hardware (even it if over
 #ifdef CONFIG_B43_BCMA
 static const struct bcma_device_id b43_bcma_tbl[] = {
        BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x11, BCMA_ANY_CLASS),
+       BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x15, BCMA_ANY_CLASS),
        BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x17, BCMA_ANY_CLASS),
        BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x18, BCMA_ANY_CLASS),
        BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x1C, BCMA_ANY_CLASS),
index ab45819c1fbbf6d0080813c26090bb095082672d..e18629a16fb0260dff9b3486c572f4bfd2166fcd 100644 (file)
@@ -1020,7 +1020,7 @@ static void iwlagn_wowlan_program_keys(struct ieee80211_hw *hw,
                        u8 *pn = seq.ccmp.pn;
 
                        ieee80211_get_key_rx_seq(key, i, &seq);
-                       aes_sc->pn = cpu_to_le64(
+                       aes_sc[i].pn = cpu_to_le64(
                                        (u64)pn[5] |
                                        ((u64)pn[4] << 8) |
                                        ((u64)pn[3] << 16) |
index 6951aba620eb74a13f6fc2c2da36a043272d8a43..3fb327d5a911aeba53e4ac71ad6bb2ad419d06b0 100644 (file)
@@ -348,6 +348,6 @@ const struct iwl_cfg iwl7265d_n_cfg = {
 };
 
 MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
-MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL3160_UCODE_API_OK));
+MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
 MODULE_FIRMWARE(IWL7265_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
 MODULE_FIRMWARE(IWL7265D_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
index 04264e417c1c644e2b362e9bf29760489cfcae4f..576187611e614adc3a92ca50c4e1f2ab3a7bb7e1 100644 (file)
@@ -274,18 +274,13 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
                break;
        case WLAN_CIPHER_SUITE_CCMP:
                if (sta) {
-                       u8 *pn = seq.ccmp.pn;
+                       u64 pn64;
 
                        aes_sc = data->rsc_tsc->all_tsc_rsc.aes.unicast_rsc;
                        aes_tx_sc = &data->rsc_tsc->all_tsc_rsc.aes.tsc;
 
-                       ieee80211_get_key_tx_seq(key, &seq);
-                       aes_tx_sc->pn = cpu_to_le64((u64)pn[5] |
-                                                   ((u64)pn[4] << 8) |
-                                                   ((u64)pn[3] << 16) |
-                                                   ((u64)pn[2] << 24) |
-                                                   ((u64)pn[1] << 32) |
-                                                   ((u64)pn[0] << 40));
+                       pn64 = atomic64_read(&key->tx_pn);
+                       aes_tx_sc->pn = cpu_to_le64(pn64);
                } else {
                        aes_sc = data->rsc_tsc->all_tsc_rsc.aes.multicast_rsc;
                }
@@ -298,12 +293,12 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
                        u8 *pn = seq.ccmp.pn;
 
                        ieee80211_get_key_rx_seq(key, i, &seq);
-                       aes_sc->pn = cpu_to_le64((u64)pn[5] |
-                                                ((u64)pn[4] << 8) |
-                                                ((u64)pn[3] << 16) |
-                                                ((u64)pn[2] << 24) |
-                                                ((u64)pn[1] << 32) |
-                                                ((u64)pn[0] << 40));
+                       aes_sc[i].pn = cpu_to_le64((u64)pn[5] |
+                                                  ((u64)pn[4] << 8) |
+                                                  ((u64)pn[3] << 16) |
+                                                  ((u64)pn[2] << 24) |
+                                                  ((u64)pn[1] << 32) |
+                                                  ((u64)pn[0] << 40));
                }
                data->use_rsc_tsc = true;
                break;
@@ -1453,15 +1448,15 @@ static void iwl_mvm_d3_update_gtks(struct ieee80211_hw *hw,
 
                switch (key->cipher) {
                case WLAN_CIPHER_SUITE_CCMP:
-                       iwl_mvm_aes_sc_to_seq(&sc->aes.tsc, &seq);
                        iwl_mvm_set_aes_rx_seq(sc->aes.unicast_rsc, key);
+                       atomic64_set(&key->tx_pn, le64_to_cpu(sc->aes.tsc.pn));
                        break;
                case WLAN_CIPHER_SUITE_TKIP:
                        iwl_mvm_tkip_sc_to_seq(&sc->tkip.tsc, &seq);
                        iwl_mvm_set_tkip_rx_seq(sc->tkip.unicast_rsc, key);
+                       ieee80211_set_key_tx_seq(key, &seq);
                        break;
                }
-               ieee80211_set_key_tx_seq(key, &seq);
 
                /* that's it for this key */
                return;
index 4a0ce83315bdd212d1714956af8900ea271f62b6..5c7f7cc9ffcc2aa1d81cbf1ff5b2d33f46133727 100644 (file)
@@ -703,7 +703,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
         * abort after reading the nvm in case RF Kill is on, we will complete
         * the init seq later when RF kill will switch to off
         */
-       if (iwl_mvm_is_radio_killed(mvm)) {
+       if (iwl_mvm_is_radio_hw_killed(mvm)) {
                IWL_DEBUG_RF_KILL(mvm,
                                  "jump over all phy activities due to RF kill\n");
                iwl_remove_notification(&mvm->notif_wait, &calib_wait);
@@ -736,7 +736,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
        ret = iwl_wait_notification(&mvm->notif_wait, &calib_wait,
                        MVM_UCODE_CALIB_TIMEOUT);
 
-       if (ret && iwl_mvm_is_radio_killed(mvm)) {
+       if (ret && iwl_mvm_is_radio_hw_killed(mvm)) {
                IWL_DEBUG_RF_KILL(mvm, "RFKILL while calibrating.\n");
                ret = 1;
        }
index aa8c2b7f23c73862f0526f109ad647cc0c80a259..7c2944a72470b92acdca39a6f7c13b845b34842a 100644 (file)
@@ -2388,6 +2388,7 @@ static void iwl_mvm_stop_ap_ibss(struct ieee80211_hw *hw,
                iwl_mvm_remove_time_event(mvm, mvmvif,
                                          &mvmvif->time_event_data);
                RCU_INIT_POINTER(mvm->csa_vif, NULL);
+               mvmvif->csa_countdown = false;
        }
 
        if (rcu_access_pointer(mvm->csa_tx_blocked_vif) == vif) {
index b95a07ec9e362bf031f960dee35dc52c97221ed0..c754051a4ceacf138d4e6399c9cc679d8a9979c0 100644 (file)
@@ -860,6 +860,11 @@ static inline bool iwl_mvm_is_radio_killed(struct iwl_mvm *mvm)
               test_bit(IWL_MVM_STATUS_HW_CTKILL, &mvm->status);
 }
 
+static inline bool iwl_mvm_is_radio_hw_killed(struct iwl_mvm *mvm)
+{
+       return test_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status);
+}
+
 /* Must be called with rcu_read_lock() held and it can only be
  * released when mvmsta is not needed anymore.
  */
index a37de3f410a01e0b594f41d43bfda4360273e324..f0cb092f980ec26b26e9ca3c6cadf813f39de853 100644 (file)
@@ -590,6 +590,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
        ieee80211_unregister_hw(mvm->hw);
        iwl_mvm_leds_exit(mvm);
  out_free:
+       flush_delayed_work(&mvm->fw_dump_wk);
        iwl_phy_db_free(mvm->phy_db);
        kfree(mvm->scan_cmd);
        if (!cfg->no_power_up_nic_in_init || !mvm->nvm_file_name)
index b0825c402c732c0514637b3b21b26288a7275444..644b58bc5226c52b3cdee0a24b9a392c25e8ac02 100644 (file)
@@ -414,6 +414,11 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
        {IWL_PCI_DEVICE(0x095A, 0x5590, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095B, 0x5290, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x5490, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5F10, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095B, 0x5212, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095B, 0x520A, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x9000, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x9400, iwl7265_2ac_cfg)},
 
 /* 8000 Series */
        {IWL_PCI_DEVICE(0x24F3, 0x0010, iwl8260_2ac_cfg)},
index 5932306084fd305a6f45ccf03d8957b771eaaa13..bf9afbf46c1bbbc1220bad06e429d2622a1f9f58 100644 (file)
@@ -1114,6 +1114,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
        { USB_DEVICE(0x0db0, 0x871c) },
        { USB_DEVICE(0x0db0, 0x899a) },
        /* Ovislink */
+       { USB_DEVICE(0x1b75, 0x3070) },
        { USB_DEVICE(0x1b75, 0x3071) },
        { USB_DEVICE(0x1b75, 0x3072) },
        { USB_DEVICE(0x1b75, 0xa200) },
index d4567d12e07ebd13f17f0097baeec41a25702d31..5da6703942d9dd08017d896070404fdbe29a96e4 100644 (file)
@@ -247,6 +247,8 @@ struct rtl_pci {
        /* MSI support */
        bool msi_support;
        bool using_msi;
+       /* interrupt clear before set */
+       bool int_clear;
 };
 
 struct mp_adapter {
index b7f18e2155eb18358cf4d4f9f3f82774f9b6f522..6e9418ed90c289bee5b7f2dfc478f847dfc7ca68 100644 (file)
@@ -2253,11 +2253,28 @@ void rtl8821ae_set_qos(struct ieee80211_hw *hw, int aci)
        }
 }
 
+static void rtl8821ae_clear_interrupt(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       u32 tmp = rtl_read_dword(rtlpriv, REG_HISR);
+
+       rtl_write_dword(rtlpriv, REG_HISR, tmp);
+
+       tmp = rtl_read_dword(rtlpriv, REG_HISRE);
+       rtl_write_dword(rtlpriv, REG_HISRE, tmp);
+
+       tmp = rtl_read_dword(rtlpriv, REG_HSISR);
+       rtl_write_dword(rtlpriv, REG_HSISR, tmp);
+}
+
 void rtl8821ae_enable_interrupt(struct ieee80211_hw *hw)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 
+       if (!rtlpci->int_clear)
+               rtl8821ae_clear_interrupt(hw);/*clear it here first*/
+
        rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF);
        rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF);
        rtlpci->irq_enabled = true;
index a4988121e1ab6a20bad5ad9b5934c166a41f36d6..8ee141a55bc5cc6b566e79dde58cdb05583e7fdf 100644 (file)
@@ -96,6 +96,7 @@ int rtl8821ae_init_sw_vars(struct ieee80211_hw *hw)
 
        rtl8821ae_bt_reg_init(hw);
        rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support;
+       rtlpci->int_clear = rtlpriv->cfg->mod_params->int_clear;
        rtlpriv->btcoexist.btc_ops = rtl_btc_get_ops_pointer();
 
        rtlpriv->dm.dm_initialgain_enable = 1;
@@ -167,6 +168,7 @@ int rtl8821ae_init_sw_vars(struct ieee80211_hw *hw)
        rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps;
        rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps;
        rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support;
+       rtlpci->msi_support = rtlpriv->cfg->mod_params->int_clear;
        if (rtlpriv->cfg->mod_params->disable_watchdog)
                pr_info("watchdog disabled\n");
        rtlpriv->psc.reg_fwctrl_lps = 3;
@@ -308,6 +310,7 @@ static struct rtl_mod_params rtl8821ae_mod_params = {
        .swctrl_lps = false,
        .fwctrl_lps = true,
        .msi_support = true,
+       .int_clear = true,
        .debug = DBG_EMERG,
        .disable_watchdog = 0,
 };
@@ -437,6 +440,7 @@ module_param_named(fwlps, rtl8821ae_mod_params.fwctrl_lps, bool, 0444);
 module_param_named(msi, rtl8821ae_mod_params.msi_support, bool, 0444);
 module_param_named(disable_watchdog, rtl8821ae_mod_params.disable_watchdog,
                   bool, 0444);
+module_param_named(int_clear, rtl8821ae_mod_params.int_clear, bool, 0444);
 MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n");
 MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n");
 MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n");
@@ -444,6 +448,7 @@ MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n");
 MODULE_PARM_DESC(msi, "Set to 1 to use MSI interrupts mode (default 1)\n");
 MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)");
 MODULE_PARM_DESC(disable_watchdog, "Set to 1 to disable the watchdog (default 0)\n");
+MODULE_PARM_DESC(int_clear, "Set to 1 to disable interrupt clear before set (default 0)\n");
 
 static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume);
 
index b90ca618b123209a1724bc808c4fdfe8ea330a69..4544752a2ba83ca173f7cb4f14abc72538b73beb 100644 (file)
@@ -2249,6 +2249,9 @@ struct rtl_mod_params {
 
        /* default 0: 1 means disable */
        bool disable_watchdog;
+
+       /* default 0: 1 means do not disable interrupts */
+       bool int_clear;
 };
 
 struct rtl_hal_usbint_cfg {
index 929a6e7e5ecfe9249569c0059516e531fb0b79eb..56ebd8267386e6a91cabf506962e15f5d83531ec 100644 (file)
@@ -788,6 +788,12 @@ static void connect(struct backend_info *be)
        /* Use the number of queues requested by the frontend */
        be->vif->queues = vzalloc(requested_num_queues *
                                  sizeof(struct xenvif_queue));
+       if (!be->vif->queues) {
+               xenbus_dev_fatal(dev, -ENOMEM,
+                                "allocating queues");
+               return;
+       }
+
        be->vif->num_queues = requested_num_queues;
        be->vif->stalled_queues = requested_num_queues;
 
index f821a97d78278feed765d08d886a4665d8795bd5..6febc053a37febc069d241e6811d904f18890f45 100644 (file)
@@ -1706,19 +1706,19 @@ static void xennet_destroy_queues(struct netfront_info *info)
 }
 
 static int xennet_create_queues(struct netfront_info *info,
-                               unsigned int num_queues)
+                               unsigned int *num_queues)
 {
        unsigned int i;
        int ret;
 
-       info->queues = kcalloc(num_queues, sizeof(struct netfront_queue),
+       info->queues = kcalloc(*num_queues, sizeof(struct netfront_queue),
                               GFP_KERNEL);
        if (!info->queues)
                return -ENOMEM;
 
        rtnl_lock();
 
-       for (i = 0; i < num_queues; i++) {
+       for (i = 0; i < *num_queues; i++) {
                struct netfront_queue *queue = &info->queues[i];
 
                queue->id = i;
@@ -1728,7 +1728,7 @@ static int xennet_create_queues(struct netfront_info *info,
                if (ret < 0) {
                        dev_warn(&info->netdev->dev,
                                 "only created %d queues\n", i);
-                       num_queues = i;
+                       *num_queues = i;
                        break;
                }
 
@@ -1738,11 +1738,11 @@ static int xennet_create_queues(struct netfront_info *info,
                        napi_enable(&queue->napi);
        }
 
-       netif_set_real_num_tx_queues(info->netdev, num_queues);
+       netif_set_real_num_tx_queues(info->netdev, *num_queues);
 
        rtnl_unlock();
 
-       if (num_queues == 0) {
+       if (*num_queues == 0) {
                dev_err(&info->netdev->dev, "no queues\n");
                return -EINVAL;
        }
@@ -1788,7 +1788,7 @@ static int talk_to_netback(struct xenbus_device *dev,
        if (info->queues)
                xennet_destroy_queues(info);
 
-       err = xennet_create_queues(info, num_queues);
+       err = xennet_create_queues(info, &num_queues);
        if (err < 0)
                goto destroy_ring;
 
index 59ad54a63d9fa98fcd584a68c7dbb8a4aa863d18..cb477518dd0e4d397ede8ccc83ffe2f29ceb02a6 100644 (file)
@@ -128,13 +128,13 @@ static ssize_t namespace_store(struct device *dev,
        struct nd_btt *nd_btt = to_nd_btt(dev);
        ssize_t rc;
 
-       nvdimm_bus_lock(dev);
        device_lock(dev);
+       nvdimm_bus_lock(dev);
        rc = nd_namespace_store(dev, &nd_btt->ndns, buf, len);
        dev_dbg(dev, "%s: result: %zd wrote: %s%s", __func__,
                        rc, buf, buf[len - 1] == '\n' ? "" : "\n");
-       device_unlock(dev);
        nvdimm_bus_unlock(dev);
+       device_unlock(dev);
 
        return rc;
 }
index 3fd7d0d81a470b4cff54b093b0c24c6d14c376b5..71805a1aa0f3e5f002ee5d26339c53d49aadf951 100644 (file)
@@ -148,13 +148,13 @@ static ssize_t namespace_store(struct device *dev,
        struct nd_pfn *nd_pfn = to_nd_pfn(dev);
        ssize_t rc;
 
-       nvdimm_bus_lock(dev);
        device_lock(dev);
+       nvdimm_bus_lock(dev);
        rc = nd_namespace_store(dev, &nd_pfn->ndns, buf, len);
        dev_dbg(dev, "%s: result: %zd wrote: %s%s", __func__,
                        rc, buf, buf[len - 1] == '\n' ? "" : "\n");
-       device_unlock(dev);
        nvdimm_bus_unlock(dev);
+       device_unlock(dev);
 
        return rc;
 }
index b9525385c0dc35532ceaed6087c3f36ea2697ae0..0ba6a978f227e76a4b0c27046e2736d43cf37e45 100644 (file)
@@ -92,6 +92,8 @@ static int pmem_rw_page(struct block_device *bdev, sector_t sector,
        struct pmem_device *pmem = bdev->bd_disk->private_data;
 
        pmem_do_bvec(pmem, page, PAGE_CACHE_SIZE, 0, rw, sector);
+       if (rw & WRITE)
+               wmb_pmem();
        page_endio(page, rw & WRITE, 0);
 
        return 0;
index d3c6676b3c0cafbaa996c1f60d1c21adb0f20b21..6fd4e5a5ef4a495bbd412ee33b931f4fb3a8a24f 100644 (file)
@@ -67,7 +67,7 @@ static ssize_t bin_attr_nvmem_read(struct file *filp, struct kobject *kobj,
        int rc;
 
        /* Stop the user from reading */
-       if (pos > nvmem->size)
+       if (pos >= nvmem->size)
                return 0;
 
        if (pos + count > nvmem->size)
@@ -92,7 +92,7 @@ static ssize_t bin_attr_nvmem_write(struct file *filp, struct kobject *kobj,
        int rc;
 
        /* Stop the user from writing */
-       if (pos > nvmem->size)
+       if (pos >= nvmem->size)
                return 0;
 
        if (pos + count > nvmem->size)
@@ -825,7 +825,7 @@ static int __nvmem_cell_read(struct nvmem_device *nvmem,
                return rc;
 
        /* shift bits in-place */
-       if (cell->bit_offset || cell->bit_offset)
+       if (cell->bit_offset || cell->nbits)
                nvmem_shift_read_buffer_in_place(cell, buf);
 
        *len = cell->bytes;
@@ -938,7 +938,7 @@ int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len)
        rc = regmap_raw_write(nvmem->regmap, cell->offset, buf, cell->bytes);
 
        /* free the tmp buffer */
-       if (cell->bit_offset)
+       if (cell->bit_offset || cell->nbits)
                kfree(buf);
 
        if (IS_ERR_VALUE(rc))
index 14777dd5212d29d10c672a18c8b85c17fdcdceb4..cfa3b85064dd233a463b1556742274d960e4f47b 100644 (file)
@@ -103,7 +103,7 @@ static int sunxi_sid_probe(struct platform_device *pdev)
        struct nvmem_device *nvmem;
        struct regmap *regmap;
        struct sunxi_sid *sid;
-       int i, size;
+       int ret, i, size;
        char *randomness;
 
        sid = devm_kzalloc(dev, sizeof(*sid), GFP_KERNEL);
@@ -131,6 +131,11 @@ static int sunxi_sid_probe(struct platform_device *pdev)
                return PTR_ERR(nvmem);
 
        randomness = kzalloc(sizeof(u8) * size, GFP_KERNEL);
+       if (!randomness) {
+               ret = -EINVAL;
+               goto err_unreg_nvmem;
+       }
+
        for (i = 0; i < size; i++)
                randomness[i] = sunxi_sid_read_byte(sid, i);
 
@@ -140,6 +145,10 @@ static int sunxi_sid_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, nvmem);
 
        return 0;
+
+err_unreg_nvmem:
+       nvmem_unregister(nvmem);
+       return ret;
 }
 
 static int sunxi_sid_remove(struct platform_device *pdev)
index 1350fa25cdb0605c60d3fc7f55f582c27dd868b1..a87a868fed64f50f22b66741aa357fbff7d5a0bb 100644 (file)
@@ -197,7 +197,8 @@ static int of_phy_match(struct device *dev, void *phy_np)
  * of_phy_find_device - Give a PHY node, find the phy_device
  * @phy_np: Pointer to the phy's device tree node
  *
- * Returns a pointer to the phy_device.
+ * If successful, returns a pointer to the phy_device with the embedded
+ * struct device refcount incremented by one, or NULL on failure.
  */
 struct phy_device *of_phy_find_device(struct device_node *phy_np)
 {
@@ -217,7 +218,9 @@ EXPORT_SYMBOL(of_phy_find_device);
  * @hndlr: Link state callback for the network device
  * @iface: PHY data interface type
  *
- * Returns a pointer to the phy_device if successful.  NULL otherwise
+ * If successful, returns a pointer to the phy_device with the embedded
+ * struct device refcount incremented by one, or NULL on failure. The
+ * refcount must be dropped by calling phy_disconnect() or phy_detach().
  */
 struct phy_device *of_phy_connect(struct net_device *dev,
                                  struct device_node *phy_np,
@@ -225,13 +228,19 @@ struct phy_device *of_phy_connect(struct net_device *dev,
                                  phy_interface_t iface)
 {
        struct phy_device *phy = of_phy_find_device(phy_np);
+       int ret;
 
        if (!phy)
                return NULL;
 
        phy->dev_flags = flags;
 
-       return phy_connect_direct(dev, phy, hndlr, iface) ? NULL : phy;
+       ret = phy_connect_direct(dev, phy, hndlr, iface);
+
+       /* refcount is held by phy_connect_direct() on success */
+       put_device(&phy->dev);
+
+       return ret ? NULL : phy;
 }
 EXPORT_SYMBOL(of_phy_connect);
 
@@ -241,17 +250,27 @@ EXPORT_SYMBOL(of_phy_connect);
  * @phy_np: Node pointer for the PHY
  * @flags: flags to pass to the PHY
  * @iface: PHY data interface type
+ *
+ * If successful, returns a pointer to the phy_device with the embedded
+ * struct device refcount incremented by one, or NULL on failure. The
+ * refcount must be dropped by calling phy_disconnect() or phy_detach().
  */
 struct phy_device *of_phy_attach(struct net_device *dev,
                                 struct device_node *phy_np, u32 flags,
                                 phy_interface_t iface)
 {
        struct phy_device *phy = of_phy_find_device(phy_np);
+       int ret;
 
        if (!phy)
                return NULL;
 
-       return phy_attach_direct(dev, phy, flags, iface) ? NULL : phy;
+       ret = phy_attach_direct(dev, phy, flags, iface);
+
+       /* refcount is held by phy_attach_direct() on success */
+       put_device(&phy->dev);
+
+       return ret ? NULL : phy;
 }
 EXPORT_SYMBOL(of_phy_attach);
 
index 1710d9dc7fc2e304b10e414bdab24e5329609387..2306313c0029a095c1fefa6b7b5eb0ff28f1cf9c 100644 (file)
@@ -38,8 +38,8 @@ int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq
         */
        rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
        if (rc != 0)
-               return rc;
-       /* No pin, exit */
+               goto err;
+       /* No pin, exit with no error message. */
        if (pin == 0)
                return -ENODEV;
 
@@ -53,8 +53,10 @@ int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq
                        ppnode = pci_bus_to_OF_node(pdev->bus);
 
                        /* No node for host bridge ? give up */
-                       if (ppnode == NULL)
-                               return -EINVAL;
+                       if (ppnode == NULL) {
+                               rc = -EINVAL;
+                               goto err;
+                       }
                } else {
                        /* We found a P2P bridge, check if it has a node */
                        ppnode = pci_device_to_OF_node(ppdev);
@@ -86,7 +88,13 @@ int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq
        out_irq->args[0] = pin;
        laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8));
        laddr[1] = laddr[2] = cpu_to_be32(0);
-       return of_irq_parse_raw(laddr, out_irq);
+       rc = of_irq_parse_raw(laddr, out_irq);
+       if (rc)
+               goto err;
+       return 0;
+err:
+       dev_err(&pdev->dev, "of_irq_parse_pci() failed with rc=%d\n", rc);
+       return rc;
 }
 EXPORT_SYMBOL_GPL(of_irq_parse_pci);
 
@@ -105,10 +113,8 @@ int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin)
        int ret;
 
        ret = of_irq_parse_pci(dev, &oirq);
-       if (ret) {
-               dev_err(&dev->dev, "of_irq_parse_pci() failed with rc=%d\n", ret);
+       if (ret)
                return 0; /* Proper return code 0 == NO_IRQ */
-       }
 
        return irq_create_of_mapping(&oirq);
 }
index baec33c4e6981ffdb19df8d767f5aff8cb72bb77..a0580afe1713a5f58db5e96da635028856200a08 100644 (file)
@@ -560,6 +560,9 @@ dino_fixup_bus(struct pci_bus *bus)
        } else if (bus->parent) {
                int i;
 
+               pci_read_bridge_bases(bus);
+
+
                for(i = PCI_BRIDGE_RESOURCES; i < PCI_NUM_RESOURCES; i++) {
                        if((bus->self->resource[i].flags & 
                            (IORESOURCE_IO | IORESOURCE_MEM)) == 0)
index 7b9e89ba0465f120b07385643b56900a61054696..a32c1f6c252cd91660b358ae8cd754d28953ce3b 100644 (file)
@@ -693,6 +693,7 @@ lba_fixup_bus(struct pci_bus *bus)
        if (bus->parent) {
                int i;
                /* PCI-PCI Bridge */
+               pci_read_bridge_bases(bus);
                for (i = PCI_BRIDGE_RESOURCES; i < PCI_NUM_RESOURCES; i++)
                        pci_claim_bridge_resource(bus->self, i);
        } else {
index 769f7e35f1a2efecabd75b731465e29e71a4fd62..59ac36fe7c42d9b9f911a7939985c008ffed951c 100644 (file)
@@ -442,7 +442,8 @@ static const struct pci_vpd_ops pci_vpd_pci22_ops = {
 static ssize_t pci_vpd_f0_read(struct pci_dev *dev, loff_t pos, size_t count,
                               void *arg)
 {
-       struct pci_dev *tdev = pci_get_slot(dev->bus, PCI_SLOT(dev->devfn));
+       struct pci_dev *tdev = pci_get_slot(dev->bus,
+                                           PCI_DEVFN(PCI_SLOT(dev->devfn), 0));
        ssize_t ret;
 
        if (!tdev)
@@ -456,7 +457,8 @@ static ssize_t pci_vpd_f0_read(struct pci_dev *dev, loff_t pos, size_t count,
 static ssize_t pci_vpd_f0_write(struct pci_dev *dev, loff_t pos, size_t count,
                                const void *arg)
 {
-       struct pci_dev *tdev = pci_get_slot(dev->bus, PCI_SLOT(dev->devfn));
+       struct pci_dev *tdev = pci_get_slot(dev->bus,
+                                           PCI_DEVFN(PCI_SLOT(dev->devfn), 0));
        ssize_t ret;
 
        if (!tdev)
@@ -473,22 +475,6 @@ static const struct pci_vpd_ops pci_vpd_f0_ops = {
        .release = pci_vpd_pci22_release,
 };
 
-static int pci_vpd_f0_dev_check(struct pci_dev *dev)
-{
-       struct pci_dev *tdev = pci_get_slot(dev->bus, PCI_SLOT(dev->devfn));
-       int ret = 0;
-
-       if (!tdev)
-               return -ENODEV;
-       if (!tdev->vpd || !tdev->multifunction ||
-           dev->class != tdev->class || dev->vendor != tdev->vendor ||
-           dev->device != tdev->device)
-               ret = -ENODEV;
-
-       pci_dev_put(tdev);
-       return ret;
-}
-
 int pci_vpd_pci22_init(struct pci_dev *dev)
 {
        struct pci_vpd_pci22 *vpd;
@@ -497,12 +483,7 @@ int pci_vpd_pci22_init(struct pci_dev *dev)
        cap = pci_find_capability(dev, PCI_CAP_ID_VPD);
        if (!cap)
                return -ENODEV;
-       if (dev->dev_flags & PCI_DEV_FLAGS_VPD_REF_F0) {
-               int ret = pci_vpd_f0_dev_check(dev);
 
-               if (ret)
-                       return ret;
-       }
        vpd = kzalloc(sizeof(*vpd), GFP_ATOMIC);
        if (!vpd)
                return -ENOMEM;
index 6fbd3f2b5992a2cdd53c759147629292463789fd..d3346d23963b87606517b44b15c196ee3393ac4e 100644 (file)
@@ -256,6 +256,8 @@ bool pci_bus_clip_resource(struct pci_dev *dev, int idx)
 
                res->start = start;
                res->end = end;
+               res->flags &= ~IORESOURCE_UNSET;
+               orig_res.flags &= ~IORESOURCE_UNSET;
                dev_printk(KERN_DEBUG, &dev->dev, "%pR clipped to %pR\n",
                                 &orig_res, res);
 
index 81253e70b1c5441b41544a58f682caa73f84dbc8..0aa81bd3de12d8eca876851e6f019a87f9b88f64 100644 (file)
@@ -110,7 +110,7 @@ static int ks_pcie_establish_link(struct keystone_pcie *ks_pcie)
        return -EINVAL;
 }
 
-static void ks_pcie_msi_irq_handler(unsigned int __irq, struct irq_desc *desc)
+static void ks_pcie_msi_irq_handler(struct irq_desc *desc)
 {
        unsigned int irq = irq_desc_get_irq(desc);
        struct keystone_pcie *ks_pcie = irq_desc_get_handler_data(desc);
@@ -138,8 +138,7 @@ static void ks_pcie_msi_irq_handler(unsigned int __irq, struct irq_desc *desc)
  * Traverse through pending legacy interrupts and invoke handler for each. Also
  * takes care of interrupt controller level mask/ack operation.
  */
-static void ks_pcie_legacy_irq_handler(unsigned int __irq,
-                                      struct irq_desc *desc)
+static void ks_pcie_legacy_irq_handler(struct irq_desc *desc)
 {
        unsigned int irq = irq_desc_get_irq(desc);
        struct keystone_pcie *ks_pcie = irq_desc_get_handler_data(desc);
index 367e28fa75643a1fe27218d640f090ac004877b9..c4f64bfee551b6cd46c50dabb05cbb5d7b4f5c48 100644 (file)
@@ -362,6 +362,7 @@ static int rcar_pci_probe(struct platform_device *pdev)
 static struct of_device_id rcar_pci_of_match[] = {
        { .compatible = "renesas,pci-r8a7790", },
        { .compatible = "renesas,pci-r8a7791", },
+       { .compatible = "renesas,pci-r8a7794", },
        { },
 };
 
index 996327cfa1e1945e47449f1a33dd941ef143b372..e491681daf22681c7bd541ad75d078edfa32ea1c 100644 (file)
@@ -295,7 +295,7 @@ static int xgene_msi_init_allocator(struct xgene_msi *xgene_msi)
        return 0;
 }
 
-static void xgene_msi_isr(unsigned int irq, struct irq_desc *desc)
+static void xgene_msi_isr(struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_desc_get_chip(desc);
        struct xgene_msi_group *msi_groups;
index d4497141d083a71d5d5206496fee58fbddc5cb13..4a7da3c3e0353c3c746e9b10be9a093c8d085920 100644 (file)
@@ -1243,6 +1243,10 @@ static void pci_msi_domain_update_chip_ops(struct msi_domain_info *info)
        BUG_ON(!chip);
        if (!chip->irq_write_msi_msg)
                chip->irq_write_msi_msg = pci_msi_domain_write_msg;
+       if (!chip->irq_mask)
+               chip->irq_mask = pci_msi_mask_irq;
+       if (!chip->irq_unmask)
+               chip->irq_unmask = pci_msi_unmask_irq;
 }
 
 /**
index dd652f2ae03db964ed539c5d369092173ab9ab33..108a3118ace7fbd107a2916aa29066cc326c0b6c 100644 (file)
@@ -299,9 +299,10 @@ static long local_pci_probe(void *_ddi)
         * Unbound PCI devices are always put in D0, regardless of
         * runtime PM status.  During probe, the device is set to
         * active and the usage count is incremented.  If the driver
-        * supports runtime PM, it should call pm_runtime_put_noidle()
-        * in its probe routine and pm_runtime_get_noresume() in its
-        * remove routine.
+        * supports runtime PM, it should call pm_runtime_put_noidle(),
+        * or any other runtime PM helper function decrementing the usage
+        * count, in its probe routine and pm_runtime_get_noresume() in
+        * its remove routine.
         */
        pm_runtime_get_sync(dev);
        pci_dev->driver = pci_drv;
index 312f23a8429cd9331b45afaf72a278e84bd41d83..92618686604cb9d314aa1e6bf833363cfbaaa1b5 100644 (file)
@@ -216,7 +216,7 @@ static ssize_t numa_node_store(struct device *dev,
        if (ret)
                return ret;
 
-       if (!node_online(node))
+       if (node >= MAX_NUMNODES || !node_online(node))
                return -EINVAL;
 
        add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
index 0b2be174d9818e9ffe86110068c9eb2e3ea19f11..8361d27e5ecad82ff9767c3d55a019a66f884046 100644 (file)
@@ -676,15 +676,20 @@ static struct irq_domain *pci_host_bridge_msi_domain(struct pci_bus *bus)
 static void pci_set_bus_msi_domain(struct pci_bus *bus)
 {
        struct irq_domain *d;
+       struct pci_bus *b;
 
        /*
-        * Either bus is the root, and we must obtain it from the
-        * firmware, or we inherit it from the bridge device.
+        * The bus can be a root bus, a subordinate bus, or a virtual bus
+        * created by an SR-IOV device.  Walk up to the first bridge device
+        * found or derive the domain from the host bridge.
         */
-       if (pci_is_root_bus(bus))
-               d = pci_host_bridge_msi_domain(bus);
-       else
-               d = dev_get_msi_domain(&bus->self->dev);
+       for (b = bus, d = NULL; !d && !pci_is_root_bus(b); b = b->parent) {
+               if (b->self)
+                       d = dev_get_msi_domain(&b->self->dev);
+       }
+
+       if (!d)
+               d = pci_host_bridge_msi_domain(b);
 
        dev_set_msi_domain(&bus->dev, d);
 }
@@ -855,9 +860,6 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
                        child->bridge_ctl = bctl;
                }
 
-               /* Read and initialize bridge resources */
-               pci_read_bridge_bases(child);
-
                cmax = pci_scan_child_bus(child);
                if (cmax > subordinate)
                        dev_warn(&dev->dev, "bridge has subordinate %02x but max busn %02x\n",
@@ -918,9 +920,6 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
 
                if (!is_cardbus) {
                        child->bridge_ctl = bctl;
-
-                       /* Read and initialize bridge resources */
-                       pci_read_bridge_bases(child);
                        max = pci_scan_child_bus(child);
                } else {
                        /*
index 6a30252cd79f20f24e604965a9a023f2ff08478f..b03373fd05ca3854f9816d47db5a2868a6509420 100644 (file)
@@ -1907,11 +1907,27 @@ static void quirk_netmos(struct pci_dev *dev)
 DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_NETMOS, PCI_ANY_ID,
                         PCI_CLASS_COMMUNICATION_SERIAL, 8, quirk_netmos);
 
+/*
+ * Quirk non-zero PCI functions to route VPD access through function 0 for
+ * devices that share VPD resources between functions.  The functions are
+ * expected to be identical devices.
+ */
 static void quirk_f0_vpd_link(struct pci_dev *dev)
 {
-       if (!dev->multifunction || !PCI_FUNC(dev->devfn))
+       struct pci_dev *f0;
+
+       if (!PCI_FUNC(dev->devfn))
                return;
-       dev->dev_flags |= PCI_DEV_FLAGS_VPD_REF_F0;
+
+       f0 = pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn), 0));
+       if (!f0)
+               return;
+
+       if (f0->vpd && dev->class == f0->class &&
+           dev->vendor == f0->vendor && dev->device == f0->device)
+               dev->dev_flags |= PCI_DEV_FLAGS_VPD_REF_F0;
+
+       pci_dev_put(f0);
 }
 DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_INTEL, PCI_ANY_ID,
                              PCI_CLASS_NETWORK_ETHERNET, 8, quirk_f0_vpd_link);
index 2365a32a595e42b8ddf43c2dc32603749cf990d7..be3755c973e96d4c6ee48f0459c751ba6d225665 100644 (file)
@@ -823,9 +823,15 @@ static int of_pmu_irq_cfg(struct arm_pmu *pmu)
                }
 
                /* Now look up the logical CPU number */
-               for_each_possible_cpu(cpu)
-                       if (dn == of_cpu_device_node_get(cpu))
+               for_each_possible_cpu(cpu) {
+                       struct device_node *cpu_dn;
+
+                       cpu_dn = of_cpu_device_node_get(cpu);
+                       of_node_put(cpu_dn);
+
+                       if (dn == cpu_dn)
                                break;
+               }
 
                if (cpu >= nr_cpu_ids) {
                        pr_warn("Failed to find logical CPU for %s\n",
index 0062027afb1ef90335ae46782dba06448949b989..77a2e054fdea0f46ccd3d2841f5f837f80a985e1 100644 (file)
@@ -276,6 +276,7 @@ static const struct of_device_id phy_berlin_sata_of_match[] = {
        { .compatible = "marvell,berlin2q-sata-phy" },
        { },
 };
+MODULE_DEVICE_TABLE(of, phy_berlin_sata_of_match);
 
 static struct platform_driver phy_berlin_sata_driver = {
        .probe  = phy_berlin_sata_probe,
index 49a1ed0cef56fe7cbf9aed102b47149415f021f0..107cb57c3513c22642bb14420f47c469a39dcfa2 100644 (file)
@@ -432,6 +432,7 @@ out_disable_src:
 out:
        return ret;
 }
+EXPORT_SYMBOL_GPL(ufs_qcom_phy_enable_ref_clk);
 
 static
 int ufs_qcom_phy_disable_vreg(struct phy *phy,
@@ -474,6 +475,7 @@ void ufs_qcom_phy_disable_ref_clk(struct phy *generic_phy)
                phy->is_ref_clk_enabled = false;
        }
 }
+EXPORT_SYMBOL_GPL(ufs_qcom_phy_disable_ref_clk);
 
 #define UFS_REF_CLK_EN (1 << 5)
 
@@ -517,11 +519,13 @@ void ufs_qcom_phy_enable_dev_ref_clk(struct phy *generic_phy)
 {
        ufs_qcom_phy_dev_ref_clk_ctrl(generic_phy, true);
 }
+EXPORT_SYMBOL_GPL(ufs_qcom_phy_enable_dev_ref_clk);
 
 void ufs_qcom_phy_disable_dev_ref_clk(struct phy *generic_phy)
 {
        ufs_qcom_phy_dev_ref_clk_ctrl(generic_phy, false);
 }
+EXPORT_SYMBOL_GPL(ufs_qcom_phy_disable_dev_ref_clk);
 
 /* Turn ON M-PHY RMMI interface clocks */
 int ufs_qcom_phy_enable_iface_clk(struct phy *generic_phy)
@@ -550,6 +554,7 @@ int ufs_qcom_phy_enable_iface_clk(struct phy *generic_phy)
 out:
        return ret;
 }
+EXPORT_SYMBOL_GPL(ufs_qcom_phy_enable_iface_clk);
 
 /* Turn OFF M-PHY RMMI interface clocks */
 void ufs_qcom_phy_disable_iface_clk(struct phy *generic_phy)
@@ -562,6 +567,7 @@ void ufs_qcom_phy_disable_iface_clk(struct phy *generic_phy)
                phy->is_iface_clk_enabled = false;
        }
 }
+EXPORT_SYMBOL_GPL(ufs_qcom_phy_disable_iface_clk);
 
 int ufs_qcom_phy_start_serdes(struct phy *generic_phy)
 {
@@ -578,6 +584,7 @@ int ufs_qcom_phy_start_serdes(struct phy *generic_phy)
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(ufs_qcom_phy_start_serdes);
 
 int ufs_qcom_phy_set_tx_lane_enable(struct phy *generic_phy, u32 tx_lanes)
 {
@@ -595,6 +602,7 @@ int ufs_qcom_phy_set_tx_lane_enable(struct phy *generic_phy, u32 tx_lanes)
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(ufs_qcom_phy_set_tx_lane_enable);
 
 void ufs_qcom_phy_save_controller_version(struct phy *generic_phy,
                                          u8 major, u16 minor, u16 step)
@@ -605,6 +613,7 @@ void ufs_qcom_phy_save_controller_version(struct phy *generic_phy,
        ufs_qcom_phy->host_ctrl_rev_minor = minor;
        ufs_qcom_phy->host_ctrl_rev_step = step;
 }
+EXPORT_SYMBOL_GPL(ufs_qcom_phy_save_controller_version);
 
 int ufs_qcom_phy_calibrate_phy(struct phy *generic_phy, bool is_rate_B)
 {
@@ -625,6 +634,7 @@ int ufs_qcom_phy_calibrate_phy(struct phy *generic_phy, bool is_rate_B)
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(ufs_qcom_phy_calibrate_phy);
 
 int ufs_qcom_phy_remove(struct phy *generic_phy,
                        struct ufs_qcom_phy *ufs_qcom_phy)
@@ -662,6 +672,7 @@ int ufs_qcom_phy_is_pcs_ready(struct phy *generic_phy)
        return ufs_qcom_phy->phy_spec_ops->
                        is_physical_coding_sublayer_ready(ufs_qcom_phy);
 }
+EXPORT_SYMBOL_GPL(ufs_qcom_phy_is_pcs_ready);
 
 int ufs_qcom_phy_power_on(struct phy *generic_phy)
 {
index 5a5c073e72fe1ee6115bea310890b646b6b40a69..91d6f342c56596fc2e3fcff18213dba004546c3e 100644 (file)
@@ -98,6 +98,7 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
        struct device_node *child;
        struct regmap *grf;
        unsigned int reg_offset;
+       int err;
 
        grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf");
        if (IS_ERR(grf)) {
@@ -129,6 +130,11 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
                        return PTR_ERR(rk_phy->phy);
                }
                phy_set_drvdata(rk_phy->phy, rk_phy);
+
+               /* only power up usb phy when it use, so disable it when init*/
+               err = rockchip_usb_phy_power(rk_phy, 1);
+               if (err)
+                       return err;
        }
 
        phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
index 7d9482bf825271d52e7205fe9c67f330a64f0ffe..1ca783098e47463bd3c9a5f267f5fb00eb68ef88 100644 (file)
@@ -143,7 +143,7 @@ static inline bool cygnus_get_bit(struct cygnus_gpio *chip, unsigned int reg,
        return !!(readl(chip->base + offset) & BIT(shift));
 }
 
-static void cygnus_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void cygnus_gpio_irq_handler(struct irq_desc *desc)
 {
        struct gpio_chip *gc = irq_desc_get_handler_data(desc);
        struct cygnus_gpio *chip = to_cygnus_gpio(gc);
index 69723e07036bafbd29c6d6deb66e2f7bd7f0133e..9638a00c67c2bd9a3735a632c99d01e9c2625e5d 100644 (file)
@@ -349,6 +349,9 @@ static bool pinctrl_ready_for_gpio_range(unsigned gpio)
        struct pinctrl_gpio_range *range = NULL;
        struct gpio_chip *chip = gpio_to_chip(gpio);
 
+       if (WARN(!chip, "no gpio_chip for gpio%i?", gpio))
+               return false;
+
        mutex_lock(&pinctrldev_list_mutex);
 
        /* Loop over the pin controllers */
index faf635654312a75168ad7237ecf1995d317e396d..293ed4381cc0e08c1bb195bbb9f535fba66075ed 100644 (file)
@@ -26,7 +26,8 @@
 #include "pinctrl-imx.h"
 
 enum imx25_pads {
-       MX25_PAD_RESERVE0 = 1,
+       MX25_PAD_RESERVE0 = 0,
+       MX25_PAD_RESERVE1 = 1,
        MX25_PAD_A10 = 2,
        MX25_PAD_A13 = 3,
        MX25_PAD_A14 = 4,
@@ -169,6 +170,7 @@ enum imx25_pads {
 /* Pad names for the pinmux subsystem */
 static const struct pinctrl_pin_desc imx25_pinctrl_pads[] = {
        IMX_PINCTRL_PIN(MX25_PAD_RESERVE0),
+       IMX_PINCTRL_PIN(MX25_PAD_RESERVE1),
        IMX_PINCTRL_PIN(MX25_PAD_A10),
        IMX_PINCTRL_PIN(MX25_PAD_A13),
        IMX_PINCTRL_PIN(MX25_PAD_A14),
index dac4865f3203d1750653d644caabffb1fcdbf853..f79ea430f651996a2f148e141319861e285c2d28 100644 (file)
@@ -425,7 +425,7 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
        }
 }
 
-static void byt_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+static void byt_gpio_irq_handler(struct irq_desc *desc)
 {
        struct irq_data *data = irq_desc_get_irq_data(desc);
        struct byt_gpio *vg = to_byt_gpio(irq_desc_get_handler_data(desc));
index 2d5d3ddc36e5b36702771fb217967a6a3268a1f2..270c127e03ea72f759d74758d3d81b00d60e52bb 100644 (file)
@@ -1414,7 +1414,7 @@ static struct irq_chip chv_gpio_irqchip = {
        .flags = IRQCHIP_SKIP_SET_WAKE,
 };
 
-static void chv_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+static void chv_gpio_irq_handler(struct irq_desc *desc)
 {
        struct gpio_chip *gc = irq_desc_get_handler_data(desc);
        struct chv_pinctrl *pctrl = gpiochip_to_pinctrl(gc);
index bb377c110541b34d09a65867765706cb278cb9c9..54848b8decef7735d8b009c6431a970f94204488 100644 (file)
@@ -836,7 +836,7 @@ static void intel_gpio_community_irq_handler(struct gpio_chip *gc,
        }
 }
 
-static void intel_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+static void intel_gpio_irq_handler(struct irq_desc *desc)
 {
        struct gpio_chip *gc = irq_desc_get_handler_data(desc);
        struct intel_pinctrl *pctrl = gpiochip_to_pinctrl(gc);
index 7726c6caaf8350f7832ecb81ff26c074022b77a9..1b22f96ba839af38d920d40f0f63309d2141a2b5 100644 (file)
@@ -1190,7 +1190,7 @@ mtk_eint_debounce_process(struct mtk_pinctrl *pctl, int index)
        }
 }
 
-static void mtk_eint_irq_handler(unsigned irq, struct irq_desc *desc)
+static void mtk_eint_irq_handler(struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_desc_get_chip(desc);
        struct mtk_pinctrl *pctl = irq_desc_get_handler_data(desc);
index 352ede13a9e9a33ab40868810ac4eef723c46035..96cf03908e93cc1462435b1aebc6c178c4a620f5 100644 (file)
@@ -860,7 +860,7 @@ static void __nmk_gpio_irq_handler(struct irq_desc *desc, u32 status)
        chained_irq_exit(host_chip, desc);
 }
 
-static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void nmk_gpio_irq_handler(struct irq_desc *desc)
 {
        struct gpio_chip *chip = irq_desc_get_handler_data(desc);
        struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip);
@@ -873,7 +873,7 @@ static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
        __nmk_gpio_irq_handler(desc, status);
 }
 
-static void nmk_gpio_latent_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void nmk_gpio_latent_irq_handler(struct irq_desc *desc)
 {
        struct gpio_chip *chip = irq_desc_get_handler_data(desc);
        struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip);
index a5976ebc4482633514e7b8b6259b528b2bb2c0ed..f6be68518c87d78195d3a9505b8eab5377804227 100644 (file)
@@ -530,8 +530,7 @@ static inline void preflow_handler(struct irq_desc *desc)
 static inline void preflow_handler(struct irq_desc *desc) { }
 #endif
 
-static void adi_gpio_handle_pint_irq(unsigned int inta_irq,
-                       struct irq_desc *desc)
+static void adi_gpio_handle_pint_irq(struct irq_desc *desc)
 {
        u32 request;
        u32 level_mask, hwirq;
index 5e86bb8ca80e68c0f48372483b7eea6001d6e816..3318f1d6193c8a49f1ca8f4348dd25010fe18758 100644 (file)
@@ -492,15 +492,15 @@ static struct irq_chip amd_gpio_irqchip = {
        .irq_set_type = amd_gpio_irq_set_type,
 };
 
-static void amd_gpio_irq_handler(unsigned int __irq, struct irq_desc *desc)
+static void amd_gpio_irq_handler(struct irq_desc *desc)
 {
-       unsigned int irq = irq_desc_get_irq(desc);
        u32 i;
        u32 off;
        u32 reg;
        u32 pin_reg;
        u64 reg64;
        int handled = 0;
+       unsigned int irq;
        unsigned long flags;
        struct irq_chip *chip = irq_desc_get_chip(desc);
        struct gpio_chip *gc = irq_desc_get_handler_data(desc);
@@ -541,7 +541,7 @@ static void amd_gpio_irq_handler(unsigned int __irq, struct irq_desc *desc)
        }
 
        if (handled == 0)
-               handle_bad_irq(irq, desc);
+               handle_bad_irq(desc);
 
        spin_lock_irqsave(&gpio_dev->lock, flags);
        reg = readl(gpio_dev->base + WAKE_INT_MASTER_REG);
index bae0012ee356011c037fb1403eb88dce26268450..b0fde0f385e6864c4fd962751fab9bb51dfbfa13 100644 (file)
@@ -1585,7 +1585,7 @@ static struct irq_chip gpio_irqchip = {
        .irq_set_wake   = gpio_irq_set_wake,
 };
 
-static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+static void gpio_irq_handler(struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_desc_get_chip(desc);
        struct gpio_chip *gpio_chip = irq_desc_get_handler_data(desc);
index 3731cc67a88bf84a0651de1d4fc73db0281f6cad..9c9b88934bcc904de8b63f20778ef12985ad7ed5 100644 (file)
@@ -519,7 +519,7 @@ static struct irq_chip u300_gpio_irqchip = {
        .irq_set_type           = u300_gpio_irq_type,
 };
 
-static void u300_gpio_irq_handler(unsigned __irq, struct irq_desc *desc)
+static void u300_gpio_irq_handler(struct irq_desc *desc)
 {
        unsigned int irq = irq_desc_get_irq(desc);
        struct irq_chip *parent_chip = irq_desc_get_chip(desc);
index 461fffc4c62ae8b3661b930e244c51267ca81406..11f8b835d3b64f61fde81bc77c2b5ecf931fd351 100644 (file)
@@ -337,9 +337,9 @@ static int dc_pinctrl_probe(struct platform_device *pdev)
        pmap->dev = &pdev->dev;
 
        pmap->pctl = pinctrl_register(pctl_desc, &pdev->dev, pmap);
-       if (!pmap->pctl) {
+       if (IS_ERR(pmap->pctl)) {
                dev_err(&pdev->dev, "pinctrl driver registration failed\n");
-               return -EINVAL;
+               return PTR_ERR(pmap->pctl);
        }
 
        ret = dc_gpiochip_add(pmap, pdev->dev.of_node);
index 3dc2ae15f3a10f723813f78d34420ea1fb4650e9..952b1c62388773eb5594b03c7b0a639061c8f4b9 100644 (file)
@@ -1303,20 +1303,18 @@ static int pistachio_gpio_irq_set_type(struct irq_data *data, unsigned int type)
        }
 
        if (type & IRQ_TYPE_LEVEL_MASK)
-               __irq_set_handler_locked(data->irq, handle_level_irq);
+               irq_set_handler_locked(data, handle_level_irq);
        else
-               __irq_set_handler_locked(data->irq, handle_edge_irq);
+               irq_set_handler_locked(data, handle_edge_irq);
 
        return 0;
 }
 
-static void pistachio_gpio_irq_handler(unsigned int __irq,
-                                      struct irq_desc *desc)
+static void pistachio_gpio_irq_handler(struct irq_desc *desc)
 {
-       unsigned int irq = irq_desc_get_irq(desc);
        struct gpio_chip *gc = irq_desc_get_handler_data(desc);
        struct pistachio_gpio_bank *bank = gc_to_bank(gc);
-       struct irq_chip *chip = irq_get_chip(irq);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
        unsigned long pending;
        unsigned int pin;
 
index c5246c05f70cc77f70982f7d5540edec92d5e784..88bb707e107ad8d9b8f14832d5edd4788a8b5cf6 100644 (file)
@@ -1475,7 +1475,7 @@ static const struct gpio_chip rockchip_gpiolib_chip = {
  * Interrupt handling
  */
 
-static void rockchip_irq_demux(unsigned int __irq, struct irq_desc *desc)
+static void rockchip_irq_demux(struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_desc_get_chip(desc);
        struct rockchip_pin_bank *bank = irq_desc_get_handler_data(desc);
index bf548c2a7a9d83d7d447756d2d84d39caa5918e5..ef04b962c3d51992ba41080b893829d2d4102b56 100644 (file)
@@ -1679,7 +1679,7 @@ static irqreturn_t pcs_irq_handler(int irq, void *d)
  * Use this if you have a separate interrupt for each
  * pinctrl-single instance.
  */
-static void pcs_irq_chain_handler(unsigned int irq, struct irq_desc *desc)
+static void pcs_irq_chain_handler(struct irq_desc *desc)
 {
        struct pcs_soc_data *pcs_soc = irq_desc_get_handler_data(desc);
        struct irq_chip *chip;
index f8338d2e6b6b91d53bf531abd0a522ac99d75c1b..389526e704fb0eb68125e31cee1363d78c3caf8b 100644 (file)
@@ -1460,7 +1460,7 @@ static void __gpio_irq_handler(struct st_gpio_bank *bank)
        }
 }
 
-static void st_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+static void st_gpio_irq_handler(struct irq_desc *desc)
 {
        /* interrupt dedicated per bank */
        struct irq_chip *chip = irq_desc_get_chip(desc);
@@ -1472,7 +1472,7 @@ static void st_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
        chained_irq_exit(chip, desc);
 }
 
-static void st_gpio_irqmux_handler(unsigned irq, struct irq_desc *desc)
+static void st_gpio_irqmux_handler(struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_desc_get_chip(desc);
        struct st_pinctrl *info = irq_desc_get_handler_data(desc);
index 67e08cb315c47e67329f8c4090ef2a1f503b9873..29984b36926aef871bb8e5ce93fa6308ddec37b5 100644 (file)
@@ -313,8 +313,7 @@ static int pinmux_func_name_to_selector(struct pinctrl_dev *pctldev,
 
        /* See if this pctldev has this function */
        while (selector < nfuncs) {
-               const char *fname = ops->get_function_name(pctldev,
-                                                          selector);
+               const char *fname = ops->get_function_name(pctldev, selector);
 
                if (!strcmp(function, fname))
                        return selector;
index 492cdd51dc5c718d3063a3f59269ee24bd5d1034..a0c7407c1cac486b8609283f0b06350e124468da 100644 (file)
@@ -765,9 +765,8 @@ static struct irq_chip msm_gpio_irq_chip = {
        .irq_set_wake   = msm_gpio_irq_set_wake,
 };
 
-static void msm_gpio_irq_handler(unsigned int __irq, struct irq_desc *desc)
+static void msm_gpio_irq_handler(struct irq_desc *desc)
 {
-       unsigned int irq = irq_desc_get_irq(desc);
        struct gpio_chip *gc = irq_desc_get_handler_data(desc);
        const struct msm_pingroup *g;
        struct msm_pinctrl *pctrl = to_msm_pinctrl(gc);
@@ -795,7 +794,7 @@ static void msm_gpio_irq_handler(unsigned int __irq, struct irq_desc *desc)
 
        /* No interrupts were flagged */
        if (handled == 0)
-               handle_bad_irq(irq, desc);
+               handle_bad_irq(desc);
 
        chained_irq_exit(chip, desc);
 }
index c978b311031b52a0f999f6fda52d0f9c34e0a7b0..e1a3721bc8e5814fbef5a39184170407436cb193 100644 (file)
@@ -723,9 +723,9 @@ static int pm8xxx_gpio_probe(struct platform_device *pdev)
 #endif
 
        pctrl->pctrl = pinctrl_register(&pctrl->desc, &pdev->dev, pctrl);
-       if (!pctrl->pctrl) {
+       if (IS_ERR(pctrl->pctrl)) {
                dev_err(&pdev->dev, "couldn't register pm8xxx gpio driver\n");
-               return -ENODEV;
+               return PTR_ERR(pctrl->pctrl);
        }
 
        pctrl->chip = pm8xxx_gpio_template;
index 2d1b69f171be7c4dcffeba6199536f65075b604e..6652b8d7f707aefc5656edd348f95e0d139c21da 100644 (file)
@@ -814,9 +814,9 @@ static int pm8xxx_mpp_probe(struct platform_device *pdev)
 #endif
 
        pctrl->pctrl = pinctrl_register(&pctrl->desc, &pdev->dev, pctrl);
-       if (!pctrl->pctrl) {
+       if (IS_ERR(pctrl->pctrl)) {
                dev_err(&pdev->dev, "couldn't register pm8xxx mpp driver\n");
-               return -ENODEV;
+               return PTR_ERR(pctrl->pctrl);
        }
 
        pctrl->chip = pm8xxx_mpp_template;
index 5f45caaef46d6828bbfd1ea2b4f40ce445419357..71ccf6a90b222d14a02f771862d8c227cc115b80 100644 (file)
@@ -419,7 +419,7 @@ static const struct of_device_id exynos_wkup_irq_ids[] = {
 };
 
 /* interrupt handler for wakeup interrupts 0..15 */
-static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
+static void exynos_irq_eint0_15(struct irq_desc *desc)
 {
        struct exynos_weint_data *eintd = irq_desc_get_handler_data(desc);
        struct samsung_pin_bank *bank = eintd->bank;
@@ -451,7 +451,7 @@ static inline void exynos_irq_demux_eint(unsigned long pend,
 }
 
 /* interrupt handler for wakeup interrupt 16 */
-static void exynos_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
+static void exynos_irq_demux_eint16_31(struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_desc_get_chip(desc);
        struct exynos_muxed_weint_data *eintd = irq_desc_get_handler_data(desc);
index 019844d479bb5c2b1bd63ebc840f796d5c684965..3d92f827da7a83fc08a0d24e86347004ff01ba0b 100644 (file)
@@ -240,7 +240,7 @@ static struct irq_chip s3c2410_eint0_3_chip = {
        .irq_set_type   = s3c24xx_eint_type,
 };
 
-static void s3c2410_demux_eint0_3(unsigned int irq, struct irq_desc *desc)
+static void s3c2410_demux_eint0_3(struct irq_desc *desc)
 {
        struct irq_data *data = irq_desc_get_irq_data(desc);
        struct s3c24xx_eint_data *eint_data = irq_desc_get_handler_data(desc);
@@ -295,7 +295,7 @@ static struct irq_chip s3c2412_eint0_3_chip = {
        .irq_set_type   = s3c24xx_eint_type,
 };
 
-static void s3c2412_demux_eint0_3(unsigned int irq, struct irq_desc *desc)
+static void s3c2412_demux_eint0_3(struct irq_desc *desc)
 {
        struct s3c24xx_eint_data *eint_data = irq_desc_get_handler_data(desc);
        struct irq_data *data = irq_desc_get_irq_data(desc);
@@ -361,7 +361,7 @@ static inline void s3c24xx_demux_eint(struct irq_desc *desc,
                                      u32 offset, u32 range)
 {
        struct s3c24xx_eint_data *data = irq_desc_get_handler_data(desc);
-       struct irq_chip *chip = irq_desc_get_irq_chip(desc);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
        struct samsung_pinctrl_drv_data *d = data->drvdata;
        unsigned int pend, mask;
 
@@ -388,12 +388,12 @@ static inline void s3c24xx_demux_eint(struct irq_desc *desc,
        chained_irq_exit(chip, desc);
 }
 
-static void s3c24xx_demux_eint4_7(unsigned int irq, struct irq_desc *desc)
+static void s3c24xx_demux_eint4_7(struct irq_desc *desc)
 {
        s3c24xx_demux_eint(desc, 0, 0xf0);
 }
 
-static void s3c24xx_demux_eint8_23(unsigned int irq, struct irq_desc *desc)
+static void s3c24xx_demux_eint8_23(struct irq_desc *desc)
 {
        s3c24xx_demux_eint(desc, 8, 0xffff00);
 }
index f5ea40a69711c01eceaaea391fb6ad365d1d624d..43407ab248f5121d0ca5625112592a32a9f1a968 100644 (file)
@@ -407,7 +407,7 @@ static const struct irq_domain_ops s3c64xx_gpio_irqd_ops = {
        .xlate  = irq_domain_xlate_twocell,
 };
 
-static void s3c64xx_eint_gpio_irq(unsigned int irq, struct irq_desc *desc)
+static void s3c64xx_eint_gpio_irq(struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_desc_get_chip(desc);
        struct s3c64xx_eint_gpio_data *data = irq_desc_get_handler_data(desc);
@@ -631,22 +631,22 @@ static inline void s3c64xx_irq_demux_eint(struct irq_desc *desc, u32 range)
        chained_irq_exit(chip, desc);
 }
 
-static void s3c64xx_demux_eint0_3(unsigned int irq, struct irq_desc *desc)
+static void s3c64xx_demux_eint0_3(struct irq_desc *desc)
 {
        s3c64xx_irq_demux_eint(desc, 0xf);
 }
 
-static void s3c64xx_demux_eint4_11(unsigned int irq, struct irq_desc *desc)
+static void s3c64xx_demux_eint4_11(struct irq_desc *desc)
 {
        s3c64xx_irq_demux_eint(desc, 0xff0);
 }
 
-static void s3c64xx_demux_eint12_19(unsigned int irq, struct irq_desc *desc)
+static void s3c64xx_demux_eint12_19(struct irq_desc *desc)
 {
        s3c64xx_irq_demux_eint(desc, 0xff000);
 }
 
-static void s3c64xx_demux_eint20_27(unsigned int irq, struct irq_desc *desc)
+static void s3c64xx_demux_eint20_27(struct irq_desc *desc)
 {
        s3c64xx_irq_demux_eint(desc, 0xff00000);
 }
index 9df0c5f25824a2cbac9d3284f27a688345e83687..0d24d9e4b70c9583899d72aa02f072a8a0bdcd0d 100644 (file)
@@ -4489,7 +4489,7 @@ static struct irq_chip atlas7_gpio_irq_chip = {
        .irq_set_type = atlas7_gpio_irq_type,
 };
 
-static void atlas7_gpio_handle_irq(unsigned int __irq, struct irq_desc *desc)
+static void atlas7_gpio_handle_irq(struct irq_desc *desc)
 {
        struct gpio_chip *gc = irq_desc_get_handler_data(desc);
        struct atlas7_gpio_chip *a7gc = to_atlas7_gpio(gc);
@@ -4512,7 +4512,7 @@ static void atlas7_gpio_handle_irq(unsigned int __irq, struct irq_desc *desc)
        if (!status) {
                pr_warn("%s: gpio [%s] status %#x no interrupt is flaged\n",
                        __func__, gc->label, status);
-               handle_bad_irq(irq, desc);
+               handle_bad_irq(desc);
                return;
        }
 
index f8bd9fb52033d70ac4704036447b0a7d18bdd938..2a8d69725de81aab6a469faa02558d065f22f7d9 100644 (file)
@@ -545,7 +545,7 @@ static struct irq_chip sirfsoc_irq_chip = {
        .irq_set_type = sirfsoc_gpio_irq_type,
 };
 
-static void sirfsoc_gpio_handle_irq(unsigned int __irq, struct irq_desc *desc)
+static void sirfsoc_gpio_handle_irq(struct irq_desc *desc)
 {
        unsigned int irq = irq_desc_get_irq(desc);
        struct gpio_chip *gc = irq_desc_get_handler_data(desc);
@@ -570,7 +570,7 @@ static void sirfsoc_gpio_handle_irq(unsigned int __irq, struct irq_desc *desc)
                printk(KERN_WARNING
                        "%s: gpio id %d status %#x no interrupt is flagged\n",
                        __func__, bank->id, status);
-               handle_bad_irq(irq, desc);
+               handle_bad_irq(desc);
                return;
        }
 
index ae8f29fb55361ce53958fc08fbdbd43514336257..1f0af250dbb51362d30fb385fc09011dc16c7275 100644 (file)
@@ -356,7 +356,7 @@ static struct irq_chip plgpio_irqchip = {
        .irq_set_type   = plgpio_irq_set_type,
 };
 
-static void plgpio_irq_handler(unsigned irq, struct irq_desc *desc)
+static void plgpio_irq_handler(struct irq_desc *desc)
 {
        struct gpio_chip *gc = irq_desc_get_handler_data(desc);
        struct plgpio *plgpio = container_of(gc, struct plgpio, chip);
index 63676617bc5997218729a56c15c8597f8c2499b9..f9a3f8f446f76afe28177d5f9dcb8b8376b0310b 100644 (file)
@@ -653,7 +653,7 @@ static const struct sunxi_desc_pin sun5i_a10s_pins[] = {
                  SUNXI_FUNCTION(0x0, "gpio_in"),
                  SUNXI_FUNCTION(0x1, "gpio_out"),
                  SUNXI_FUNCTION(0x2, "spi1"),          /* CS1 */
-                 SUNXI_FUNCTION(0x3, "uart3"),         /* PWM1 */
+                 SUNXI_FUNCTION(0x3, "pwm"),           /* PWM1 */
                  SUNXI_FUNCTION(0x5, "uart2"),         /* CTS */
                  SUNXI_FUNCTION_IRQ(0x6, 13)),         /* EINT13 */
 };
index fb4669c0ce0e7651e1d9b3dfbcc4d1b4421f4427..38e0c7bdd2ac456362a7e2b845c0250be5e60411 100644 (file)
@@ -617,13 +617,11 @@ static int sunxi_pinctrl_irq_set_type(struct irq_data *d, unsigned int type)
        spin_lock_irqsave(&pctl->lock, flags);
 
        if (type & IRQ_TYPE_LEVEL_MASK)
-               __irq_set_chip_handler_name_locked(d->irq,
-                                                  &sunxi_pinctrl_level_irq_chip,
-                                                  handle_fasteoi_irq, NULL);
+               irq_set_chip_handler_name_locked(d, &sunxi_pinctrl_level_irq_chip,
+                                                handle_fasteoi_irq, NULL);
        else
-               __irq_set_chip_handler_name_locked(d->irq,
-                                                  &sunxi_pinctrl_edge_irq_chip,
-                                                  handle_edge_irq, NULL);
+               irq_set_chip_handler_name_locked(d, &sunxi_pinctrl_edge_irq_chip,
+                                                handle_edge_irq, NULL);
 
        regval = readl(pctl->membase + reg);
        regval &= ~(IRQ_CFG_IRQ_MASK << index);
@@ -742,7 +740,7 @@ static struct irq_domain_ops sunxi_pinctrl_irq_domain_ops = {
        .xlate          = sunxi_pinctrl_irq_of_xlate,
 };
 
-static void sunxi_pinctrl_irq_handler(unsigned __irq, struct irq_desc *desc)
+static void sunxi_pinctrl_irq_handler(struct irq_desc *desc)
 {
        unsigned int irq = irq_desc_get_irq(desc);
        struct irq_chip *chip = irq_desc_get_chip(desc);
index 7e9dae54fcb22e1df91d8a9fc6e01556de2e14f1..2df8bbecebfc4c5742e5652386186ce67a7aba7e 100644 (file)
 #define DRIVER_NAME "ph1-sld8-pinctrl"
 
 static const struct pinctrl_pin_desc ph1_sld8_pins[] = {
-       UNIPHIER_PINCTRL_PIN(0, "PCA00", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(0, "PCA00", 0,
                             15, UNIPHIER_PIN_DRV_4_8,
                             15, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(1, "PCA01", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(1, "PCA01", 0,
                             16, UNIPHIER_PIN_DRV_4_8,
                             16, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(2, "PCA02", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(2, "PCA02", 0,
                             17, UNIPHIER_PIN_DRV_4_8,
                             17, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(3, "PCA03", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(3, "PCA03", 0,
                             18, UNIPHIER_PIN_DRV_4_8,
                             18, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(4, "PCA04", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(4, "PCA04", 0,
                             19, UNIPHIER_PIN_DRV_4_8,
                             19, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(5, "PCA05", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(5, "PCA05", 0,
                             20, UNIPHIER_PIN_DRV_4_8,
                             20, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(6, "PCA06", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(6, "PCA06", 0,
                             21, UNIPHIER_PIN_DRV_4_8,
                             21, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(7, "PCA07", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(7, "PCA07", 0,
                             22, UNIPHIER_PIN_DRV_4_8,
                             22, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(8, "PCA08", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(8, "PCA08", 0,
                             23, UNIPHIER_PIN_DRV_4_8,
                             23, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(9, "PCA09", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(9, "PCA09", 0,
                             24, UNIPHIER_PIN_DRV_4_8,
                             24, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(10, "PCA10", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(10, "PCA10", 0,
                             25, UNIPHIER_PIN_DRV_4_8,
                             25, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(11, "PCA11", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(11, "PCA11", 0,
                             26, UNIPHIER_PIN_DRV_4_8,
                             26, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(12, "PCA12", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(12, "PCA12", 0,
                             27, UNIPHIER_PIN_DRV_4_8,
                             27, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(13, "PCA13", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(13, "PCA13", 0,
                             28, UNIPHIER_PIN_DRV_4_8,
                             28, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(14, "PCA14", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(14, "PCA14", 0,
                             29, UNIPHIER_PIN_DRV_4_8,
                             29, UNIPHIER_PIN_PULL_DOWN),
        UNIPHIER_PINCTRL_PIN(15, "XNFRE_GB", UNIPHIER_PIN_IECTRL_NONE,
@@ -118,199 +118,199 @@ static const struct pinctrl_pin_desc ph1_sld8_pins[] = {
        UNIPHIER_PINCTRL_PIN(31, "NFD7_GB", UNIPHIER_PIN_IECTRL_NONE,
                             36, UNIPHIER_PIN_DRV_8_12_16_20,
                             128, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(32, "SDCLK", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(32, "SDCLK", 8,
                             40, UNIPHIER_PIN_DRV_8_12_16_20,
                             -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(33, "SDCMD", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(33, "SDCMD", 8,
                             44, UNIPHIER_PIN_DRV_8_12_16_20,
                             -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(34, "SDDAT0", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(34, "SDDAT0", 8,
                             48, UNIPHIER_PIN_DRV_8_12_16_20,
                             -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(35, "SDDAT1", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(35, "SDDAT1", 8,
                             52, UNIPHIER_PIN_DRV_8_12_16_20,
                             -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(36, "SDDAT2", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(36, "SDDAT2", 8,
                             56, UNIPHIER_PIN_DRV_8_12_16_20,
                             -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(37, "SDDAT3", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(37, "SDDAT3", 8,
                             60, UNIPHIER_PIN_DRV_8_12_16_20,
                             -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(38, "SDCD", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(38, "SDCD", 8,
                             -1, UNIPHIER_PIN_DRV_FIXED_4,
                             129, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(39, "SDWP", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(39, "SDWP", 8,
                             -1, UNIPHIER_PIN_DRV_FIXED_4,
                             130, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(40, "SDVOLC", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(40, "SDVOLC", 9,
                             -1, UNIPHIER_PIN_DRV_FIXED_4,
                             131, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(41, "USB0VBUS", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(41, "USB0VBUS", 0,
                             37, UNIPHIER_PIN_DRV_4_8,
                             37, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(42, "USB0OD", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(42, "USB0OD", 0,
                             38, UNIPHIER_PIN_DRV_4_8,
                             38, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(43, "USB1VBUS", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(43, "USB1VBUS", 0,
                             39, UNIPHIER_PIN_DRV_4_8,
                             39, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(44, "USB1OD", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(44, "USB1OD", 0,
                             40, UNIPHIER_PIN_DRV_4_8,
                             40, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(45, "PCRESET", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(45, "PCRESET", 0,
                             41, UNIPHIER_PIN_DRV_4_8,
                             41, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(46, "PCREG", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(46, "PCREG", 0,
                             42, UNIPHIER_PIN_DRV_4_8,
                             42, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(47, "PCCE2", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(47, "PCCE2", 0,
                             43, UNIPHIER_PIN_DRV_4_8,
                             43, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(48, "PCVS1", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(48, "PCVS1", 0,
                             44, UNIPHIER_PIN_DRV_4_8,
                             44, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(49, "PCCD2", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(49, "PCCD2", 0,
                             45, UNIPHIER_PIN_DRV_4_8,
                             45, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(50, "PCCD1", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(50, "PCCD1", 0,
                             46, UNIPHIER_PIN_DRV_4_8,
                             46, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(51, "PCREADY", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(51, "PCREADY", 0,
                             47, UNIPHIER_PIN_DRV_4_8,
                             47, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(52, "PCDOE", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(52, "PCDOE", 0,
                             48, UNIPHIER_PIN_DRV_4_8,
                             48, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(53, "PCCE1", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(53, "PCCE1", 0,
                             49, UNIPHIER_PIN_DRV_4_8,
                             49, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(54, "PCWE", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(54, "PCWE", 0,
                             50, UNIPHIER_PIN_DRV_4_8,
                             50, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(55, "PCOE", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(55, "PCOE", 0,
                             51, UNIPHIER_PIN_DRV_4_8,
                             51, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(56, "PCWAIT", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(56, "PCWAIT", 0,
                             52, UNIPHIER_PIN_DRV_4_8,
                             52, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(57, "PCIOWR", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(57, "PCIOWR", 0,
                             53, UNIPHIER_PIN_DRV_4_8,
                             53, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(58, "PCIORD", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(58, "PCIORD", 0,
                             54, UNIPHIER_PIN_DRV_4_8,
                             54, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(59, "HS0DIN0", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(59, "HS0DIN0", 0,
                             55, UNIPHIER_PIN_DRV_4_8,
                             55, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(60, "HS0DIN1", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(60, "HS0DIN1", 0,
                             56, UNIPHIER_PIN_DRV_4_8,
                             56, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(61, "HS0DIN2", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(61, "HS0DIN2", 0,
                             57, UNIPHIER_PIN_DRV_4_8,
                             57, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(62, "HS0DIN3", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(62, "HS0DIN3", 0,
                             58, UNIPHIER_PIN_DRV_4_8,
                             58, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(63, "HS0DIN4", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(63, "HS0DIN4", 0,
                             59, UNIPHIER_PIN_DRV_4_8,
                             59, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(64, "HS0DIN5", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(64, "HS0DIN5", 0,
                             60, UNIPHIER_PIN_DRV_4_8,
                             60, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(65, "HS0DIN6", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(65, "HS0DIN6", 0,
                             61, UNIPHIER_PIN_DRV_4_8,
                             61, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(66, "HS0DIN7", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(66, "HS0DIN7", 0,
                             62, UNIPHIER_PIN_DRV_4_8,
                             62, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(67, "HS0BCLKIN", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(67, "HS0BCLKIN", 0,
                             63, UNIPHIER_PIN_DRV_4_8,
                             63, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(68, "HS0VALIN", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(68, "HS0VALIN", 0,
                             64, UNIPHIER_PIN_DRV_4_8,
                             64, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(69, "HS0SYNCIN", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(69, "HS0SYNCIN", 0,
                             65, UNIPHIER_PIN_DRV_4_8,
                             65, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(70, "HSDOUT0", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(70, "HSDOUT0", 0,
                             66, UNIPHIER_PIN_DRV_4_8,
                             66, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(71, "HSDOUT1", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(71, "HSDOUT1", 0,
                             67, UNIPHIER_PIN_DRV_4_8,
                             67, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(72, "HSDOUT2", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(72, "HSDOUT2", 0,
                             68, UNIPHIER_PIN_DRV_4_8,
                             68, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(73, "HSDOUT3", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(73, "HSDOUT3", 0,
                             69, UNIPHIER_PIN_DRV_4_8,
                             69, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(74, "HSDOUT4", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(74, "HSDOUT4", 0,
                             70, UNIPHIER_PIN_DRV_4_8,
                             70, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(75, "HSDOUT5", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(75, "HSDOUT5", 0,
                             71, UNIPHIER_PIN_DRV_4_8,
                             71, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(76, "HSDOUT6", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(76, "HSDOUT6", 0,
                             72, UNIPHIER_PIN_DRV_4_8,
                             72, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(77, "HSDOUT7", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(77, "HSDOUT7", 0,
                             73, UNIPHIER_PIN_DRV_4_8,
                             73, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(78, "HSBCLKOUT", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(78, "HSBCLKOUT", 0,
                             74, UNIPHIER_PIN_DRV_4_8,
                             74, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(79, "HSVALOUT", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(79, "HSVALOUT", 0,
                             75, UNIPHIER_PIN_DRV_4_8,
                             75, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(80, "HSSYNCOUT", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(80, "HSSYNCOUT", 0,
                             76, UNIPHIER_PIN_DRV_4_8,
                             76, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(81, "HS1DIN0", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(81, "HS1DIN0", 0,
                             77, UNIPHIER_PIN_DRV_4_8,
                             77, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(82, "HS1DIN1", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(82, "HS1DIN1", 0,
                             78, UNIPHIER_PIN_DRV_4_8,
                             78, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(83, "HS1DIN2", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(83, "HS1DIN2", 0,
                             79, UNIPHIER_PIN_DRV_4_8,
                             79, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(84, "HS1DIN3", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(84, "HS1DIN3", 0,
                             80, UNIPHIER_PIN_DRV_4_8,
                             80, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(85, "HS1DIN4", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(85, "HS1DIN4", 0,
                             81, UNIPHIER_PIN_DRV_4_8,
                             81, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(86, "HS1DIN5", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(86, "HS1DIN5", 0,
                             82, UNIPHIER_PIN_DRV_4_8,
                             82, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(87, "HS1DIN6", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(87, "HS1DIN6", 0,
                             83, UNIPHIER_PIN_DRV_4_8,
                             83, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(88, "HS1DIN7", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(88, "HS1DIN7", 0,
                             84, UNIPHIER_PIN_DRV_4_8,
                             84, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(89, "HS1BCLKIN", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(89, "HS1BCLKIN", 0,
                             85, UNIPHIER_PIN_DRV_4_8,
                             85, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(90, "HS1VALIN", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(90, "HS1VALIN", 0,
                             86, UNIPHIER_PIN_DRV_4_8,
                             86, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(91, "HS1SYNCIN", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(91, "HS1SYNCIN", 0,
                             87, UNIPHIER_PIN_DRV_4_8,
                             87, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(92, "AGCI", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(92, "AGCI", 3,
                             -1, UNIPHIER_PIN_DRV_FIXED_4,
                             132, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(93, "AGCR", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(93, "AGCR", 4,
                             -1, UNIPHIER_PIN_DRV_FIXED_4,
                             133, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(94, "AGCBS", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(94, "AGCBS", 5,
                             -1, UNIPHIER_PIN_DRV_FIXED_4,
                             134, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(95, "IECOUT", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(95, "IECOUT", 0,
                             88, UNIPHIER_PIN_DRV_4_8,
                             88, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(96, "ASMCK", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(96, "ASMCK", 0,
                             89, UNIPHIER_PIN_DRV_4_8,
                             89, UNIPHIER_PIN_PULL_DOWN),
        UNIPHIER_PINCTRL_PIN(97, "ABCKO", UNIPHIER_PIN_IECTRL_NONE,
@@ -325,31 +325,31 @@ static const struct pinctrl_pin_desc ph1_sld8_pins[] = {
        UNIPHIER_PINCTRL_PIN(100, "ASDOUT1", UNIPHIER_PIN_IECTRL_NONE,
                             93, UNIPHIER_PIN_DRV_4_8,
                             93, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(101, "ARCOUT", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(101, "ARCOUT", 0,
                             94, UNIPHIER_PIN_DRV_4_8,
                             94, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(102, "SDA0", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(102, "SDA0", 10,
                             -1, UNIPHIER_PIN_DRV_FIXED_4,
                             -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(103, "SCL0", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(103, "SCL0", 10,
                             -1, UNIPHIER_PIN_DRV_FIXED_4,
                             -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(104, "SDA1", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(104, "SDA1", 11,
                             -1, UNIPHIER_PIN_DRV_FIXED_4,
                             -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(105, "SCL1", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(105, "SCL1", 11,
                             -1, UNIPHIER_PIN_DRV_FIXED_4,
                             -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(106, "DMDSDA0", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(106, "DMDSDA0", 12,
                             -1, UNIPHIER_PIN_DRV_FIXED_4,
                             -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(107, "DMDSCL0", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(107, "DMDSCL0", 12,
                             -1, UNIPHIER_PIN_DRV_FIXED_4,
                             -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(108, "DMDSDA1", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(108, "DMDSDA1", 13,
                             -1, UNIPHIER_PIN_DRV_FIXED_4,
                             -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(109, "DMDSCL1", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(109, "DMDSCL1", 13,
                             -1, UNIPHIER_PIN_DRV_FIXED_4,
                             -1, UNIPHIER_PIN_PULL_NONE),
        UNIPHIER_PINCTRL_PIN(110, "SBO0", UNIPHIER_PIN_IECTRL_NONE,
@@ -358,76 +358,76 @@ static const struct pinctrl_pin_desc ph1_sld8_pins[] = {
        UNIPHIER_PINCTRL_PIN(111, "SBI0", UNIPHIER_PIN_IECTRL_NONE,
                             96, UNIPHIER_PIN_DRV_4_8,
                             96, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(112, "SBO1", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(112, "SBO1", 0,
                             97, UNIPHIER_PIN_DRV_4_8,
                             97, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(113, "SBI1", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(113, "SBI1", 0,
                             98, UNIPHIER_PIN_DRV_4_8,
                             98, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(114, "TXD1", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(114, "TXD1", 0,
                             99, UNIPHIER_PIN_DRV_4_8,
                             99, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(115, "RXD1", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(115, "RXD1", 0,
                             100, UNIPHIER_PIN_DRV_4_8,
                             100, UNIPHIER_PIN_PULL_UP),
-       UNIPHIER_PINCTRL_PIN(116, "HIN", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(116, "HIN", 1,
                             -1, UNIPHIER_PIN_DRV_FIXED_5,
                             -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(117, "VIN", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(117, "VIN", 2,
                             -1, UNIPHIER_PIN_DRV_FIXED_5,
                             -1, UNIPHIER_PIN_PULL_NONE),
-       UNIPHIER_PINCTRL_PIN(118, "TCON0", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(118, "TCON0", 0,
                             101, UNIPHIER_PIN_DRV_4_8,
                             101, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(119, "TCON1", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(119, "TCON1", 0,
                             102, UNIPHIER_PIN_DRV_4_8,
                             102, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(120, "TCON2", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(120, "TCON2", 0,
                             103, UNIPHIER_PIN_DRV_4_8,
                             103, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(121, "TCON3", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(121, "TCON3", 0,
                             104, UNIPHIER_PIN_DRV_4_8,
                             104, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(122, "TCON4", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(122, "TCON4", 0,
                             105, UNIPHIER_PIN_DRV_4_8,
                             105, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(123, "TCON5", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(123, "TCON5", 0,
                             106, UNIPHIER_PIN_DRV_4_8,
                             106, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(124, "TCON6", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(124, "TCON6", 0,
                             107, UNIPHIER_PIN_DRV_4_8,
                             107, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(125, "TCON7", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(125, "TCON7", 0,
                             108, UNIPHIER_PIN_DRV_4_8,
                             108, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(126, "TCON8", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(126, "TCON8", 0,
                             109, UNIPHIER_PIN_DRV_4_8,
                             109, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(127, "PWMA", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(127, "PWMA", 0,
                             110, UNIPHIER_PIN_DRV_4_8,
                             110, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(128, "XIRQ0", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(128, "XIRQ0", 0,
                             111, UNIPHIER_PIN_DRV_4_8,
                             111, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(129, "XIRQ1", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(129, "XIRQ1", 0,
                             112, UNIPHIER_PIN_DRV_4_8,
                             112, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(130, "XIRQ2", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(130, "XIRQ2", 0,
                             113, UNIPHIER_PIN_DRV_4_8,
                             113, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(131, "XIRQ3", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(131, "XIRQ3", 0,
                             114, UNIPHIER_PIN_DRV_4_8,
                             114, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(132, "XIRQ4", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(132, "XIRQ4", 0,
                             115, UNIPHIER_PIN_DRV_4_8,
                             115, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(133, "XIRQ5", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(133, "XIRQ5", 0,
                             116, UNIPHIER_PIN_DRV_4_8,
                             116, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(134, "XIRQ6", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(134, "XIRQ6", 0,
                             117, UNIPHIER_PIN_DRV_4_8,
                             117, UNIPHIER_PIN_PULL_DOWN),
-       UNIPHIER_PINCTRL_PIN(135, "XIRQ7", UNIPHIER_PIN_IECTRL_NONE,
+       UNIPHIER_PINCTRL_PIN(135, "XIRQ7", 0,
                             118, UNIPHIER_PIN_DRV_4_8,
                             118, UNIPHIER_PIN_PULL_DOWN),
 };
index abdaed34c7285116ffb573102880d55fafdfa8c1..131fee2b093eadde86ba6c0b0fc53be458150e82 100644 (file)
@@ -126,6 +126,24 @@ static const struct dmi_system_id asus_quirks[] = {
                },
                .driver_data = &quirk_asus_wapf4,
        },
+       {
+               .callback = dmi_matched,
+               .ident = "ASUSTeK COMPUTER INC. X456UA",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "X456UA"),
+               },
+               .driver_data = &quirk_asus_wapf4,
+       },
+       {
+               .callback = dmi_matched,
+               .ident = "ASUSTeK COMPUTER INC. X456UF",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "X456UF"),
+               },
+               .driver_data = &quirk_asus_wapf4,
+       },
        {
                .callback = dmi_matched,
                .ident = "ASUSTeK COMPUTER INC. X501U",
index 06697315a0887f6493c0f55185b864c12f8bc76e..fb4dd7b3ee711f9ba9b42b4384331c1df9e32fc0 100644 (file)
@@ -54,8 +54,9 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4");
 #define HPWMI_HARDWARE_QUERY 0x4
 #define HPWMI_WIRELESS_QUERY 0x5
 #define HPWMI_BIOS_QUERY 0x9
+#define HPWMI_FEATURE_QUERY 0xb
 #define HPWMI_HOTKEY_QUERY 0xc
-#define HPWMI_FEATURE_QUERY 0xd
+#define HPWMI_FEATURE2_QUERY 0xd
 #define HPWMI_WIRELESS2_QUERY 0x1b
 #define HPWMI_POSTCODEERROR_QUERY 0x2a
 
@@ -295,25 +296,33 @@ static int hp_wmi_tablet_state(void)
        return (state & 0x4) ? 1 : 0;
 }
 
-static int __init hp_wmi_bios_2009_later(void)
+static int __init hp_wmi_bios_2008_later(void)
 {
        int state = 0;
        int ret = hp_wmi_perform_query(HPWMI_FEATURE_QUERY, 0, &state,
                                       sizeof(state), sizeof(state));
-       if (ret)
-               return ret;
+       if (!ret)
+               return 1;
 
-       return (state & 0x10) ? 1 : 0;
+       return (ret == HPWMI_RET_UNKNOWN_CMDTYPE) ? 0 : -ENXIO;
 }
 
-static int hp_wmi_enable_hotkeys(void)
+static int __init hp_wmi_bios_2009_later(void)
 {
-       int ret;
-       int query = 0x6e;
+       int state = 0;
+       int ret = hp_wmi_perform_query(HPWMI_FEATURE2_QUERY, 0, &state,
+                                      sizeof(state), sizeof(state));
+       if (!ret)
+               return 1;
 
-       ret = hp_wmi_perform_query(HPWMI_BIOS_QUERY, 1, &query, sizeof(query),
-                                  0);
+       return (ret == HPWMI_RET_UNKNOWN_CMDTYPE) ? 0 : -ENXIO;
+}
 
+static int __init hp_wmi_enable_hotkeys(void)
+{
+       int value = 0x6e;
+       int ret = hp_wmi_perform_query(HPWMI_BIOS_QUERY, 1, &value,
+                                      sizeof(value), 0);
        if (ret)
                return -EINVAL;
        return 0;
@@ -663,7 +672,7 @@ static int __init hp_wmi_input_setup(void)
                            hp_wmi_tablet_state());
        input_sync(hp_wmi_input_dev);
 
-       if (hp_wmi_bios_2009_later() == 4)
+       if (!hp_wmi_bios_2009_later() && hp_wmi_bios_2008_later())
                hp_wmi_enable_hotkeys();
 
        status = wmi_install_notify_handler(HPWMI_EVENT_GUID, hp_wmi_notify, NULL);
index 6740c513919cc153f522a0c72e3fd4e183dab16a..f2372f400ddbb406927efc71c843c05a0222c4c4 100644 (file)
@@ -938,7 +938,7 @@ static int toshiba_usb_sleep_music_get(struct toshiba_acpi_dev *dev, u32 *state)
        else if (result == TOS_NOT_SUPPORTED)
                return -ENODEV;
 
-       return result = TOS_SUCCESS ? 0 : -EIO;
+       return result == TOS_SUCCESS ? 0 : -EIO;
 }
 
 static int toshiba_usb_sleep_music_set(struct toshiba_acpi_dev *dev, u32 state)
@@ -2398,11 +2398,9 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
        if (error)
                return error;
 
-       error = toshiba_hotkey_event_type_get(dev, &events_type);
-       if (error) {
-               pr_err("Unable to query Hotkey Event Type\n");
-               return error;
-       }
+       if (toshiba_hotkey_event_type_get(dev, &events_type))
+               pr_notice("Unable to query Hotkey Event Type\n");
+
        dev->hotkey_event_type = events_type;
 
        dev->hotkey_dev = input_allocate_device();
index aac47573f9ed83e4c42ea84aef9c3940644e4db1..eb391a2818330e9423f2030722a041eddedc9130 100644 (file)
@@ -194,34 +194,6 @@ static bool wmi_parse_guid(const u8 *src, u8 *dest)
        return true;
 }
 
-/*
- * Convert a raw GUID to the ACII string representation
- */
-static int wmi_gtoa(const char *in, char *out)
-{
-       int i;
-
-       for (i = 3; i >= 0; i--)
-               out += sprintf(out, "%02X", in[i] & 0xFF);
-
-       out += sprintf(out, "-");
-       out += sprintf(out, "%02X", in[5] & 0xFF);
-       out += sprintf(out, "%02X", in[4] & 0xFF);
-       out += sprintf(out, "-");
-       out += sprintf(out, "%02X", in[7] & 0xFF);
-       out += sprintf(out, "%02X", in[6] & 0xFF);
-       out += sprintf(out, "-");
-       out += sprintf(out, "%02X", in[8] & 0xFF);
-       out += sprintf(out, "%02X", in[9] & 0xFF);
-       out += sprintf(out, "-");
-
-       for (i = 10; i <= 15; i++)
-               out += sprintf(out, "%02X", in[i] & 0xFF);
-
-       *out = '\0';
-       return 0;
-}
-
 static bool find_guid(const char *guid_string, struct wmi_block **out)
 {
        char tmp[16], guid_input[16];
@@ -457,11 +429,7 @@ EXPORT_SYMBOL_GPL(wmi_set_block);
 
 static void wmi_dump_wdg(const struct guid_block *g)
 {
-       char guid_string[37];
-
-       wmi_gtoa(g->guid, guid_string);
-
-       pr_info("%s:\n", guid_string);
+       pr_info("%pUL:\n", g->guid);
        pr_info("\tobject_id: %c%c\n", g->object_id[0], g->object_id[1]);
        pr_info("\tnotify_id: %02X\n", g->notify_id);
        pr_info("\treserved: %02X\n", g->reserved);
@@ -661,7 +629,6 @@ EXPORT_SYMBOL_GPL(wmi_has_guid);
 static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
                             char *buf)
 {
-       char guid_string[37];
        struct wmi_block *wblock;
 
        wblock = dev_get_drvdata(dev);
@@ -670,9 +637,7 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
                return strlen(buf);
        }
 
-       wmi_gtoa(wblock->gblock.guid, guid_string);
-
-       return sprintf(buf, "wmi:%s\n", guid_string);
+       return sprintf(buf, "wmi:%pUL\n", wblock->gblock.guid);
 }
 static DEVICE_ATTR_RO(modalias);
 
@@ -695,7 +660,7 @@ static int wmi_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
        if (!wblock)
                return -ENOMEM;
 
-       wmi_gtoa(wblock->gblock.guid, guid_string);
+       sprintf(guid_string, "%pUL", wblock->gblock.guid);
 
        strcpy(&env->buf[env->buflen - 1], "wmi:");
        memcpy(&env->buf[env->buflen - 1 + 4], guid_string, 36);
@@ -721,12 +686,9 @@ static struct class wmi_class = {
 static int wmi_create_device(const struct guid_block *gblock,
                             struct wmi_block *wblock, acpi_handle handle)
 {
-       char guid_string[37];
-
        wblock->dev.class = &wmi_class;
 
-       wmi_gtoa(gblock->guid, guid_string);
-       dev_set_name(&wblock->dev, "%s", guid_string);
+       dev_set_name(&wblock->dev, "%pUL", gblock->guid);
 
        dev_set_drvdata(&wblock->dev, wblock);
 
@@ -877,7 +839,6 @@ static void acpi_wmi_notify(struct acpi_device *device, u32 event)
        struct guid_block *block;
        struct wmi_block *wblock;
        struct list_head *p;
-       char guid_string[37];
 
        list_for_each(p, &wmi_block_list) {
                wblock = list_entry(p, struct wmi_block, list);
@@ -888,8 +849,8 @@ static void acpi_wmi_notify(struct acpi_device *device, u32 event)
                        if (wblock->handler)
                                wblock->handler(event, wblock->handler_data);
                        if (debug_event) {
-                               wmi_gtoa(wblock->gblock.guid, guid_string);
-                               pr_info("DEBUG Event GUID: %s\n", guid_string);
+                               pr_info("DEBUG Event GUID: %pUL\n",
+                                       wblock->gblock.guid);
                        }
 
                        acpi_bus_generate_netlink_event(
index f4f2c1f76c326d9093c9d9ea7587dd189aed5182..74f2d3ff1d7cf4242935974a738f9d1fb2749111 100644 (file)
@@ -91,7 +91,7 @@
 #define TWL4030_MSTATEC_COMPLETE1      0x0b
 #define TWL4030_MSTATEC_COMPLETE4      0x0e
 
-#if IS_ENABLED(CONFIG_TWL4030_MADC)
+#if IS_REACHABLE(CONFIG_TWL4030_MADC)
 /*
  * If AC (Accessory Charger) voltage exceeds 4.5V (MADC 11)
  * then AC is available.
@@ -1057,13 +1057,9 @@ static int twl4030_bci_probe(struct platform_device *pdev)
 
                phynode = of_find_compatible_node(bci->dev->of_node->parent,
                                                  NULL, "ti,twl4030-usb");
-               if (phynode) {
+               if (phynode)
                        bci->transceiver = devm_usb_get_phy_by_node(
                                bci->dev, phynode, &bci->usb_nb);
-                       if (IS_ERR(bci->transceiver) &&
-                           PTR_ERR(bci->transceiver) == -EPROBE_DEFER)
-                               return -EPROBE_DEFER;
-               }
        }
 
        /* Enable interrupts now. */
index 738adfa5332bcdc5f3ef935436dcf79ca512ea62..52ea605f813060e68d92b4c47fcf400701810373 100644 (file)
@@ -318,6 +318,7 @@ static const struct of_device_id of_anatop_regulator_match_tbl[] = {
        { .compatible = "fsl,anatop-regulator", },
        { /* end */ }
 };
+MODULE_DEVICE_TABLE(of, of_anatop_regulator_match_tbl);
 
 static struct platform_driver anatop_regulator_driver = {
        .driver = {
index 01bf3476a79183714f62f67efcf5d8b17b70d497..a9567af7cec02c5a13102be118010e7bb7b1c888 100644 (file)
@@ -192,9 +192,9 @@ static const struct regulator_desc axp22x_regulators[] = {
        AXP_DESC(AXP22X, DCDC3, "dcdc3", "vin3", 600, 1860, 20,
                 AXP22X_DCDC3_V_OUT, 0x3f, AXP22X_PWR_OUT_CTRL1, BIT(3)),
        AXP_DESC(AXP22X, DCDC4, "dcdc4", "vin4", 600, 1540, 20,
-                AXP22X_DCDC4_V_OUT, 0x3f, AXP22X_PWR_OUT_CTRL1, BIT(3)),
+                AXP22X_DCDC4_V_OUT, 0x3f, AXP22X_PWR_OUT_CTRL1, BIT(4)),
        AXP_DESC(AXP22X, DCDC5, "dcdc5", "vin5", 1000, 2550, 50,
-                AXP22X_DCDC5_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(4)),
+                AXP22X_DCDC5_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(5)),
        /* secondary switchable output of DCDC1 */
        AXP_DESC_SW(AXP22X, DC1SW, "dc1sw", "dcdc1", 1600, 3400, 100,
                    AXP22X_DCDC1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(7)),
index 7a85ac9e32c5da9168c1e79d3ae82d230d9dd628..8a34f6acc801531ce8eb16882fed2b04ed4c874c 100644 (file)
@@ -1394,15 +1394,19 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
                return 0;
 
        r = regulator_dev_lookup(dev, rdev->supply_name, &ret);
-       if (ret == -ENODEV) {
-               /*
-                * No supply was specified for this regulator and
-                * there will never be one.
-                */
-               return 0;
-       }
-
        if (!r) {
+               if (ret == -ENODEV) {
+                       /*
+                        * No supply was specified for this regulator and
+                        * there will never be one.
+                        */
+                       return 0;
+               }
+
+               /* Did the lookup explicitly defer for us? */
+               if (ret == -EPROBE_DEFER)
+                       return ret;
+
                if (have_full_constraints()) {
                        r = dummy_regulator_rdev;
                } else {
@@ -1422,11 +1426,10 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
                return ret;
 
        /* Cascade always-on state to supply */
-       if (_regulator_is_enabled(rdev)) {
+       if (_regulator_is_enabled(rdev) && rdev->supply) {
                ret = regulator_enable(rdev->supply);
                if (ret < 0) {
-                       if (rdev->supply)
-                               _regulator_put(rdev->supply);
+                       _regulator_put(rdev->supply);
                        return ret;
                }
        }
index 464018de7e97a346b712cd2187ba190e2ff9e404..7bba8b747f30280cc0f6c72853cc17272ea8d87d 100644 (file)
@@ -394,6 +394,7 @@ static const struct of_device_id regulator_gpio_of_match[] = {
        { .compatible = "regulator-gpio", },
        {},
 };
+MODULE_DEVICE_TABLE(of, regulator_gpio_of_match);
 #endif
 
 static struct platform_driver gpio_regulator_driver = {
index 4fa7bcaf454e85e9c4d239c5b6214e340f873c19..f9d74d63be7c7e6bb88d7cfeb8d4d4046d919002 100644 (file)
@@ -45,6 +45,10 @@ struct pbias_regulator_data {
        int voltage;
 };
 
+struct pbias_of_data {
+       unsigned int offset;
+};
+
 static const unsigned int pbias_volt_table[] = {
        1800000,
        3000000
@@ -102,8 +106,35 @@ static struct of_regulator_match pbias_matches[] = {
 };
 #define PBIAS_NUM_REGS ARRAY_SIZE(pbias_matches)
 
+/* Offset from SCM general area (and syscon) base */
+
+static const struct pbias_of_data pbias_of_data_omap2 = {
+       .offset = 0x230,
+};
+
+static const struct pbias_of_data pbias_of_data_omap3 = {
+       .offset = 0x2b0,
+};
+
+static const struct pbias_of_data pbias_of_data_omap4 = {
+       .offset = 0x60,
+};
+
+static const struct pbias_of_data pbias_of_data_omap5 = {
+       .offset = 0x60,
+};
+
+static const struct pbias_of_data pbias_of_data_dra7 = {
+       .offset = 0xe00,
+};
+
 static const struct of_device_id pbias_of_match[] = {
        { .compatible = "ti,pbias-omap", },
+       { .compatible = "ti,pbias-omap2", .data = &pbias_of_data_omap2, },
+       { .compatible = "ti,pbias-omap3", .data = &pbias_of_data_omap3, },
+       { .compatible = "ti,pbias-omap4", .data = &pbias_of_data_omap4, },
+       { .compatible = "ti,pbias-omap5", .data = &pbias_of_data_omap5, },
+       { .compatible = "ti,pbias-dra7", .data = &pbias_of_data_dra7, },
        {},
 };
 MODULE_DEVICE_TABLE(of, pbias_of_match);
@@ -118,6 +149,9 @@ static int pbias_regulator_probe(struct platform_device *pdev)
        const struct pbias_reg_info *info;
        int ret = 0;
        int count, idx, data_idx = 0;
+       const struct of_device_id *match;
+       const struct pbias_of_data *data;
+       unsigned int offset;
 
        count = of_regulator_match(&pdev->dev, np, pbias_matches,
                                                PBIAS_NUM_REGS);
@@ -133,6 +167,20 @@ static int pbias_regulator_probe(struct platform_device *pdev)
        if (IS_ERR(syscon))
                return PTR_ERR(syscon);
 
+       match = of_match_device(of_match_ptr(pbias_of_match), &pdev->dev);
+       if (match && match->data) {
+               data = match->data;
+               offset = data->offset;
+       } else {
+               res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+               if (!res)
+                       return -EINVAL;
+
+               offset = res->start;
+               dev_WARN(&pdev->dev,
+                        "using legacy dt data for pbias offset\n");
+       }
+
        cfg.regmap = syscon;
        cfg.dev = &pdev->dev;
 
@@ -145,10 +193,6 @@ static int pbias_regulator_probe(struct platform_device *pdev)
                if (!info)
                        return -ENODEV;
 
-               res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-               if (!res)
-                       return -EINVAL;
-
                drvdata[data_idx].syscon = syscon;
                drvdata[data_idx].info = info;
                drvdata[data_idx].desc.name = info->name;
@@ -158,9 +202,9 @@ static int pbias_regulator_probe(struct platform_device *pdev)
                drvdata[data_idx].desc.volt_table = pbias_volt_table;
                drvdata[data_idx].desc.n_voltages = 2;
                drvdata[data_idx].desc.enable_time = info->enable_time;
-               drvdata[data_idx].desc.vsel_reg = res->start;
+               drvdata[data_idx].desc.vsel_reg = offset;
                drvdata[data_idx].desc.vsel_mask = info->vmode;
-               drvdata[data_idx].desc.enable_reg = res->start;
+               drvdata[data_idx].desc.enable_reg = offset;
                drvdata[data_idx].desc.enable_mask = info->enable_mask;
                drvdata[data_idx].desc.enable_val = info->enable;
                drvdata[data_idx].desc.disable_val = info->disable_val;
index 7f97223f95c5bf4aac43f0fc1666e8d0eaa266ee..a02c1b9610396aeb981ff68a8989d57ec6dac6a1 100644 (file)
@@ -73,7 +73,7 @@ static const struct regulator_linear_range dcdc4_ranges[] = {
 };
 
 static struct tps_info tps65218_pmic_regs[] = {
-       TPS65218_INFO(DCDC1, "DCDC1", 850000, 167500),
+       TPS65218_INFO(DCDC1, "DCDC1", 850000, 1675000),
        TPS65218_INFO(DCDC2, "DCDC2", 850000, 1675000),
        TPS65218_INFO(DCDC3, "DCDC3", 900000, 3400000),
        TPS65218_INFO(DCDC4, "DCDC4", 1175000, 3400000),
index bed9d3ee4198359c0933207c517d2656f8ba5cdd..c810cbbd463f0e6949645c4b5139759b8f0ffd92 100644 (file)
@@ -103,6 +103,7 @@ static const struct of_device_id vexpress_regulator_of_match[] = {
        { .compatible = "arm,vexpress-volt", },
        { }
 };
+MODULE_DEVICE_TABLE(of, vexpress_regulator_of_match);
 
 static struct platform_driver vexpress_regulator_driver = {
        .probe = vexpress_regulator_probe,
index f8d8fdb26b72a593260fa67b98337414a684e9b5..e9fae30fafda03d39df228e500d5f70c0a86e048 100644 (file)
@@ -400,12 +400,16 @@ static bool virtio_ccw_kvm_notify(struct virtqueue *vq)
 static int virtio_ccw_read_vq_conf(struct virtio_ccw_device *vcdev,
                                   struct ccw1 *ccw, int index)
 {
+       int ret;
+
        vcdev->config_block->index = index;
        ccw->cmd_code = CCW_CMD_READ_VQ_CONF;
        ccw->flags = 0;
        ccw->count = sizeof(struct vq_config_block);
        ccw->cda = (__u32)(unsigned long)(vcdev->config_block);
-       ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_VQ_CONF);
+       ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_VQ_CONF);
+       if (ret)
+               return ret;
        return vcdev->config_block->num;
 }
 
@@ -503,6 +507,10 @@ static struct virtqueue *virtio_ccw_setup_vq(struct virtio_device *vdev,
                goto out_err;
        }
        info->num = virtio_ccw_read_vq_conf(vcdev, ccw, i);
+       if (info->num < 0) {
+               err = info->num;
+               goto out_err;
+       }
        size = PAGE_ALIGN(vring_size(info->num, KVM_VIRTIO_CCW_RING_ALIGN));
        info->queue = alloc_pages_exact(size, GFP_KERNEL | __GFP_ZERO);
        if (info->queue == NULL) {
index add419d6ff34996ed4aab8a145aee637ee987dbf..a56a7b243e91fae96b05cae0118d96e9d284dd7b 100644 (file)
@@ -212,6 +212,17 @@ static const struct file_operations twa_fops = {
        .llseek         = noop_llseek,
 };
 
+/*
+ * The controllers use an inline buffer instead of a mapped SGL for small,
+ * single entry buffers.  Note that we treat a zero-length transfer like
+ * a mapped SGL.
+ */
+static bool twa_command_mapped(struct scsi_cmnd *cmd)
+{
+       return scsi_sg_count(cmd) != 1 ||
+               scsi_bufflen(cmd) >= TW_MIN_SGL_LENGTH;
+}
+
 /* This function will complete an aen request from the isr */
 static int twa_aen_complete(TW_Device_Extension *tw_dev, int request_id)
 {
@@ -1339,7 +1350,8 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance)
                                }
 
                                /* Now complete the io */
-                               scsi_dma_unmap(cmd);
+                               if (twa_command_mapped(cmd))
+                                       scsi_dma_unmap(cmd);
                                cmd->scsi_done(cmd);
                                tw_dev->state[request_id] = TW_S_COMPLETED;
                                twa_free_request_id(tw_dev, request_id);
@@ -1582,7 +1594,8 @@ static int twa_reset_device_extension(TW_Device_Extension *tw_dev)
                                struct scsi_cmnd *cmd = tw_dev->srb[i];
 
                                cmd->result = (DID_RESET << 16);
-                               scsi_dma_unmap(cmd);
+                               if (twa_command_mapped(cmd))
+                                       scsi_dma_unmap(cmd);
                                cmd->scsi_done(cmd);
                        }
                }
@@ -1765,12 +1778,14 @@ static int twa_scsi_queue_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_
        retval = twa_scsiop_execute_scsi(tw_dev, request_id, NULL, 0, NULL);
        switch (retval) {
        case SCSI_MLQUEUE_HOST_BUSY:
-               scsi_dma_unmap(SCpnt);
+               if (twa_command_mapped(SCpnt))
+                       scsi_dma_unmap(SCpnt);
                twa_free_request_id(tw_dev, request_id);
                break;
        case 1:
                SCpnt->result = (DID_ERROR << 16);
-               scsi_dma_unmap(SCpnt);
+               if (twa_command_mapped(SCpnt))
+                       scsi_dma_unmap(SCpnt);
                done(SCpnt);
                tw_dev->state[request_id] = TW_S_COMPLETED;
                twa_free_request_id(tw_dev, request_id);
@@ -1831,8 +1846,7 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
                /* Map sglist from scsi layer to cmd packet */
 
                if (scsi_sg_count(srb)) {
-                       if ((scsi_sg_count(srb) == 1) &&
-                           (scsi_bufflen(srb) < TW_MIN_SGL_LENGTH)) {
+                       if (!twa_command_mapped(srb)) {
                                if (srb->sc_data_direction == DMA_TO_DEVICE ||
                                    srb->sc_data_direction == DMA_BIDIRECTIONAL)
                                        scsi_sg_copy_to_buffer(srb,
@@ -1905,7 +1919,7 @@ static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int re
 {
        struct scsi_cmnd *cmd = tw_dev->srb[request_id];
 
-       if (scsi_bufflen(cmd) < TW_MIN_SGL_LENGTH &&
+       if (!twa_command_mapped(cmd) &&
            (cmd->sc_data_direction == DMA_FROM_DEVICE ||
             cmd->sc_data_direction == DMA_BIDIRECTIONAL)) {
                if (scsi_sg_count(cmd) == 1) {
index 33c74d3436c947a7f11ca22498206f6efa97fcc2..6bffd91b973a475d614500a077be0034dbf6786f 100644 (file)
@@ -976,13 +976,13 @@ static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
        wake_up(&conn->ehwait);
 }
 
-static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
+static int iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
 {
         struct iscsi_nopout hdr;
        struct iscsi_task *task;
 
        if (!rhdr && conn->ping_task)
-               return;
+               return -EINVAL;
 
        memset(&hdr, 0, sizeof(struct iscsi_nopout));
        hdr.opcode = ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE;
@@ -996,13 +996,16 @@ static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
                hdr.ttt = RESERVED_ITT;
 
        task = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0);
-       if (!task)
+       if (!task) {
                iscsi_conn_printk(KERN_ERR, conn, "Could not send nopout\n");
-       else if (!rhdr) {
+               return -EIO;
+       } else if (!rhdr) {
                /* only track our nops */
                conn->ping_task = task;
                conn->last_ping = jiffies;
        }
+
+       return 0;
 }
 
 static int iscsi_nop_out_rsp(struct iscsi_task *task,
@@ -2092,8 +2095,10 @@ static void iscsi_check_transport_timeouts(unsigned long data)
        if (time_before_eq(last_recv + recv_timeout, jiffies)) {
                /* send a ping to try to provoke some traffic */
                ISCSI_DBG_CONN(conn, "Sending nopout as ping\n");
-               iscsi_send_nopout(conn, NULL);
-               next_timeout = conn->last_ping + (conn->ping_timeout * HZ);
+               if (iscsi_send_nopout(conn, NULL))
+                       next_timeout = jiffies + (1 * HZ);
+               else
+                       next_timeout = conn->last_ping + (conn->ping_timeout * HZ);
        } else
                next_timeout = last_recv + recv_timeout;
 
index 454536c49315dd6f367051bfcb37ea59fb23e2bd..9c780740fb829db69d411c48717415f2ac10cb0e 100644 (file)
@@ -887,6 +887,8 @@ static void mvs_slot_free(struct mvs_info *mvi, u32 rx_desc)
 static void mvs_slot_task_free(struct mvs_info *mvi, struct sas_task *task,
                          struct mvs_slot_info *slot, u32 slot_idx)
 {
+       if (!slot)
+               return;
        if (!slot->task)
                return;
        if (!sas_protocol_ata(task->task_proto))
index edb044a7b56d348a269634212155edce3a89f9b8..e7649ed3f6677e69fe2e3644da24d99de2aa3181 100644 (file)
@@ -111,7 +111,7 @@ static struct scsi_device_handler *scsi_dh_lookup(const char *name)
 
        dh = __scsi_dh_lookup(name);
        if (!dh) {
-               request_module(name);
+               request_module("scsi_dh_%s", name);
                dh = __scsi_dh_lookup(name);
        }
 
@@ -226,16 +226,20 @@ int scsi_dh_add_device(struct scsi_device *sdev)
 
        drv = scsi_dh_find_driver(sdev);
        if (drv)
-               devinfo = scsi_dh_lookup(drv);
+               devinfo = __scsi_dh_lookup(drv);
        if (devinfo)
                err = scsi_dh_handler_attach(sdev, devinfo);
        return err;
 }
 
-void scsi_dh_remove_device(struct scsi_device *sdev)
+void scsi_dh_release_device(struct scsi_device *sdev)
 {
        if (sdev->handler)
                scsi_dh_handler_detach(sdev);
+}
+
+void scsi_dh_remove_device(struct scsi_device *sdev)
+{
        device_remove_file(&sdev->sdev_gendev, &scsi_dh_state_attr);
 }
 
index cbfc5990052b6b2733ae1c8a81467d3a0e9e70f4..126a48c6431e5a5d9798aed3472916b06ef476c8 100644 (file)
@@ -1957,7 +1957,7 @@ static int scsi_mq_prep_fn(struct request *req)
 static void scsi_mq_done(struct scsi_cmnd *cmd)
 {
        trace_scsi_dispatch_cmd_done(cmd);
-       blk_mq_complete_request(cmd->request);
+       blk_mq_complete_request(cmd->request, cmd->request->errors);
 }
 
 static int scsi_queue_rq(struct blk_mq_hw_ctx *hctx,
index 644bb7339b55bd89068e2a1c34a096dab682cb62..4d01cdb1b348306807663467bf56c254f16b94df 100644 (file)
@@ -173,9 +173,11 @@ extern struct async_domain scsi_sd_probe_domain;
 /* scsi_dh.c */
 #ifdef CONFIG_SCSI_DH
 int scsi_dh_add_device(struct scsi_device *sdev);
+void scsi_dh_release_device(struct scsi_device *sdev);
 void scsi_dh_remove_device(struct scsi_device *sdev);
 #else
 static inline int scsi_dh_add_device(struct scsi_device *sdev) { return 0; }
+static inline void scsi_dh_release_device(struct scsi_device *sdev) { }
 static inline void scsi_dh_remove_device(struct scsi_device *sdev) { }
 #endif
 
index b333389f248ffec291958014a39829156a188bd0..dff8fafb741c1bff625131e73e7fe4425375ced2 100644 (file)
@@ -399,6 +399,8 @@ static void scsi_device_dev_release_usercontext(struct work_struct *work)
 
        sdev = container_of(work, struct scsi_device, ew.work);
 
+       scsi_dh_release_device(sdev);
+
        parent = sdev->sdev_gendev.parent;
 
        spin_lock_irqsave(sdev->host->host_lock, flags);
index 043419dcee92306eb93c52b6240df0a48071c272..8e72bcbd3d6d4b4da15f716d74cd89be8906b0a3 100644 (file)
@@ -65,7 +65,7 @@ void intc_set_prio_level(unsigned int irq, unsigned int level)
        raw_spin_unlock_irqrestore(&intc_big_lock, flags);
 }
 
-static void intc_redirect_irq(unsigned int irq, struct irq_desc *desc)
+static void intc_redirect_irq(struct irq_desc *desc)
 {
        generic_handle_irq((unsigned int)irq_desc_get_handler_data(desc));
 }
index 7dff08e2a071377a963e4d095952bcd5f8bbd589..6ce7f0d26dcf0ec914b433cec73cf0c2337fb1e8 100644 (file)
@@ -99,15 +99,7 @@ static inline struct intc_desc_int *get_intc_desc(unsigned int irq)
  */
 static inline void activate_irq(int irq)
 {
-#ifdef CONFIG_ARM
-       /* ARM requires an extra step to clear IRQ_NOREQUEST, which it
-        * sets on behalf of every irq_chip.  Also sets IRQ_NOPROBE.
-        */
-       set_irq_flags(irq, IRQF_VALID);
-#else
-       /* same effect on other architectures */
-       irq_set_noprobe(irq);
-#endif
+       irq_modify_status(irq, IRQ_NOREQUEST, IRQ_NOPROBE);
 }
 
 static inline int intc_handle_int_cmp(const void *a, const void *b)
index bafc51c6f0bacbe2fdb99e033d89a46dd07d37ea..e7899624aa0b637d8602aad96fb7e7439590a286 100644 (file)
@@ -109,7 +109,7 @@ static int add_virq_to_pirq(unsigned int irq, unsigned int virq)
        return 0;
 }
 
-static void intc_virq_handler(unsigned int __irq, struct irq_desc *desc)
+static void intc_virq_handler(struct irq_desc *desc)
 {
        unsigned int irq = irq_desc_get_irq(desc);
        struct irq_data *data = irq_desc_get_irq_data(desc);
@@ -127,7 +127,7 @@ static void intc_virq_handler(unsigned int __irq, struct irq_desc *desc)
                        handle = (unsigned long)irq_desc_get_handler_data(vdesc);
                        addr = INTC_REG(d, _INTC_ADDR_E(handle), 0);
                        if (intc_reg_fns[_INTC_FN(handle)](addr, handle, 0))
-                               generic_handle_irq_desc(entry->irq, vdesc);
+                               generic_handle_irq_desc(vdesc);
                }
        }
 
index d3d1891cda3cf9a891b1714e240e73036109f2ac..25abd4eb7d102113d94c62bf7bbc1b8f935f0ca8 100644 (file)
@@ -35,20 +35,11 @@ static struct pm_clk_notifier_block platform_bus_notifier = {
 static int __init sh_pm_runtime_init(void)
 {
        if (IS_ENABLED(CONFIG_ARCH_SHMOBILE_MULTI)) {
-               if (!of_machine_is_compatible("renesas,emev2") &&
-                   !of_machine_is_compatible("renesas,r7s72100") &&
-#ifndef CONFIG_PM_GENERIC_DOMAINS_OF
-                   !of_machine_is_compatible("renesas,r8a73a4") &&
-                   !of_machine_is_compatible("renesas,r8a7740") &&
-                   !of_machine_is_compatible("renesas,sh73a0") &&
-#endif
-                   !of_machine_is_compatible("renesas,r8a7778") &&
-                   !of_machine_is_compatible("renesas,r8a7779") &&
-                   !of_machine_is_compatible("renesas,r8a7790") &&
-                   !of_machine_is_compatible("renesas,r8a7791") &&
-                   !of_machine_is_compatible("renesas,r8a7792") &&
-                   !of_machine_is_compatible("renesas,r8a7793") &&
-                   !of_machine_is_compatible("renesas,r8a7794"))
+               if (!of_find_compatible_node(NULL, NULL,
+                                            "renesas,cpg-mstp-clocks"))
+                       return 0;
+               if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS_OF) &&
+                   of_find_node_with_property(NULL, "#power-domain-cells"))
                        return 0;
        }
 
index 6792aae9e2e5aca50ffb6657a43b4012214d3709..052aecf298935e8420fc5b6df0069992b5dc4e3b 100644 (file)
@@ -222,9 +222,9 @@ static void __pmu_domain_register(struct pmu_domain *domain,
 }
 
 /* PMU IRQ controller */
-static void pmu_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void pmu_irq_handler(struct irq_desc *desc)
 {
-       struct pmu_data *pmu = irq_get_handler_data(irq);
+       struct pmu_data *pmu = irq_desc_get_handler_data(desc);
        struct irq_chip_generic *gc = pmu->irq_gc;
        struct irq_domain *domain = pmu->irq_domain;
        void __iomem *base = gc->reg_base;
@@ -232,7 +232,7 @@ static void pmu_irq_handler(unsigned int irq, struct irq_desc *desc)
        u32 done = ~0;
 
        if (stat == 0) {
-               handle_bad_irq(irq, desc);
+               handle_bad_irq(desc);
                return;
        }
 
index bb41bd54ac0aceb80de9010dd8011452116356ff..8b9c2a38d1ccd8ae00d9f2642026438d349c8be1 100644 (file)
@@ -88,6 +88,17 @@ config SPI_BCM2835
          is for the regular SPI controller. Slave mode operation is not also
          not supported.
 
+config SPI_BCM2835AUX
+       tristate "BCM2835 SPI auxiliary controller"
+       depends on ARCH_BCM2835 || COMPILE_TEST
+       depends on GPIOLIB
+       help
+         This selects a driver for the Broadcom BCM2835 SPI aux master.
+
+         The BCM2835 contains two types of SPI master controller; the
+         "universal SPI master", and the regular SPI controller.
+         This driver is for the universal/auxiliary SPI controller.
+
 config SPI_BFIN5XX
        tristate "SPI controller driver for ADI Blackfin5xx"
        depends on BLACKFIN && !BF60x
@@ -125,7 +136,7 @@ config SPI_BCM53XX
 
 config SPI_BCM63XX
        tristate "Broadcom BCM63xx SPI controller"
-       depends on BCM63XX
+       depends on BCM63XX || COMPILE_TEST
        help
           Enable support for the SPI controller on the Broadcom BCM63xx SoCs.
 
index 6a7f6f9d0d1c8cd7dbb89cbd1a902d2997264baa..31fb7fb2a0b698dee2dee7e03a733150857f7363 100644 (file)
@@ -15,6 +15,7 @@ obj-$(CONFIG_SPI_ATMEL)                       += spi-atmel.o
 obj-$(CONFIG_SPI_ATH79)                        += spi-ath79.o
 obj-$(CONFIG_SPI_AU1550)               += spi-au1550.o
 obj-$(CONFIG_SPI_BCM2835)              += spi-bcm2835.o
+obj-$(CONFIG_SPI_BCM2835AUX)           += spi-bcm2835aux.o
 obj-$(CONFIG_SPI_BCM53XX)              += spi-bcm53xx.o
 obj-$(CONFIG_SPI_BCM63XX)              += spi-bcm63xx.o
 obj-$(CONFIG_SPI_BCM63XX_HSSPI)                += spi-bcm63xx-hsspi.o
index bf1f9b32c597b502f0d1c51b7f33f64a4996fb25..6165bf21d42750af1f765f2e79bc9a9a51ea734c 100644 (file)
@@ -240,14 +240,9 @@ static int ath79_spi_probe(struct platform_device *pdev)
        sp->bitbang.flags = SPI_CS_HIGH;
 
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (r == NULL) {
-               ret = -ENOENT;
-               goto err_put_master;
-       }
-
-       sp->base = devm_ioremap(&pdev->dev, r->start, resource_size(r));
-       if (!sp->base) {
-               ret = -ENXIO;
+       sp->base = devm_ioremap_resource(&pdev->dev, r);
+       if (IS_ERR(sp->base)) {
+               ret = PTR_ERR(sp->base);
                goto err_put_master;
        }
 
index bf9ed380bb1c0754addbd27aedf7d874cee89ff2..aebad36391c93b36658c52222e761366c111216f 100644 (file)
@@ -773,7 +773,8 @@ static int atmel_spi_next_xfer_dma_submit(struct spi_master *master,
 
        *plen = len;
 
-       if (atmel_spi_dma_slave_config(as, &slave_config, 8))
+       if (atmel_spi_dma_slave_config(as, &slave_config,
+                                      xfer->bits_per_word))
                goto err_exit;
 
        /* Send both scatterlists */
@@ -871,14 +872,7 @@ static int atmel_spi_set_xfer_speed(struct atmel_spi *as,
         * Calculate the lowest divider that satisfies the
         * constraint, assuming div32/fdiv/mbz == 0.
         */
-       if (xfer->speed_hz)
-               scbr = DIV_ROUND_UP(bus_hz, xfer->speed_hz);
-       else
-               /*
-                * This can happend if max_speed is null.
-                * In this case, we set the lowest possible speed
-                */
-               scbr = 0xff;
+       scbr = DIV_ROUND_UP(bus_hz, xfer->speed_hz);
 
        /*
         * If the resulting divider doesn't fit into the
@@ -1300,14 +1294,12 @@ static int atmel_spi_one_transfer(struct spi_master *master,
                return -EINVAL;
        }
 
-       if (xfer->bits_per_word) {
-               asd = spi->controller_state;
-               bits = (asd->csr >> 4) & 0xf;
-               if (bits != xfer->bits_per_word - 8) {
-                       dev_dbg(&spi->dev,
+       asd = spi->controller_state;
+       bits = (asd->csr >> 4) & 0xf;
+       if (bits != xfer->bits_per_word - 8) {
+               dev_dbg(&spi->dev,
                        "you can't yet change bits_per_word in transfers\n");
-                       return -ENOPROTOOPT;
-               }
+               return -ENOPROTOOPT;
        }
 
        /*
@@ -1720,6 +1712,7 @@ static int atmel_spi_runtime_resume(struct device *dev)
        return clk_prepare_enable(as->clk);
 }
 
+#ifdef CONFIG_PM_SLEEP
 static int atmel_spi_suspend(struct device *dev)
 {
        struct spi_master *master = dev_get_drvdata(dev);
@@ -1756,6 +1749,7 @@ static int atmel_spi_resume(struct device *dev)
 
        return ret;
 }
+#endif
 
 static const struct dev_pm_ops atmel_spi_pm_ops = {
        SET_SYSTEM_SLEEP_PM_OPS(atmel_spi_suspend, atmel_spi_resume)
index f45e085c01a616436f7a6b115e69bb8144012463..afd239d6dec1432350b1fdc5cf3e58c43562dff6 100644 (file)
@@ -233,13 +233,12 @@ static int au1550_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t)
        unsigned bpw, hz;
        u32 cfg, stat;
 
-       bpw = spi->bits_per_word;
-       hz = spi->max_speed_hz;
        if (t) {
-               if (t->bits_per_word)
-                       bpw = t->bits_per_word;
-               if (t->speed_hz)
-                       hz = t->speed_hz;
+               bpw = t->bits_per_word;
+               hz = t->speed_hz;
+       } else {
+               bpw = spi->bits_per_word;
+               hz = spi->max_speed_hz;
        }
 
        if (!hz)
index e7874a6171ecdb4b5b5e7c99bb706aaca2135e2d..cf04960cc3e6ca1f5a87ad24f3d88cdbcfaa8a36 100644 (file)
@@ -386,14 +386,14 @@ static bool bcm2835_spi_can_dma(struct spi_master *master,
        /* otherwise we only allow transfers within the same page
         * to avoid wasting time on dma_mapping when it is not practical
         */
-       if (((size_t)tfr->tx_buf & PAGE_MASK) + tfr->len > PAGE_SIZE) {
+       if (((size_t)tfr->tx_buf & (PAGE_SIZE - 1)) + tfr->len > PAGE_SIZE) {
                dev_warn_once(&spi->dev,
                              "Unaligned spi tx-transfer bridging page\n");
                return false;
        }
-       if (((size_t)tfr->rx_buf & PAGE_MASK) + tfr->len > PAGE_SIZE) {
+       if (((size_t)tfr->rx_buf & (PAGE_SIZE - 1)) + tfr->len > PAGE_SIZE) {
                dev_warn_once(&spi->dev,
-                             "Unaligned spi tx-transfer bridging page\n");
+                             "Unaligned spi rx-transfer bridging page\n");
                return false;
        }
 
@@ -777,7 +777,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
                goto out_master_put;
        }
 
-       bs->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
+       bs->irq = platform_get_irq(pdev, 0);
        if (bs->irq <= 0) {
                dev_err(&pdev->dev, "could not get IRQ: %d\n", bs->irq);
                err = bs->irq ? bs->irq : -ENODEV;
@@ -786,6 +786,12 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
 
        clk_prepare_enable(bs->clk);
 
+       bcm2835_dma_init(master, &pdev->dev);
+
+       /* initialise the hardware with the default polarities */
+       bcm2835_wr(bs, BCM2835_SPI_CS,
+                  BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX);
+
        err = devm_request_irq(&pdev->dev, bs->irq, bcm2835_spi_interrupt, 0,
                               dev_name(&pdev->dev), master);
        if (err) {
@@ -793,12 +799,6 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
                goto out_clk_disable;
        }
 
-       bcm2835_dma_init(master, &pdev->dev);
-
-       /* initialise the hardware with the default polarities */
-       bcm2835_wr(bs, BCM2835_SPI_CS,
-                  BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX);
-
        err = devm_spi_register_master(&pdev->dev, master);
        if (err) {
                dev_err(&pdev->dev, "could not register SPI master: %d\n", err);
diff --git a/drivers/spi/spi-bcm2835aux.c b/drivers/spi/spi-bcm2835aux.c
new file mode 100644 (file)
index 0000000..7de6f84
--- /dev/null
@@ -0,0 +1,512 @@
+/*
+ * Driver for Broadcom BCM2835 auxiliary SPI Controllers
+ *
+ * the driver does not rely on the native chipselects at all
+ * but only uses the gpio type chipselects
+ *
+ * Based on: spi-bcm2835.c
+ *
+ * Copyright (C) 2015 Martin Sperl
+ *
+ * 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.
+ */
+
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/of_irq.h>
+#include <linux/regmap.h>
+#include <linux/spi/spi.h>
+#include <linux/spinlock.h>
+
+/*
+ * spi register defines
+ *
+ * note there is garbage in the "official" documentation,
+ * so some data is taken from the file:
+ *   brcm_usrlib/dag/vmcsx/vcinclude/bcm2708_chip/aux_io.h
+ * inside of:
+ *   http://www.broadcom.com/docs/support/videocore/Brcm_Android_ICS_Graphics_Stack.tar.gz
+ */
+
+/* SPI register offsets */
+#define BCM2835_AUX_SPI_CNTL0  0x00
+#define BCM2835_AUX_SPI_CNTL1  0x04
+#define BCM2835_AUX_SPI_STAT   0x08
+#define BCM2835_AUX_SPI_PEEK   0x0C
+#define BCM2835_AUX_SPI_IO     0x20
+#define BCM2835_AUX_SPI_TXHOLD 0x30
+
+/* Bitfields in CNTL0 */
+#define BCM2835_AUX_SPI_CNTL0_SPEED    0xFFF00000
+#define BCM2835_AUX_SPI_CNTL0_SPEED_MAX        0xFFF
+#define BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT      20
+#define BCM2835_AUX_SPI_CNTL0_CS       0x000E0000
+#define BCM2835_AUX_SPI_CNTL0_POSTINPUT        0x00010000
+#define BCM2835_AUX_SPI_CNTL0_VAR_CS   0x00008000
+#define BCM2835_AUX_SPI_CNTL0_VAR_WIDTH        0x00004000
+#define BCM2835_AUX_SPI_CNTL0_DOUTHOLD 0x00003000
+#define BCM2835_AUX_SPI_CNTL0_ENABLE   0x00000800
+#define BCM2835_AUX_SPI_CNTL0_CPHA_IN  0x00000400
+#define BCM2835_AUX_SPI_CNTL0_CLEARFIFO        0x00000200
+#define BCM2835_AUX_SPI_CNTL0_CPHA_OUT 0x00000100
+#define BCM2835_AUX_SPI_CNTL0_CPOL     0x00000080
+#define BCM2835_AUX_SPI_CNTL0_MSBF_OUT 0x00000040
+#define BCM2835_AUX_SPI_CNTL0_SHIFTLEN 0x0000003F
+
+/* Bitfields in CNTL1 */
+#define BCM2835_AUX_SPI_CNTL1_CSHIGH   0x00000700
+#define BCM2835_AUX_SPI_CNTL1_IDLE     0x00000080
+#define BCM2835_AUX_SPI_CNTL1_TXEMPTY  0x00000040
+#define BCM2835_AUX_SPI_CNTL1_MSBF_IN  0x00000002
+#define BCM2835_AUX_SPI_CNTL1_KEEP_IN  0x00000001
+
+/* Bitfields in STAT */
+#define BCM2835_AUX_SPI_STAT_TX_LVL    0xFF000000
+#define BCM2835_AUX_SPI_STAT_RX_LVL    0x00FF0000
+#define BCM2835_AUX_SPI_STAT_TX_FULL   0x00000400
+#define BCM2835_AUX_SPI_STAT_TX_EMPTY  0x00000200
+#define BCM2835_AUX_SPI_STAT_RX_FULL   0x00000100
+#define BCM2835_AUX_SPI_STAT_RX_EMPTY  0x00000080
+#define BCM2835_AUX_SPI_STAT_BUSY      0x00000040
+#define BCM2835_AUX_SPI_STAT_BITCOUNT  0x0000003F
+
+/* timeout values */
+#define BCM2835_AUX_SPI_POLLING_LIMIT_US       30
+#define BCM2835_AUX_SPI_POLLING_JIFFIES                2
+
+#define BCM2835_AUX_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \
+                                 | SPI_NO_CS)
+
+struct bcm2835aux_spi {
+       void __iomem *regs;
+       struct clk *clk;
+       int irq;
+       u32 cntl[2];
+       const u8 *tx_buf;
+       u8 *rx_buf;
+       int tx_len;
+       int rx_len;
+       int pending;
+};
+
+static inline u32 bcm2835aux_rd(struct bcm2835aux_spi *bs, unsigned reg)
+{
+       return readl(bs->regs + reg);
+}
+
+static inline void bcm2835aux_wr(struct bcm2835aux_spi *bs, unsigned reg,
+                                u32 val)
+{
+       writel(val, bs->regs + reg);
+}
+
+static inline void bcm2835aux_rd_fifo(struct bcm2835aux_spi *bs)
+{
+       u32 data;
+       int count = min(bs->rx_len, 3);
+
+       data = bcm2835aux_rd(bs, BCM2835_AUX_SPI_IO);
+       if (bs->rx_buf) {
+               switch (count) {
+               case 4:
+                       *bs->rx_buf++ = (data >> 24) & 0xff;
+                       /* fallthrough */
+               case 3:
+                       *bs->rx_buf++ = (data >> 16) & 0xff;
+                       /* fallthrough */
+               case 2:
+                       *bs->rx_buf++ = (data >> 8) & 0xff;
+                       /* fallthrough */
+               case 1:
+                       *bs->rx_buf++ = (data >> 0) & 0xff;
+                       /* fallthrough - no default */
+               }
+       }
+       bs->rx_len -= count;
+       bs->pending -= count;
+}
+
+static inline void bcm2835aux_wr_fifo(struct bcm2835aux_spi *bs)
+{
+       u32 data;
+       u8 byte;
+       int count;
+       int i;
+
+       /* gather up to 3 bytes to write to the FIFO */
+       count = min(bs->tx_len, 3);
+       data = 0;
+       for (i = 0; i < count; i++) {
+               byte = bs->tx_buf ? *bs->tx_buf++ : 0;
+               data |= byte << (8 * (2 - i));
+       }
+
+       /* and set the variable bit-length */
+       data |= (count * 8) << 24;
+
+       /* and decrement length */
+       bs->tx_len -= count;
+       bs->pending += count;
+
+       /* write to the correct TX-register */
+       if (bs->tx_len)
+               bcm2835aux_wr(bs, BCM2835_AUX_SPI_TXHOLD, data);
+       else
+               bcm2835aux_wr(bs, BCM2835_AUX_SPI_IO, data);
+}
+
+static void bcm2835aux_spi_reset_hw(struct bcm2835aux_spi *bs)
+{
+       /* disable spi clearing fifo and interrupts */
+       bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, 0);
+       bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL0,
+                     BCM2835_AUX_SPI_CNTL0_CLEARFIFO);
+}
+
+static irqreturn_t bcm2835aux_spi_interrupt(int irq, void *dev_id)
+{
+       struct spi_master *master = dev_id;
+       struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
+       irqreturn_t ret = IRQ_NONE;
+
+       /* check if we have data to read */
+       while (bs->rx_len &&
+              (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) &
+                 BCM2835_AUX_SPI_STAT_RX_EMPTY))) {
+               bcm2835aux_rd_fifo(bs);
+               ret = IRQ_HANDLED;
+       }
+
+       /* check if we have data to write */
+       while (bs->tx_len &&
+              (bs->pending < 12) &&
+              (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) &
+                 BCM2835_AUX_SPI_STAT_TX_FULL))) {
+               bcm2835aux_wr_fifo(bs);
+               ret = IRQ_HANDLED;
+       }
+
+       /* and check if we have reached "done" */
+       while (bs->rx_len &&
+              (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) &
+                 BCM2835_AUX_SPI_STAT_BUSY))) {
+               bcm2835aux_rd_fifo(bs);
+               ret = IRQ_HANDLED;
+       }
+
+       /* and if rx_len is 0 then wake up completion and disable spi */
+       if (!bs->rx_len) {
+               bcm2835aux_spi_reset_hw(bs);
+               complete(&master->xfer_completion);
+       }
+
+       /* and return */
+       return ret;
+}
+
+static int __bcm2835aux_spi_transfer_one_irq(struct spi_master *master,
+                                            struct spi_device *spi,
+                                            struct spi_transfer *tfr)
+{
+       struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
+
+       /* enable interrupts */
+       bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1] |
+               BCM2835_AUX_SPI_CNTL1_TXEMPTY |
+               BCM2835_AUX_SPI_CNTL1_IDLE);
+
+       /* and wait for finish... */
+       return 1;
+}
+
+static int bcm2835aux_spi_transfer_one_irq(struct spi_master *master,
+                                          struct spi_device *spi,
+                                          struct spi_transfer *tfr)
+{
+       struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
+
+       /* fill in registers and fifos before enabling interrupts */
+       bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]);
+       bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL0, bs->cntl[0]);
+
+       /* fill in tx fifo with data before enabling interrupts */
+       while ((bs->tx_len) &&
+              (bs->pending < 12) &&
+              (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) &
+                 BCM2835_AUX_SPI_STAT_TX_FULL))) {
+               bcm2835aux_wr_fifo(bs);
+       }
+
+       /* now run the interrupt mode */
+       return __bcm2835aux_spi_transfer_one_irq(master, spi, tfr);
+}
+
+static int bcm2835aux_spi_transfer_one_poll(struct spi_master *master,
+                                           struct spi_device *spi,
+                                       struct spi_transfer *tfr)
+{
+       struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
+       unsigned long timeout;
+       u32 stat;
+
+       /* configure spi */
+       bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]);
+       bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL0, bs->cntl[0]);
+
+       /* set the timeout */
+       timeout = jiffies + BCM2835_AUX_SPI_POLLING_JIFFIES;
+
+       /* loop until finished the transfer */
+       while (bs->rx_len) {
+               /* read status */
+               stat = bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT);
+
+               /* fill in tx fifo with remaining data */
+               if ((bs->tx_len) && (!(stat & BCM2835_AUX_SPI_STAT_TX_FULL))) {
+                       bcm2835aux_wr_fifo(bs);
+                       continue;
+               }
+
+               /* read data from fifo for both cases */
+               if (!(stat & BCM2835_AUX_SPI_STAT_RX_EMPTY)) {
+                       bcm2835aux_rd_fifo(bs);
+                       continue;
+               }
+               if (!(stat & BCM2835_AUX_SPI_STAT_BUSY)) {
+                       bcm2835aux_rd_fifo(bs);
+                       continue;
+               }
+
+               /* there is still data pending to read check the timeout */
+               if (bs->rx_len && time_after(jiffies, timeout)) {
+                       dev_dbg_ratelimited(&spi->dev,
+                                           "timeout period reached: jiffies: %lu remaining tx/rx: %d/%d - falling back to interrupt mode\n",
+                                           jiffies - timeout,
+                                           bs->tx_len, bs->rx_len);
+                       /* forward to interrupt handler */
+                       return __bcm2835aux_spi_transfer_one_irq(master,
+                                                              spi, tfr);
+               }
+       }
+
+       /* Transfer complete - reset SPI HW */
+       bcm2835aux_spi_reset_hw(bs);
+
+       /* and return without waiting for completion */
+       return 0;
+}
+
+static int bcm2835aux_spi_transfer_one(struct spi_master *master,
+                                      struct spi_device *spi,
+                                      struct spi_transfer *tfr)
+{
+       struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
+       unsigned long spi_hz, clk_hz, speed;
+       unsigned long spi_used_hz;
+       unsigned long long xfer_time_us;
+
+       /* calculate the registers to handle
+        *
+        * note that we use the variable data mode, which
+        * is not optimal for longer transfers as we waste registers
+        * resulting (potentially) in more interrupts when transferring
+        * more than 12 bytes
+        */
+       bs->cntl[0] = BCM2835_AUX_SPI_CNTL0_ENABLE |
+                     BCM2835_AUX_SPI_CNTL0_VAR_WIDTH |
+                     BCM2835_AUX_SPI_CNTL0_MSBF_OUT;
+       bs->cntl[1] = BCM2835_AUX_SPI_CNTL1_MSBF_IN;
+
+       /* set clock */
+       spi_hz = tfr->speed_hz;
+       clk_hz = clk_get_rate(bs->clk);
+
+       if (spi_hz >= clk_hz / 2) {
+               speed = 0;
+       } else if (spi_hz) {
+               speed = DIV_ROUND_UP(clk_hz, 2 * spi_hz) - 1;
+               if (speed >  BCM2835_AUX_SPI_CNTL0_SPEED_MAX)
+                       speed = BCM2835_AUX_SPI_CNTL0_SPEED_MAX;
+       } else { /* the slowest we can go */
+               speed = BCM2835_AUX_SPI_CNTL0_SPEED_MAX;
+       }
+       bs->cntl[0] |= speed << BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT;
+
+       spi_used_hz = clk_hz / (2 * (speed + 1));
+
+       /* handle all the modes */
+       if (spi->mode & SPI_CPOL)
+               bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_CPOL;
+       if (spi->mode & SPI_CPHA)
+               bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_CPHA_OUT |
+                              BCM2835_AUX_SPI_CNTL0_CPHA_IN;
+
+       /* set transmit buffers and length */
+       bs->tx_buf = tfr->tx_buf;
+       bs->rx_buf = tfr->rx_buf;
+       bs->tx_len = tfr->len;
+       bs->rx_len = tfr->len;
+       bs->pending = 0;
+
+       /* calculate the estimated time in us the transfer runs
+        * note that there are are 2 idle clocks after each
+        * chunk getting transferred - in our case the chunk size
+        * is 3 bytes, so we approximate this by 9 bits/byte
+        */
+       xfer_time_us = tfr->len * 9 * 1000000;
+       do_div(xfer_time_us, spi_used_hz);
+
+       /* run in polling mode for short transfers */
+       if (xfer_time_us < BCM2835_AUX_SPI_POLLING_LIMIT_US)
+               return bcm2835aux_spi_transfer_one_poll(master, spi, tfr);
+
+       /* run in interrupt mode for all others */
+       return bcm2835aux_spi_transfer_one_irq(master, spi, tfr);
+}
+
+static void bcm2835aux_spi_handle_err(struct spi_master *master,
+                                     struct spi_message *msg)
+{
+       struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
+
+       bcm2835aux_spi_reset_hw(bs);
+}
+
+static int bcm2835aux_spi_probe(struct platform_device *pdev)
+{
+       struct spi_master *master;
+       struct bcm2835aux_spi *bs;
+       struct resource *res;
+       unsigned long clk_hz;
+       int err;
+
+       master = spi_alloc_master(&pdev->dev, sizeof(*bs));
+       if (!master) {
+               dev_err(&pdev->dev, "spi_alloc_master() failed\n");
+               return -ENOMEM;
+       }
+
+       platform_set_drvdata(pdev, master);
+       master->mode_bits = BCM2835_AUX_SPI_MODE_BITS;
+       master->bits_per_word_mask = SPI_BPW_MASK(8);
+       master->num_chipselect = -1;
+       master->transfer_one = bcm2835aux_spi_transfer_one;
+       master->handle_err = bcm2835aux_spi_handle_err;
+       master->dev.of_node = pdev->dev.of_node;
+
+       bs = spi_master_get_devdata(master);
+
+       /* the main area */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       bs->regs = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(bs->regs)) {
+               err = PTR_ERR(bs->regs);
+               goto out_master_put;
+       }
+
+       bs->clk = devm_clk_get(&pdev->dev, NULL);
+       if ((!bs->clk) || (IS_ERR(bs->clk))) {
+               err = PTR_ERR(bs->clk);
+               dev_err(&pdev->dev, "could not get clk: %d\n", err);
+               goto out_master_put;
+       }
+
+       bs->irq = platform_get_irq(pdev, 0);
+       if (bs->irq <= 0) {
+               dev_err(&pdev->dev, "could not get IRQ: %d\n", bs->irq);
+               err = bs->irq ? bs->irq : -ENODEV;
+               goto out_master_put;
+       }
+
+       /* this also enables the HW block */
+       err = clk_prepare_enable(bs->clk);
+       if (err) {
+               dev_err(&pdev->dev, "could not prepare clock: %d\n", err);
+               goto out_master_put;
+       }
+
+       /* just checking if the clock returns a sane value */
+       clk_hz = clk_get_rate(bs->clk);
+       if (!clk_hz) {
+               dev_err(&pdev->dev, "clock returns 0 Hz\n");
+               err = -ENODEV;
+               goto out_clk_disable;
+       }
+
+       /* reset SPI-HW block */
+       bcm2835aux_spi_reset_hw(bs);
+
+       err = devm_request_irq(&pdev->dev, bs->irq,
+                              bcm2835aux_spi_interrupt,
+                              IRQF_SHARED,
+                              dev_name(&pdev->dev), master);
+       if (err) {
+               dev_err(&pdev->dev, "could not request IRQ: %d\n", err);
+               goto out_clk_disable;
+       }
+
+       err = devm_spi_register_master(&pdev->dev, master);
+       if (err) {
+               dev_err(&pdev->dev, "could not register SPI master: %d\n", err);
+               goto out_clk_disable;
+       }
+
+       return 0;
+
+out_clk_disable:
+       clk_disable_unprepare(bs->clk);
+out_master_put:
+       spi_master_put(master);
+       return err;
+}
+
+static int bcm2835aux_spi_remove(struct platform_device *pdev)
+{
+       struct spi_master *master = platform_get_drvdata(pdev);
+       struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
+
+       bcm2835aux_spi_reset_hw(bs);
+
+       /* disable the HW block by releasing the clock */
+       clk_disable_unprepare(bs->clk);
+
+       return 0;
+}
+
+static const struct of_device_id bcm2835aux_spi_match[] = {
+       { .compatible = "brcm,bcm2835-aux-spi", },
+       {}
+};
+MODULE_DEVICE_TABLE(of, bcm2835aux_spi_match);
+
+static struct platform_driver bcm2835aux_spi_driver = {
+       .driver         = {
+               .name           = "spi-bcm2835aux",
+               .of_match_table = bcm2835aux_spi_match,
+       },
+       .probe          = bcm2835aux_spi_probe,
+       .remove         = bcm2835aux_spi_remove,
+};
+module_platform_driver(bcm2835aux_spi_driver);
+
+MODULE_DESCRIPTION("SPI controller driver for Broadcom BCM2835 aux");
+MODULE_AUTHOR("Martin Sperl <kernel@martin.sperl.org>");
+MODULE_LICENSE("GPL v2");
index 1520554978a31373126829025a45f37b75a73702..cc3f938f0a6b67632515ee0606f67417779043e9 100644 (file)
@@ -247,28 +247,19 @@ static int bcm53xxspi_bcma_probe(struct bcma_device *core)
        if (err) {
                spi_master_put(master);
                bcma_set_drvdata(core, NULL);
-               goto out;
+               return err;
        }
 
        /* Broadcom SoCs (at least with the CC rev 42) use SPI for flash only */
        spi_new_device(master, &bcm53xx_info);
 
-out:
-       return err;
-}
-
-static void bcm53xxspi_bcma_remove(struct bcma_device *core)
-{
-       struct bcm53xxspi *b53spi = bcma_get_drvdata(core);
-
-       spi_unregister_master(b53spi->master);
+       return 0;
 }
 
 static struct bcma_driver bcm53xxspi_bcma_driver = {
        .name           = KBUILD_MODNAME,
        .id_table       = bcm53xxspi_bcma_tbl,
        .probe          = bcm53xxspi_bcma_probe,
-       .remove         = bcm53xxspi_bcma_remove,
 };
 
 /**************************************************
index e73e2b052c9ccf0ca3ff2ef46950600aa5ff9f3f..06858e04ec59a8f2e290c398f6f06e2d1b15e28a 100644 (file)
 #include <linux/err.h>
 #include <linux/pm_runtime.h>
 
-#include <bcm63xx_dev_spi.h>
+/* BCM 6338/6348 SPI core */
+#define SPI_6348_RSET_SIZE             64
+#define SPI_6348_CMD                   0x00    /* 16-bits register */
+#define SPI_6348_INT_STATUS            0x02
+#define SPI_6348_INT_MASK_ST           0x03
+#define SPI_6348_INT_MASK              0x04
+#define SPI_6348_ST                    0x05
+#define SPI_6348_CLK_CFG               0x06
+#define SPI_6348_FILL_BYTE             0x07
+#define SPI_6348_MSG_TAIL              0x09
+#define SPI_6348_RX_TAIL               0x0b
+#define SPI_6348_MSG_CTL               0x40    /* 8-bits register */
+#define SPI_6348_MSG_CTL_WIDTH         8
+#define SPI_6348_MSG_DATA              0x41
+#define SPI_6348_MSG_DATA_SIZE         0x3f
+#define SPI_6348_RX_DATA               0x80
+#define SPI_6348_RX_DATA_SIZE          0x3f
+
+/* BCM 3368/6358/6262/6368 SPI core */
+#define SPI_6358_RSET_SIZE             1804
+#define SPI_6358_MSG_CTL               0x00    /* 16-bits register */
+#define SPI_6358_MSG_CTL_WIDTH         16
+#define SPI_6358_MSG_DATA              0x02
+#define SPI_6358_MSG_DATA_SIZE         0x21e
+#define SPI_6358_RX_DATA               0x400
+#define SPI_6358_RX_DATA_SIZE          0x220
+#define SPI_6358_CMD                   0x700   /* 16-bits register */
+#define SPI_6358_INT_STATUS            0x702
+#define SPI_6358_INT_MASK_ST           0x703
+#define SPI_6358_INT_MASK              0x704
+#define SPI_6358_ST                    0x705
+#define SPI_6358_CLK_CFG               0x706
+#define SPI_6358_FILL_BYTE             0x707
+#define SPI_6358_MSG_TAIL              0x709
+#define SPI_6358_RX_TAIL               0x70B
+
+/* Shared SPI definitions */
+
+/* Message configuration */
+#define SPI_FD_RW                      0x00
+#define SPI_HD_W                       0x01
+#define SPI_HD_R                       0x02
+#define SPI_BYTE_CNT_SHIFT             0
+#define SPI_6348_MSG_TYPE_SHIFT                6
+#define SPI_6358_MSG_TYPE_SHIFT                14
+
+/* Command */
+#define SPI_CMD_NOOP                   0x00
+#define SPI_CMD_SOFT_RESET             0x01
+#define SPI_CMD_HARD_RESET             0x02
+#define SPI_CMD_START_IMMEDIATE                0x03
+#define SPI_CMD_COMMAND_SHIFT          0
+#define SPI_CMD_COMMAND_MASK           0x000f
+#define SPI_CMD_DEVICE_ID_SHIFT                4
+#define SPI_CMD_PREPEND_BYTE_CNT_SHIFT 8
+#define SPI_CMD_ONE_BYTE_SHIFT         11
+#define SPI_CMD_ONE_WIRE_SHIFT         12
+#define SPI_DEV_ID_0                   0
+#define SPI_DEV_ID_1                   1
+#define SPI_DEV_ID_2                   2
+#define SPI_DEV_ID_3                   3
+
+/* Interrupt mask */
+#define SPI_INTR_CMD_DONE              0x01
+#define SPI_INTR_RX_OVERFLOW           0x02
+#define SPI_INTR_TX_UNDERFLOW          0x04
+#define SPI_INTR_TX_OVERFLOW           0x08
+#define SPI_INTR_RX_UNDERFLOW          0x10
+#define SPI_INTR_CLEAR_ALL             0x1f
+
+/* Status */
+#define SPI_RX_EMPTY                   0x02
+#define SPI_CMD_BUSY                   0x04
+#define SPI_SERIAL_BUSY                        0x08
+
+/* Clock configuration */
+#define SPI_CLK_20MHZ                  0x00
+#define SPI_CLK_0_391MHZ               0x01
+#define SPI_CLK_0_781MHZ               0x02    /* default */
+#define SPI_CLK_1_563MHZ               0x03
+#define SPI_CLK_3_125MHZ               0x04
+#define SPI_CLK_6_250MHZ               0x05
+#define SPI_CLK_12_50MHZ               0x06
+#define SPI_CLK_MASK                   0x07
+#define SPI_SSOFFTIME_MASK             0x38
+#define SPI_SSOFFTIME_SHIFT            3
+#define SPI_BYTE_SWAP                  0x80
+
+enum bcm63xx_regs_spi {
+       SPI_CMD,
+       SPI_INT_STATUS,
+       SPI_INT_MASK_ST,
+       SPI_INT_MASK,
+       SPI_ST,
+       SPI_CLK_CFG,
+       SPI_FILL_BYTE,
+       SPI_MSG_TAIL,
+       SPI_RX_TAIL,
+       SPI_MSG_CTL,
+       SPI_MSG_DATA,
+       SPI_RX_DATA,
+       SPI_MSG_TYPE_SHIFT,
+       SPI_MSG_CTL_WIDTH,
+       SPI_MSG_DATA_SIZE,
+};
 
 #define BCM63XX_SPI_MAX_PREPEND                15
 
+#define BCM63XX_SPI_MAX_CS             8
+#define BCM63XX_SPI_BUS_NUM            0
+
 struct bcm63xx_spi {
        struct completion       done;
 
@@ -38,6 +145,7 @@ struct bcm63xx_spi {
        int                     irq;
 
        /* Platform data */
+       const unsigned long     *reg_offsets;
        unsigned                fifo_size;
        unsigned int            msg_type_shift;
        unsigned int            msg_ctl_width;
@@ -51,27 +159,35 @@ struct bcm63xx_spi {
 };
 
 static inline u8 bcm_spi_readb(struct bcm63xx_spi *bs,
-                               unsigned int offset)
+                              unsigned int offset)
 {
-       return bcm_readb(bs->regs + bcm63xx_spireg(offset));
+       return readb(bs->regs + bs->reg_offsets[offset]);
 }
 
 static inline u16 bcm_spi_readw(struct bcm63xx_spi *bs,
                                unsigned int offset)
 {
-       return bcm_readw(bs->regs + bcm63xx_spireg(offset));
+#ifdef CONFIG_CPU_BIG_ENDIAN
+       return ioread16be(bs->regs + bs->reg_offsets[offset]);
+#else
+       return readw(bs->regs + bs->reg_offsets[offset]);
+#endif
 }
 
 static inline void bcm_spi_writeb(struct bcm63xx_spi *bs,
                                  u8 value, unsigned int offset)
 {
-       bcm_writeb(value, bs->regs + bcm63xx_spireg(offset));
+       writeb(value, bs->regs + bs->reg_offsets[offset]);
 }
 
 static inline void bcm_spi_writew(struct bcm63xx_spi *bs,
                                  u16 value, unsigned int offset)
 {
-       bcm_writew(value, bs->regs + bcm63xx_spireg(offset));
+#ifdef CONFIG_CPU_BIG_ENDIAN
+       iowrite16be(value, bs->regs + bs->reg_offsets[offset]);
+#else
+       writew(value, bs->regs + bs->reg_offsets[offset]);
+#endif
 }
 
 static const unsigned bcm63xx_spi_freq_table[SPI_CLK_MASK][2] = {
@@ -122,7 +238,6 @@ static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *first,
        struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
        u16 msg_ctl;
        u16 cmd;
-       u8 rx_tail;
        unsigned int i, timeout = 0, prepend_len = 0, len = 0;
        struct spi_transfer *t = first;
        bool do_rx = false;
@@ -314,18 +429,71 @@ static irqreturn_t bcm63xx_spi_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
+static const unsigned long bcm6348_spi_reg_offsets[] = {
+       [SPI_CMD]               = SPI_6348_CMD,
+       [SPI_INT_STATUS]        = SPI_6348_INT_STATUS,
+       [SPI_INT_MASK_ST]       = SPI_6348_INT_MASK_ST,
+       [SPI_INT_MASK]          = SPI_6348_INT_MASK,
+       [SPI_ST]                = SPI_6348_ST,
+       [SPI_CLK_CFG]           = SPI_6348_CLK_CFG,
+       [SPI_FILL_BYTE]         = SPI_6348_FILL_BYTE,
+       [SPI_MSG_TAIL]          = SPI_6348_MSG_TAIL,
+       [SPI_RX_TAIL]           = SPI_6348_RX_TAIL,
+       [SPI_MSG_CTL]           = SPI_6348_MSG_CTL,
+       [SPI_MSG_DATA]          = SPI_6348_MSG_DATA,
+       [SPI_RX_DATA]           = SPI_6348_RX_DATA,
+       [SPI_MSG_TYPE_SHIFT]    = SPI_6348_MSG_TYPE_SHIFT,
+       [SPI_MSG_CTL_WIDTH]     = SPI_6348_MSG_CTL_WIDTH,
+       [SPI_MSG_DATA_SIZE]     = SPI_6348_MSG_DATA_SIZE,
+};
+
+static const unsigned long bcm6358_spi_reg_offsets[] = {
+       [SPI_CMD]               = SPI_6358_CMD,
+       [SPI_INT_STATUS]        = SPI_6358_INT_STATUS,
+       [SPI_INT_MASK_ST]       = SPI_6358_INT_MASK_ST,
+       [SPI_INT_MASK]          = SPI_6358_INT_MASK,
+       [SPI_ST]                = SPI_6358_ST,
+       [SPI_CLK_CFG]           = SPI_6358_CLK_CFG,
+       [SPI_FILL_BYTE]         = SPI_6358_FILL_BYTE,
+       [SPI_MSG_TAIL]          = SPI_6358_MSG_TAIL,
+       [SPI_RX_TAIL]           = SPI_6358_RX_TAIL,
+       [SPI_MSG_CTL]           = SPI_6358_MSG_CTL,
+       [SPI_MSG_DATA]          = SPI_6358_MSG_DATA,
+       [SPI_RX_DATA]           = SPI_6358_RX_DATA,
+       [SPI_MSG_TYPE_SHIFT]    = SPI_6358_MSG_TYPE_SHIFT,
+       [SPI_MSG_CTL_WIDTH]     = SPI_6358_MSG_CTL_WIDTH,
+       [SPI_MSG_DATA_SIZE]     = SPI_6358_MSG_DATA_SIZE,
+};
+
+static const struct platform_device_id bcm63xx_spi_dev_match[] = {
+       {
+               .name = "bcm6348-spi",
+               .driver_data = (unsigned long)bcm6348_spi_reg_offsets,
+       },
+       {
+               .name = "bcm6358-spi",
+               .driver_data = (unsigned long)bcm6358_spi_reg_offsets,
+       },
+       {
+       },
+};
 
 static int bcm63xx_spi_probe(struct platform_device *pdev)
 {
        struct resource *r;
+       const unsigned long *bcm63xx_spireg;
        struct device *dev = &pdev->dev;
-       struct bcm63xx_spi_pdata *pdata = dev_get_platdata(&pdev->dev);
        int irq;
        struct spi_master *master;
        struct clk *clk;
        struct bcm63xx_spi *bs;
        int ret;
 
+       if (!pdev->id_entry->driver_data)
+               return -EINVAL;
+
+       bcm63xx_spireg = (const unsigned long *)pdev->id_entry->driver_data;
+
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
                dev_err(dev, "no irq\n");
@@ -359,7 +527,8 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
 
        bs->irq = irq;
        bs->clk = clk;
-       bs->fifo_size = pdata->fifo_size;
+       bs->reg_offsets = bcm63xx_spireg;
+       bs->fifo_size = bs->reg_offsets[SPI_MSG_DATA_SIZE];
 
        ret = devm_request_irq(&pdev->dev, irq, bcm63xx_spi_interrupt, 0,
                                                        pdev->name, master);
@@ -368,26 +537,16 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
                goto out_err;
        }
 
-       master->bus_num = pdata->bus_num;
-       master->num_chipselect = pdata->num_chipselect;
+       master->bus_num = BCM63XX_SPI_BUS_NUM;
+       master->num_chipselect = BCM63XX_SPI_MAX_CS;
        master->transfer_one_message = bcm63xx_spi_transfer_one;
        master->mode_bits = MODEBITS;
        master->bits_per_word_mask = SPI_BPW_MASK(8);
        master->auto_runtime_pm = true;
-       bs->msg_type_shift = pdata->msg_type_shift;
-       bs->msg_ctl_width = pdata->msg_ctl_width;
-       bs->tx_io = (u8 *)(bs->regs + bcm63xx_spireg(SPI_MSG_DATA));
-       bs->rx_io = (const u8 *)(bs->regs + bcm63xx_spireg(SPI_RX_DATA));
-
-       switch (bs->msg_ctl_width) {
-       case 8:
-       case 16:
-               break;
-       default:
-               dev_err(dev, "unsupported MSG_CTL width: %d\n",
-                        bs->msg_ctl_width);
-               goto out_err;
-       }
+       bs->msg_type_shift = bs->reg_offsets[SPI_MSG_TYPE_SHIFT];
+       bs->msg_ctl_width = bs->reg_offsets[SPI_MSG_CTL_WIDTH];
+       bs->tx_io = (u8 *)(bs->regs + bs->reg_offsets[SPI_MSG_DATA]);
+       bs->rx_io = (const u8 *)(bs->regs + bs->reg_offsets[SPI_RX_DATA]);
 
        /* Initialize hardware */
        ret = clk_prepare_enable(bs->clk);
@@ -467,6 +626,7 @@ static struct platform_driver bcm63xx_spi_driver = {
                .name   = "bcm63xx-spi",
                .pm     = &bcm63xx_spi_pm_ops,
        },
+       .id_table       = bcm63xx_spi_dev_match,
        .probe          = bcm63xx_spi_probe,
        .remove         = bcm63xx_spi_remove,
 };
index a78693189f4580c2929266feed8958fb1e7ea38e..6c967555a56a4d3a030bd374c2ef94151039e44a 100644 (file)
@@ -352,10 +352,7 @@ bfin_sport_spi_pump_transfers(unsigned long data)
        transfer = drv_data->cur_transfer;
        chip = drv_data->cur_chip;
 
-       if (transfer->speed_hz)
-               transfer_speed = bfin_sport_hz_to_spi_baud(transfer->speed_hz);
-       else
-               transfer_speed = chip->baud;
+       transfer_speed = bfin_sport_hz_to_spi_baud(transfer->speed_hz);
        bfin_write(&drv_data->regs->tclkdiv, transfer_speed);
        SSYNC();
 
index a3d65b4f49445d144fcba077ce3413630300e8c8..1e91325bf39c20f0b5fdc368680de06d566fdb6f 100644 (file)
@@ -661,11 +661,7 @@ static void bfin_spi_pump_transfers(unsigned long data)
        message->state = RUNNING_STATE;
        dma_config = 0;
 
-       /* Speed setup (surely valid because already checked) */
-       if (transfer->speed_hz)
-               bfin_write(&drv_data->regs->baud, hz_to_spi_baud(transfer->speed_hz));
-       else
-               bfin_write(&drv_data->regs->baud, chip->baud);
+       bfin_write(&drv_data->regs->baud, hz_to_spi_baud(transfer->speed_hz));
 
        bfin_write(&drv_data->regs->stat, BIT_STAT_CLR);
        bfin_spi_cs_active(drv_data, chip);
index 840a4984d3650e27dcf98713235a67e040b8ca1a..3aa9e6e3dac82d63f1abf58e5b7eb4aacbb8f212 100644 (file)
@@ -24,6 +24,8 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/spi_bitbang.h>
 
+#define SPI_BITBANG_CS_DELAY   100
+
 
 /*----------------------------------------------------------------------*/
 
@@ -180,7 +182,6 @@ int spi_bitbang_setup(struct spi_device *spi)
 {
        struct spi_bitbang_cs   *cs = spi->controller_state;
        struct spi_bitbang      *bitbang;
-       unsigned long           flags;
 
        bitbang = spi_master_get_devdata(spi->master);
 
@@ -210,12 +211,12 @@ int spi_bitbang_setup(struct spi_device *spi)
         */
 
        /* deselect chip (low or high) */
-       spin_lock_irqsave(&bitbang->lock, flags);
+       mutex_lock(&bitbang->lock);
        if (!bitbang->busy) {
                bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
                ndelay(cs->nsecs);
        }
-       spin_unlock_irqrestore(&bitbang->lock, flags);
+       mutex_unlock(&bitbang->lock);
 
        return 0;
 }
@@ -255,122 +256,39 @@ static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t)
 static int spi_bitbang_prepare_hardware(struct spi_master *spi)
 {
        struct spi_bitbang      *bitbang;
-       unsigned long           flags;
 
        bitbang = spi_master_get_devdata(spi);
 
-       spin_lock_irqsave(&bitbang->lock, flags);
+       mutex_lock(&bitbang->lock);
        bitbang->busy = 1;
-       spin_unlock_irqrestore(&bitbang->lock, flags);
+       mutex_unlock(&bitbang->lock);
 
        return 0;
 }
 
 static int spi_bitbang_transfer_one(struct spi_master *master,
-                                   struct spi_message *m)
+                                   struct spi_device *spi,
+                                   struct spi_transfer *transfer)
 {
-       struct spi_bitbang      *bitbang;
-       unsigned                nsecs;
-       struct spi_transfer     *t = NULL;
-       unsigned                cs_change;
-       int                     status;
-       int                     do_setup = -1;
-       struct spi_device       *spi = m->spi;
-
-       bitbang = spi_master_get_devdata(master);
-
-       /* FIXME this is made-up ... the correct value is known to
-        * word-at-a-time bitbang code, and presumably chipselect()
-        * should enforce these requirements too?
-        */
-       nsecs = 100;
-
-       cs_change = 1;
-       status = 0;
-
-       list_for_each_entry(t, &m->transfers, transfer_list) {
-
-               /* override speed or wordsize? */
-               if (t->speed_hz || t->bits_per_word)
-                       do_setup = 1;
-
-               /* init (-1) or override (1) transfer params */
-               if (do_setup != 0) {
-                       if (bitbang->setup_transfer) {
-                               status = bitbang->setup_transfer(spi, t);
-                               if (status < 0)
-                                       break;
-                       }
-                       if (do_setup == -1)
-                               do_setup = 0;
-               }
-
-               /* set up default clock polarity, and activate chip;
-                * this implicitly updates clock and spi modes as
-                * previously recorded for this device via setup().
-                * (and also deselects any other chip that might be
-                * selected ...)
-                */
-               if (cs_change) {
-                       bitbang->chipselect(spi, BITBANG_CS_ACTIVE);
-                       ndelay(nsecs);
-               }
-               cs_change = t->cs_change;
-               if (!t->tx_buf && !t->rx_buf && t->len) {
-                       status = -EINVAL;
-                       break;
-               }
-
-               /* transfer data.  the lower level code handles any
-                * new dma mappings it needs. our caller always gave
-                * us dma-safe buffers.
-                */
-               if (t->len) {
-                       /* REVISIT dma API still needs a designated
-                        * DMA_ADDR_INVALID; ~0 might be better.
-                        */
-                       if (!m->is_dma_mapped)
-                               t->rx_dma = t->tx_dma = 0;
-                       status = bitbang->txrx_bufs(spi, t);
-               }
-               if (status > 0)
-                       m->actual_length += status;
-               if (status != t->len) {
-                       /* always report some kind of error */
-                       if (status >= 0)
-                               status = -EREMOTEIO;
-                       break;
-               }
-               status = 0;
+       struct spi_bitbang *bitbang = spi_master_get_devdata(master);
+       int status = 0;
 
-               /* protocol tweaks before next transfer */
-               if (t->delay_usecs)
-                       udelay(t->delay_usecs);
-
-               if (cs_change &&
-                   !list_is_last(&t->transfer_list, &m->transfers)) {
-                       /* sometimes a short mid-message deselect of the chip
-                        * may be needed to terminate a mode or command
-                        */
-                       ndelay(nsecs);
-                       bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
-                       ndelay(nsecs);
-               }
+       if (bitbang->setup_transfer) {
+               status = bitbang->setup_transfer(spi, transfer);
+               if (status < 0)
+                       goto out;
        }
 
-       m->status = status;
+       if (transfer->len)
+               status = bitbang->txrx_bufs(spi, transfer);
 
-       /* normally deactivate chipselect ... unless no error and
-        * cs_change has hinted that the next message will probably
-        * be for this chip too.
-        */
-       if (!(status == 0 && cs_change)) {
-               ndelay(nsecs);
-               bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
-               ndelay(nsecs);
-       }
+       if (status == transfer->len)
+               status = 0;
+       else if (status >= 0)
+               status = -EREMOTEIO;
 
-       spi_finalize_current_message(master);
+out:
+       spi_finalize_current_transfer(master);
 
        return status;
 }
@@ -378,17 +296,32 @@ static int spi_bitbang_transfer_one(struct spi_master *master,
 static int spi_bitbang_unprepare_hardware(struct spi_master *spi)
 {
        struct spi_bitbang      *bitbang;
-       unsigned long           flags;
 
        bitbang = spi_master_get_devdata(spi);
 
-       spin_lock_irqsave(&bitbang->lock, flags);
+       mutex_lock(&bitbang->lock);
        bitbang->busy = 0;
-       spin_unlock_irqrestore(&bitbang->lock, flags);
+       mutex_unlock(&bitbang->lock);
 
        return 0;
 }
 
+static void spi_bitbang_set_cs(struct spi_device *spi, bool enable)
+{
+       struct spi_bitbang *bitbang = spi_master_get_devdata(spi->master);
+
+       /* SPI core provides CS high / low, but bitbang driver
+        * expects CS active
+        * spi device driver takes care of handling SPI_CS_HIGH
+        */
+       enable = (!!(spi->mode & SPI_CS_HIGH) == enable);
+
+       ndelay(SPI_BITBANG_CS_DELAY);
+       bitbang->chipselect(spi, enable ? BITBANG_CS_ACTIVE :
+                           BITBANG_CS_INACTIVE);
+       ndelay(SPI_BITBANG_CS_DELAY);
+}
+
 /*----------------------------------------------------------------------*/
 
 /**
@@ -427,7 +360,7 @@ int spi_bitbang_start(struct spi_bitbang *bitbang)
        if (!master || !bitbang->chipselect)
                return -EINVAL;
 
-       spin_lock_init(&bitbang->lock);
+       mutex_init(&bitbang->lock);
 
        if (!master->mode_bits)
                master->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags;
@@ -437,7 +370,8 @@ int spi_bitbang_start(struct spi_bitbang *bitbang)
 
        master->prepare_transfer_hardware = spi_bitbang_prepare_hardware;
        master->unprepare_transfer_hardware = spi_bitbang_unprepare_hardware;
-       master->transfer_one_message = spi_bitbang_transfer_one;
+       master->transfer_one = spi_bitbang_transfer_one;
+       master->set_cs = spi_bitbang_set_cs;
 
        if (!bitbang->txrx_bufs) {
                bitbang->use_dma = 0;
index 688956ff5095c26a8c1101dc4740b310627ed294..23f6fffd75e111ee4a77240293e582c7b66446a0 100644 (file)
@@ -420,19 +420,20 @@ static int mcfqspi_probe(struct platform_device *pdev)
        master->auto_runtime_pm = true;
 
        platform_set_drvdata(pdev, master);
+       pm_runtime_enable(&pdev->dev);
 
        status = devm_spi_register_master(&pdev->dev, master);
        if (status) {
                dev_dbg(&pdev->dev, "spi_register_master failed\n");
                goto fail2;
        }
-       pm_runtime_enable(&pdev->dev);
 
        dev_info(&pdev->dev, "Coldfire QSPI bus driver\n");
 
        return 0;
 
 fail2:
+       pm_runtime_disable(&pdev->dev);
        mcfqspi_cs_teardown(mcfqspi);
 fail1:
        clk_disable(mcfqspi->clk);
index 3cf9faa6cc3fe871174ec1b2777472b0ac4c6883..7d3af3eacf57d7c7e82722fadf2f1fdece1a8ed2 100644 (file)
@@ -215,18 +215,10 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value)
        struct davinci_spi_config *spicfg = spi->controller_data;
        u8 chip_sel = spi->chip_select;
        u16 spidat1 = CS_DEFAULT;
-       bool gpio_chipsel = false;
-       int gpio;
 
        dspi = spi_master_get_devdata(spi->master);
        pdata = &dspi->pdata;
 
-       if (spi->cs_gpio >= 0) {
-               /* SPI core parse and update master->cs_gpio */
-               gpio_chipsel = true;
-               gpio = spi->cs_gpio;
-       }
-
        /* program delay transfers if tx_delay is non zero */
        if (spicfg->wdelay)
                spidat1 |= SPIDAT1_WDEL;
@@ -235,11 +227,12 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value)
         * Board specific chip select logic decides the polarity and cs
         * line for the controller
         */
-       if (gpio_chipsel) {
+       if (spi->cs_gpio >= 0) {
                if (value == BITBANG_CS_ACTIVE)
-                       gpio_set_value(gpio, spi->mode & SPI_CS_HIGH);
+                       gpio_set_value(spi->cs_gpio, spi->mode & SPI_CS_HIGH);
                else
-                       gpio_set_value(gpio, !(spi->mode & SPI_CS_HIGH));
+                       gpio_set_value(spi->cs_gpio,
+                               !(spi->mode & SPI_CS_HIGH));
        } else {
                if (value == BITBANG_CS_ACTIVE) {
                        spidat1 |= SPIDAT1_CSHOLD_MASK;
@@ -992,11 +985,12 @@ static int davinci_spi_probe(struct platform_device *pdev)
                goto free_master;
        }
 
-       dspi->irq = platform_get_irq(pdev, 0);
-       if (dspi->irq <= 0) {
+       ret = platform_get_irq(pdev, 0);
+       if (ret == 0)
                ret = -EINVAL;
+       if (ret < 0)
                goto free_master;
-       }
+       dspi->irq = ret;
 
        ret = devm_request_threaded_irq(&pdev->dev, dspi->irq, davinci_spi_irq,
                                dummy_thread_fn, 0, dev_name(&pdev->dev), dspi);
index 7edede6e024ba493ce0dfc7038d83e03eb88ef85..a6d7029a85ac8655ce44423751f2ded3b63b8816 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/of.h>
 #include <linux/of_gpio.h>
 #include <linux/of_platform.h>
+#include <linux/property.h>
 
 #include "spi-dw.h"
 
@@ -74,13 +75,11 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)
 
        dws->max_freq = clk_get_rate(dwsmmio->clk);
 
-       of_property_read_u32(pdev->dev.of_node, "reg-io-width",
-                            &dws->reg_io_width);
+       device_property_read_u32(&pdev->dev, "reg-io-width", &dws->reg_io_width);
 
        num_cs = 4;
 
-       if (pdev->dev.of_node)
-               of_property_read_u32(pdev->dev.of_node, "num-cs", &num_cs);
+       device_property_read_u32(&pdev->dev, "num-cs", &num_cs);
 
        dws->num_cs = num_cs;
 
index 6d331e0db33122b23cfa17f6602618a510efcde1..332ccb0539a77710e3c4783cf2468acd25a8c04f 100644 (file)
 
 #define DRIVER_NAME "dw_spi_pci"
 
-struct dw_spi_pci {
-       struct pci_dev  *pdev;
-       struct dw_spi   dws;
-};
-
 struct spi_pci_desc {
        int     (*setup)(struct dw_spi *);
        u16     num_cs;
@@ -48,7 +43,6 @@ static struct spi_pci_desc spi_pci_mid_desc_2 = {
 
 static int spi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-       struct dw_spi_pci *dwpci;
        struct dw_spi *dws;
        struct spi_pci_desc *desc = (struct spi_pci_desc *)ent->driver_data;
        int pci_bar = 0;
@@ -58,14 +52,10 @@ static int spi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (ret)
                return ret;
 
-       dwpci = devm_kzalloc(&pdev->dev, sizeof(struct dw_spi_pci),
-                       GFP_KERNEL);
-       if (!dwpci)
+       dws = devm_kzalloc(&pdev->dev, sizeof(*dws), GFP_KERNEL);
+       if (!dws)
                return -ENOMEM;
 
-       dwpci->pdev = pdev;
-       dws = &dwpci->dws;
-
        /* Get basic io resource and map it */
        dws->paddr = pci_resource_start(pdev, pci_bar);
 
@@ -74,7 +64,6 @@ static int spi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                return ret;
 
        dws->regs = pcim_iomap_table(pdev)[pci_bar];
-
        dws->irq = pdev->irq;
 
        /*
@@ -99,7 +88,7 @@ static int spi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                return ret;
 
        /* PCI hook and SPI hook use the same drv data */
-       pci_set_drvdata(pdev, dwpci);
+       pci_set_drvdata(pdev, dws);
 
        dev_info(&pdev->dev, "found PCI SPI controller(ID: %04x:%04x)\n",
                pdev->vendor, pdev->device);
@@ -109,26 +98,26 @@ static int spi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 static void spi_pci_remove(struct pci_dev *pdev)
 {
-       struct dw_spi_pci *dwpci = pci_get_drvdata(pdev);
+       struct dw_spi *dws = pci_get_drvdata(pdev);
 
-       dw_spi_remove_host(&dwpci->dws);
+       dw_spi_remove_host(dws);
 }
 
 #ifdef CONFIG_PM_SLEEP
 static int spi_suspend(struct device *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
-       struct dw_spi_pci *dwpci = pci_get_drvdata(pdev);
+       struct dw_spi *dws = pci_get_drvdata(pdev);
 
-       return dw_spi_suspend_host(&dwpci->dws);
+       return dw_spi_suspend_host(dws);
 }
 
 static int spi_resume(struct device *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
-       struct dw_spi_pci *dwpci = pci_get_drvdata(pdev);
+       struct dw_spi *dws = pci_get_drvdata(pdev);
 
-       return dw_spi_resume_host(&dwpci->dws);
+       return dw_spi_resume_host(dws);
 }
 #endif
 
index 4fbfcdc5cb244d6e9f2a7edaba603b7ccd269fb0..882cd6618cd5d0f1225eb6a8e7bbd66d80882f01 100644 (file)
 
 /* Slave spi_dev related */
 struct chip_data {
-       u16 cr0;
        u8 cs;                  /* chip select pin */
-       u8 n_bytes;             /* current is a 1/2/4 byte op */
        u8 tmode;               /* TR/TO/RO/EEPROM */
        u8 type;                /* SPI/SSP/MicroWire */
 
        u8 poll_mode;           /* 1 means use poll mode */
 
-       u32 dma_width;
-       u32 rx_threshold;
-       u32 tx_threshold;
        u8 enable_dma;
-       u8 bits_per_word;
        u16 clk_div;            /* baud rate divider */
        u32 speed_hz;           /* baud rate */
        void (*cs_control)(u32 command);
@@ -289,14 +283,11 @@ static int dw_spi_transfer_one(struct spi_master *master,
        struct chip_data *chip = spi_get_ctldata(spi);
        u8 imask = 0;
        u16 txlevel = 0;
-       u16 clk_div = 0;
-       u32 speed = 0;
-       u32 cr0 = 0;
+       u16 clk_div;
+       u32 cr0;
        int ret;
 
        dws->dma_mapped = 0;
-       dws->n_bytes = chip->n_bytes;
-       dws->dma_width = chip->dma_width;
 
        dws->tx = (void *)transfer->tx_buf;
        dws->tx_end = dws->tx + transfer->len;
@@ -306,37 +297,30 @@ static int dw_spi_transfer_one(struct spi_master *master,
 
        spi_enable_chip(dws, 0);
 
-       cr0 = chip->cr0;
-
        /* Handle per transfer options for bpw and speed */
-       if (transfer->speed_hz) {
-               speed = chip->speed_hz;
-
-               if ((transfer->speed_hz != speed) || !chip->clk_div) {
-                       speed = transfer->speed_hz;
-
-                       /* clk_div doesn't support odd number */
-                       clk_div = (dws->max_freq / speed + 1) & 0xfffe;
+       if (transfer->speed_hz != chip->speed_hz) {
+               /* clk_div doesn't support odd number */
+               clk_div = (dws->max_freq / transfer->speed_hz + 1) & 0xfffe;
 
-                       chip->speed_hz = speed;
-                       chip->clk_div = clk_div;
+               chip->speed_hz = transfer->speed_hz;
+               chip->clk_div = clk_div;
 
-                       spi_set_clk(dws, chip->clk_div);
-               }
+               spi_set_clk(dws, chip->clk_div);
        }
-       if (transfer->bits_per_word) {
-               if (transfer->bits_per_word == 8) {
-                       dws->n_bytes = 1;
-                       dws->dma_width = 1;
-               } else if (transfer->bits_per_word == 16) {
-                       dws->n_bytes = 2;
-                       dws->dma_width = 2;
-               }
-               cr0 = (transfer->bits_per_word - 1)
-                       | (chip->type << SPI_FRF_OFFSET)
-                       | (spi->mode << SPI_MODE_OFFSET)
-                       | (chip->tmode << SPI_TMOD_OFFSET);
+       if (transfer->bits_per_word == 8) {
+               dws->n_bytes = 1;
+               dws->dma_width = 1;
+       } else if (transfer->bits_per_word == 16) {
+               dws->n_bytes = 2;
+               dws->dma_width = 2;
+       } else {
+               return -EINVAL;
        }
+       /* Default SPI mode is SCPOL = 0, SCPH = 0 */
+       cr0 = (transfer->bits_per_word - 1)
+               | (chip->type << SPI_FRF_OFFSET)
+               | (spi->mode << SPI_MODE_OFFSET)
+               | (chip->tmode << SPI_TMOD_OFFSET);
 
        /*
         * Adjust transfer mode if necessary. Requires platform dependent
@@ -439,34 +423,9 @@ static int dw_spi_setup(struct spi_device *spi)
 
                chip->poll_mode = chip_info->poll_mode;
                chip->type = chip_info->type;
-
-               chip->rx_threshold = 0;
-               chip->tx_threshold = 0;
-       }
-
-       if (spi->bits_per_word == 8) {
-               chip->n_bytes = 1;
-               chip->dma_width = 1;
-       } else if (spi->bits_per_word == 16) {
-               chip->n_bytes = 2;
-               chip->dma_width = 2;
-       }
-       chip->bits_per_word = spi->bits_per_word;
-
-       if (!spi->max_speed_hz) {
-               dev_err(&spi->dev, "No max speed HZ parameter\n");
-               return -EINVAL;
        }
 
        chip->tmode = 0; /* Tx & Rx */
-       /* Default SPI mode is SCPOL = 0, SCPH = 0 */
-       chip->cr0 = (chip->bits_per_word - 1)
-                       | (chip->type << SPI_FRF_OFFSET)
-                       | (spi->mode  << SPI_MODE_OFFSET)
-                       | (chip->tmode << SPI_TMOD_OFFSET);
-
-       if (spi->mode & SPI_LOOP)
-               chip->cr0 |= 1 << SPI_SRL_OFFSET;
 
        if (gpio_is_valid(spi->cs_gpio)) {
                ret = gpio_direction_output(spi->cs_gpio,
@@ -524,13 +483,12 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
        dws->master = master;
        dws->type = SSI_MOTO_SPI;
        dws->dma_inited = 0;
-       dws->dma_addr = (dma_addr_t)(dws->paddr + 0x60);
+       dws->dma_addr = (dma_addr_t)(dws->paddr + DW_SPI_DR);
        snprintf(dws->name, sizeof(dws->name), "dw_spi%d", dws->bus_num);
 
-       ret = devm_request_irq(dev, dws->irq, dw_spi_irq, IRQF_SHARED,
-                       dws->name, master);
+       ret = request_irq(dws->irq, dw_spi_irq, IRQF_SHARED, dws->name, master);
        if (ret < 0) {
-               dev_err(&master->dev, "can not get IRQ\n");
+               dev_err(dev, "can not get IRQ\n");
                goto err_free_master;
        }
 
@@ -573,6 +531,7 @@ err_dma_exit:
        if (dws->dma_ops && dws->dma_ops->dma_exit)
                dws->dma_ops->dma_exit(dws);
        spi_enable_chip(dws, 0);
+       free_irq(dws->irq, master);
 err_free_master:
        spi_master_put(master);
        return ret;
@@ -581,28 +540,27 @@ EXPORT_SYMBOL_GPL(dw_spi_add_host);
 
 void dw_spi_remove_host(struct dw_spi *dws)
 {
-       if (!dws)
-               return;
        dw_spi_debugfs_remove(dws);
 
        if (dws->dma_ops && dws->dma_ops->dma_exit)
                dws->dma_ops->dma_exit(dws);
-       spi_enable_chip(dws, 0);
-       /* Disable clk */
-       spi_set_clk(dws, 0);
+
+       spi_shutdown_chip(dws);
+
+       free_irq(dws->irq, dws->master);
 }
 EXPORT_SYMBOL_GPL(dw_spi_remove_host);
 
 int dw_spi_suspend_host(struct dw_spi *dws)
 {
-       int ret = 0;
+       int ret;
 
        ret = spi_master_suspend(dws->master);
        if (ret)
                return ret;
-       spi_enable_chip(dws, 0);
-       spi_set_clk(dws, 0);
-       return ret;
+
+       spi_shutdown_chip(dws);
+       return 0;
 }
 EXPORT_SYMBOL_GPL(dw_spi_suspend_host);
 
index b75ed327d5a29832ad3461cb28da1089ade94cba..35589a270468d6f2dcd7f57ef0c4073cd6fe5721 100644 (file)
@@ -225,6 +225,12 @@ static inline void spi_reset_chip(struct dw_spi *dws)
        spi_enable_chip(dws, 1);
 }
 
+static inline void spi_shutdown_chip(struct dw_spi *dws)
+{
+       spi_enable_chip(dws, 0);
+       spi_set_clk(dws, 0);
+}
+
 /*
  * Each SPI slave device to work with dw_api controller should
  * has such a structure claiming its working mode (poll or PIO/DMA),
index f9deb84e4e551bdd9c42c8ac204c80c18f0f8579..0e5723ab47f0ce023db657c5be0e2274d825c149 100644 (file)
@@ -336,13 +336,20 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
 
        if (config->mode & SPI_CPHA)
                cfg |= MX51_ECSPI_CONFIG_SCLKPHA(config->cs);
+       else
+               cfg &= ~MX51_ECSPI_CONFIG_SCLKPHA(config->cs);
 
        if (config->mode & SPI_CPOL) {
                cfg |= MX51_ECSPI_CONFIG_SCLKPOL(config->cs);
                cfg |= MX51_ECSPI_CONFIG_SCLKCTL(config->cs);
+       } else {
+               cfg &= ~MX51_ECSPI_CONFIG_SCLKPOL(config->cs);
+               cfg &= ~MX51_ECSPI_CONFIG_SCLKCTL(config->cs);
        }
        if (config->mode & SPI_CS_HIGH)
                cfg |= MX51_ECSPI_CONFIG_SSBPOL(config->cs);
+       else
+               cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(config->cs);
 
        writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
        writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);
index 5468fc70dbf8d06432ce1cc1e8b2ef20c96a5a72..2465259f62411b354f5e11fe7f3e854aefd6f04f 100644 (file)
@@ -444,6 +444,7 @@ static const struct of_device_id meson_spifc_dt_match[] = {
        { .compatible = "amlogic,meson6-spifc", },
        { },
 };
+MODULE_DEVICE_TABLE(of, meson_spifc_dt_match);
 
 static struct platform_driver meson_spifc_driver = {
        .probe  = meson_spifc_probe,
index 1e75341689a622916bad62e4429d4ed4c5315fc2..c3ec46cd9f916ea5d362d43b655047b1dd0bff72 100644 (file)
@@ -302,11 +302,9 @@ static int mpc512x_psc_spi_msg_xfer(struct spi_master *master,
        cs_change = 1;
        status = 0;
        list_for_each_entry(t, &m->transfers, transfer_list) {
-               if (t->bits_per_word || t->speed_hz) {
-                       status = mpc512x_psc_spi_transfer_setup(spi, t);
-                       if (status < 0)
-                               break;
-               }
+               status = mpc512x_psc_spi_transfer_setup(spi, t);
+               if (status < 0)
+                       break;
 
                if (cs_change)
                        mpc512x_psc_spi_activate_cs(spi);
index 5f6315c47920efcb42dc52b5c93c26ce60cb7de4..563954a614242718bd125f16f9a3549f783346b8 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/ioport.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_gpio.h>
 #include <linux/platform_device.h>
 #include <linux/platform_data/spi-mt65xx.h>
 #include <linux/pm_runtime.h>
@@ -84,8 +85,9 @@ struct mtk_spi_compatible {
 struct mtk_spi {
        void __iomem *base;
        u32 state;
-       u32 pad_sel;
-       struct clk *spi_clk, *parent_clk;
+       int pad_num;
+       u32 *pad_sel;
+       struct clk *parent_clk, *sel_clk, *spi_clk;
        struct spi_transfer *cur_transfer;
        u32 xfer_len;
        struct scatterlist *tx_sgl, *rx_sgl;
@@ -131,10 +133,28 @@ static void mtk_spi_reset(struct mtk_spi *mdata)
        writel(reg_val, mdata->base + SPI_CMD_REG);
 }
 
-static void mtk_spi_config(struct mtk_spi *mdata,
-                          struct mtk_chip_config *chip_config)
+static int mtk_spi_prepare_message(struct spi_master *master,
+                                  struct spi_message *msg)
 {
+       u16 cpha, cpol;
        u32 reg_val;
+       struct spi_device *spi = msg->spi;
+       struct mtk_chip_config *chip_config = spi->controller_data;
+       struct mtk_spi *mdata = spi_master_get_devdata(master);
+
+       cpha = spi->mode & SPI_CPHA ? 1 : 0;
+       cpol = spi->mode & SPI_CPOL ? 1 : 0;
+
+       reg_val = readl(mdata->base + SPI_CMD_REG);
+       if (cpha)
+               reg_val |= SPI_CMD_CPHA;
+       else
+               reg_val &= ~SPI_CMD_CPHA;
+       if (cpol)
+               reg_val |= SPI_CMD_CPOL;
+       else
+               reg_val &= ~SPI_CMD_CPOL;
+       writel(reg_val, mdata->base + SPI_CMD_REG);
 
        reg_val = readl(mdata->base + SPI_CMD_REG);
 
@@ -170,54 +190,8 @@ static void mtk_spi_config(struct mtk_spi *mdata,
 
        /* pad select */
        if (mdata->dev_comp->need_pad_sel)
-               writel(mdata->pad_sel, mdata->base + SPI_PAD_SEL_REG);
-}
-
-static int mtk_spi_prepare_hardware(struct spi_master *master)
-{
-       struct spi_transfer *trans;
-       struct mtk_spi *mdata = spi_master_get_devdata(master);
-       struct spi_message *msg = master->cur_msg;
-
-       trans = list_first_entry(&msg->transfers, struct spi_transfer,
-                                transfer_list);
-       if (!trans->cs_change) {
-               mdata->state = MTK_SPI_IDLE;
-               mtk_spi_reset(mdata);
-       }
-
-       return 0;
-}
-
-static int mtk_spi_prepare_message(struct spi_master *master,
-                                  struct spi_message *msg)
-{
-       u32 reg_val;
-       u8 cpha, cpol;
-       struct mtk_chip_config *chip_config;
-       struct spi_device *spi = msg->spi;
-       struct mtk_spi *mdata = spi_master_get_devdata(master);
-
-       cpha = spi->mode & SPI_CPHA ? 1 : 0;
-       cpol = spi->mode & SPI_CPOL ? 1 : 0;
-
-       reg_val = readl(mdata->base + SPI_CMD_REG);
-       if (cpha)
-               reg_val |= SPI_CMD_CPHA;
-       else
-               reg_val &= ~SPI_CMD_CPHA;
-       if (cpol)
-               reg_val |= SPI_CMD_CPOL;
-       else
-               reg_val &= ~SPI_CMD_CPOL;
-       writel(reg_val, mdata->base + SPI_CMD_REG);
-
-       chip_config = spi->controller_data;
-       if (!chip_config) {
-               chip_config = (void *)&mtk_default_chip_info;
-               spi->controller_data = chip_config;
-       }
-       mtk_spi_config(mdata, chip_config);
+               writel(mdata->pad_sel[spi->chip_select],
+                      mdata->base + SPI_PAD_SEL_REG);
 
        return 0;
 }
@@ -228,11 +202,15 @@ static void mtk_spi_set_cs(struct spi_device *spi, bool enable)
        struct mtk_spi *mdata = spi_master_get_devdata(spi->master);
 
        reg_val = readl(mdata->base + SPI_CMD_REG);
-       if (!enable)
+       if (!enable) {
                reg_val |= SPI_CMD_PAUSE_EN;
-       else
+               writel(reg_val, mdata->base + SPI_CMD_REG);
+       } else {
                reg_val &= ~SPI_CMD_PAUSE_EN;
-       writel(reg_val, mdata->base + SPI_CMD_REG);
+               writel(reg_val, mdata->base + SPI_CMD_REG);
+               mdata->state = MTK_SPI_IDLE;
+               mtk_spi_reset(mdata);
+       }
 }
 
 static void mtk_spi_prepare_transfer(struct spi_master *master,
@@ -425,6 +403,19 @@ static bool mtk_spi_can_dma(struct spi_master *master,
        return xfer->len > MTK_SPI_MAX_FIFO_SIZE;
 }
 
+static int mtk_spi_setup(struct spi_device *spi)
+{
+       struct mtk_spi *mdata = spi_master_get_devdata(spi->master);
+
+       if (!spi->controller_data)
+               spi->controller_data = (void *)&mtk_default_chip_info;
+
+       if (mdata->dev_comp->need_pad_sel)
+               gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH));
+
+       return 0;
+}
+
 static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
 {
        u32 cmd, reg_val, cnt;
@@ -496,7 +487,7 @@ static int mtk_spi_probe(struct platform_device *pdev)
        struct mtk_spi *mdata;
        const struct of_device_id *of_id;
        struct resource *res;
-       int irq, ret;
+       int i, irq, ret;
 
        master = spi_alloc_master(&pdev->dev, sizeof(*mdata));
        if (!master) {
@@ -509,10 +500,10 @@ static int mtk_spi_probe(struct platform_device *pdev)
        master->mode_bits = SPI_CPOL | SPI_CPHA;
 
        master->set_cs = mtk_spi_set_cs;
-       master->prepare_transfer_hardware = mtk_spi_prepare_hardware;
        master->prepare_message = mtk_spi_prepare_message;
        master->transfer_one = mtk_spi_transfer_one;
        master->can_dma = mtk_spi_can_dma;
+       master->setup = mtk_spi_setup;
 
        of_id = of_match_node(mtk_spi_of_match, pdev->dev.of_node);
        if (!of_id) {
@@ -527,21 +518,34 @@ static int mtk_spi_probe(struct platform_device *pdev)
                master->flags = SPI_MASTER_MUST_TX;
 
        if (mdata->dev_comp->need_pad_sel) {
-               ret = of_property_read_u32(pdev->dev.of_node,
-                                          "mediatek,pad-select",
-                                          &mdata->pad_sel);
-               if (ret) {
-                       dev_err(&pdev->dev, "failed to read pad select: %d\n",
-                               ret);
+               mdata->pad_num = of_property_count_u32_elems(
+                       pdev->dev.of_node,
+                       "mediatek,pad-select");
+               if (mdata->pad_num < 0) {
+                       dev_err(&pdev->dev,
+                               "No 'mediatek,pad-select' property\n");
+                       ret = -EINVAL;
                        goto err_put_master;
                }
 
-               if (mdata->pad_sel > MT8173_SPI_MAX_PAD_SEL) {
-                       dev_err(&pdev->dev, "wrong pad-select: %u\n",
-                               mdata->pad_sel);
-                       ret = -EINVAL;
+               mdata->pad_sel = devm_kmalloc_array(&pdev->dev, mdata->pad_num,
+                                                   sizeof(u32), GFP_KERNEL);
+               if (!mdata->pad_sel) {
+                       ret = -ENOMEM;
                        goto err_put_master;
                }
+
+               for (i = 0; i < mdata->pad_num; i++) {
+                       of_property_read_u32_index(pdev->dev.of_node,
+                                                  "mediatek,pad-select",
+                                                  i, &mdata->pad_sel[i]);
+                       if (mdata->pad_sel[i] > MT8173_SPI_MAX_PAD_SEL) {
+                               dev_err(&pdev->dev, "wrong pad-sel[%d]: %u\n",
+                                       i, mdata->pad_sel[i]);
+                               ret = -EINVAL;
+                               goto err_put_master;
+                       }
+               }
        }
 
        platform_set_drvdata(pdev, master);
@@ -576,13 +580,6 @@ static int mtk_spi_probe(struct platform_device *pdev)
                goto err_put_master;
        }
 
-       mdata->spi_clk = devm_clk_get(&pdev->dev, "spi-clk");
-       if (IS_ERR(mdata->spi_clk)) {
-               ret = PTR_ERR(mdata->spi_clk);
-               dev_err(&pdev->dev, "failed to get spi-clk: %d\n", ret);
-               goto err_put_master;
-       }
-
        mdata->parent_clk = devm_clk_get(&pdev->dev, "parent-clk");
        if (IS_ERR(mdata->parent_clk)) {
                ret = PTR_ERR(mdata->parent_clk);
@@ -590,13 +587,27 @@ static int mtk_spi_probe(struct platform_device *pdev)
                goto err_put_master;
        }
 
+       mdata->sel_clk = devm_clk_get(&pdev->dev, "sel-clk");
+       if (IS_ERR(mdata->sel_clk)) {
+               ret = PTR_ERR(mdata->sel_clk);
+               dev_err(&pdev->dev, "failed to get sel-clk: %d\n", ret);
+               goto err_put_master;
+       }
+
+       mdata->spi_clk = devm_clk_get(&pdev->dev, "spi-clk");
+       if (IS_ERR(mdata->spi_clk)) {
+               ret = PTR_ERR(mdata->spi_clk);
+               dev_err(&pdev->dev, "failed to get spi-clk: %d\n", ret);
+               goto err_put_master;
+       }
+
        ret = clk_prepare_enable(mdata->spi_clk);
        if (ret < 0) {
                dev_err(&pdev->dev, "failed to enable spi_clk (%d)\n", ret);
                goto err_put_master;
        }
 
-       ret = clk_set_parent(mdata->spi_clk, mdata->parent_clk);
+       ret = clk_set_parent(mdata->sel_clk, mdata->parent_clk);
        if (ret < 0) {
                dev_err(&pdev->dev, "failed to clk_set_parent (%d)\n", ret);
                goto err_disable_clk;
@@ -612,6 +623,26 @@ static int mtk_spi_probe(struct platform_device *pdev)
                goto err_put_master;
        }
 
+       if (mdata->dev_comp->need_pad_sel) {
+               if (mdata->pad_num != master->num_chipselect) {
+                       dev_err(&pdev->dev,
+                               "pad_num does not match num_chipselect(%d != %d)\n",
+                               mdata->pad_num, master->num_chipselect);
+                       ret = -EINVAL;
+                       goto err_put_master;
+               }
+
+               for (i = 0; i < master->num_chipselect; i++) {
+                       ret = devm_gpio_request(&pdev->dev, master->cs_gpios[i],
+                                               dev_name(&pdev->dev));
+                       if (ret) {
+                               dev_err(&pdev->dev,
+                                       "can't get CS GPIO %i\n", i);
+                               goto err_put_master;
+                       }
+               }
+       }
+
        return 0;
 
 err_disable_clk:
@@ -630,7 +661,6 @@ static int mtk_spi_remove(struct platform_device *pdev)
        pm_runtime_disable(&pdev->dev);
 
        mtk_spi_reset(mdata);
-       clk_disable_unprepare(mdata->spi_clk);
        spi_master_put(master);
 
        return 0;
index 76656a77ec1213d1db70d6ee98d546bc0f760da9..b5911282a61116c47b0237071df40261831f94ab 100644 (file)
@@ -207,8 +207,7 @@ static int tiny_spi_of_probe(struct platform_device *pdev)
        struct tiny_spi *hw = platform_get_drvdata(pdev);
        struct device_node *np = pdev->dev.of_node;
        unsigned int i;
-       const __be32 *val;
-       int len;
+       u32 val;
 
        if (!np)
                return 0;
@@ -226,13 +225,10 @@ static int tiny_spi_of_probe(struct platform_device *pdev)
                        return -ENODEV;
        }
        hw->bitbang.master->dev.of_node = pdev->dev.of_node;
-       val = of_get_property(pdev->dev.of_node,
-                             "clock-frequency", &len);
-       if (val && len >= sizeof(__be32))
-               hw->freq = be32_to_cpup(val);
-       val = of_get_property(pdev->dev.of_node, "baud-width", &len);
-       if (val && len >= sizeof(__be32))
-               hw->baudwidth = be32_to_cpup(val);
+       if (!of_property_read_u32(np, "clock-frequency", &val))
+               hw->freq = val;
+       if (!of_property_read_u32(np, "baud-width", &val))
+               hw->baudwidth = val;
        return 0;
 }
 #else /* !CONFIG_OF */
index e99d6a93d3943c8b578fbd4a00ecba152d0881c5..07e4ce8273df56533aee2e8adf563c6026a956c0 100644 (file)
@@ -65,7 +65,7 @@ static int octeon_spi_do_transfer(struct octeon_spi *p,
        cpha = mode & SPI_CPHA;
        cpol = mode & SPI_CPOL;
 
-       speed_hz = xfer->speed_hz ? : spi->max_speed_hz;
+       speed_hz = xfer->speed_hz;
 
        clkdiv = octeon_get_io_clock_rate() / (2 * speed_hz);
 
index 3d09e0b69b73241c58d50e788dbdaf5cd16bf7ea..1f8903d356e5581f48d6935177906bba6bc7e302 100644 (file)
@@ -1217,6 +1217,33 @@ out:
        return status;
 }
 
+static int omap2_mcspi_prepare_message(struct spi_master *master,
+                                      struct spi_message *msg)
+{
+       struct omap2_mcspi      *mcspi = spi_master_get_devdata(master);
+       struct omap2_mcspi_regs *ctx = &mcspi->ctx;
+       struct omap2_mcspi_cs   *cs;
+
+       /* Only a single channel can have the FORCE bit enabled
+        * in its chconf0 register.
+        * Scan all channels and disable them except the current one.
+        * A FORCE can remain from a last transfer having cs_change enabled
+        */
+       list_for_each_entry(cs, &ctx->cs, node) {
+               if (msg->spi->controller_state == cs)
+                       continue;
+
+               if ((cs->chconf0 & OMAP2_MCSPI_CHCONF_FORCE)) {
+                       cs->chconf0 &= ~OMAP2_MCSPI_CHCONF_FORCE;
+                       writel_relaxed(cs->chconf0,
+                                       cs->base + OMAP2_MCSPI_CHCONF0);
+                       readl_relaxed(cs->base + OMAP2_MCSPI_CHCONF0);
+               }
+       }
+
+       return 0;
+}
+
 static int omap2_mcspi_transfer_one(struct spi_master *master,
                struct spi_device *spi, struct spi_transfer *t)
 {
@@ -1344,6 +1371,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
        master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
        master->setup = omap2_mcspi_setup;
        master->auto_runtime_pm = true;
+       master->prepare_message = omap2_mcspi_prepare_message;
        master->transfer_one = omap2_mcspi_transfer_one;
        master->set_cs = omap2_mcspi_set_cs;
        master->cleanup = omap2_mcspi_cleanup;
index 54fb984a3e1748157af2ecd230d605f60aee0bc4..dd3d0a218d8b1ffc2299595fc55adadaaa3bdeeb 100644 (file)
@@ -210,12 +210,12 @@ static int spi_ppc4xx_setupxfer(struct spi_device *spi, struct spi_transfer *t)
        if (in_8(&hw->regs->cdm) != cdm)
                out_8(&hw->regs->cdm, cdm);
 
-       spin_lock(&hw->bitbang.lock);
+       mutex_lock(&hw->bitbang.lock);
        if (!hw->bitbang.busy) {
                hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE);
                /* Need to ndelay here? */
        }
-       spin_unlock(&hw->bitbang.lock);
+       mutex_unlock(&hw->bitbang.lock);
 
        return 0;
 }
index fdd7919770419bcbf63afaf326e719e43ae6513b..a8ef38ebb9c9db551191b2e80be567990a20817b 100644 (file)
@@ -654,6 +654,10 @@ static irqreturn_t ssp_int(int irq, void *dev_id)
        if (!(sccr1_reg & SSCR1_TIE))
                mask &= ~SSSR_TFS;
 
+       /* Ignore RX timeout interrupt if it is disabled */
+       if (!(sccr1_reg & SSCR1_TINTE))
+               mask &= ~SSSR_TINT;
+
        if (!(status & mask))
                return IRQ_NONE;
 
index f36bc320a80799067e6402feeb2ebb64c4f58169..4e7d1bfed7e6b6eaa1cfbf5409232c63c4bdceac 100644 (file)
@@ -198,12 +198,12 @@ static int s3c24xx_spi_setup(struct spi_device *spi)
        if (ret)
                return ret;
 
-       spin_lock(&hw->bitbang.lock);
+       mutex_lock(&hw->bitbang.lock);
        if (!hw->bitbang.busy) {
                hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE);
                /* need to ndelay for 0.5 clocktick ? */
        }
-       spin_unlock(&hw->bitbang.lock);
+       mutex_unlock(&hw->bitbang.lock);
 
        return 0;
 }
index aa6d284131e0fd99fd19ef92dc0adff73ee18a02..81b84858cfeed2d8baebd959af2fbcfc51fc8108 100644 (file)
@@ -410,11 +410,10 @@ static int ti_qspi_start_transfer_one(struct spi_master *master,
 
        mutex_unlock(&qspi->list_lock);
 
+       ti_qspi_write(qspi, qspi->cmd | QSPI_INVAL, QSPI_SPI_CMD_REG);
        m->status = status;
        spi_finalize_current_message(master);
 
-       ti_qspi_write(qspi, qspi->cmd | QSPI_INVAL, QSPI_SPI_CMD_REG);
-
        return status;
 }
 
index a339c1e9997a93a431cf5ce9be5947b6333ac3e9..3009121173cdbc9ad1a0537a4cf19a029ceb86b8 100644 (file)
@@ -270,6 +270,7 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
 
        while (remaining_words) {
                int n_words, tx_words, rx_words;
+               u32 sr;
 
                n_words = min(remaining_words, xspi->buffer_size);
 
@@ -284,24 +285,33 @@ static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
                if (use_irq) {
                        xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET);
                        wait_for_completion(&xspi->done);
-               } else
-                       while (!(xspi->read_fn(xspi->regs + XSPI_SR_OFFSET) &
-                                               XSPI_SR_TX_EMPTY_MASK))
-                               ;
-
-               /* A transmit has just completed. Process received data and
-                * check for more data to transmit. Always inhibit the
-                * transmitter while the Isr refills the transmit register/FIFO,
-                * or make sure it is stopped if we're done.
-                */
-               if (use_irq)
+                       /* A transmit has just completed. Process received data
+                        * and check for more data to transmit. Always inhibit
+                        * the transmitter while the Isr refills the transmit
+                        * register/FIFO, or make sure it is stopped if we're
+                        * done.
+                        */
                        xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT,
-                              xspi->regs + XSPI_CR_OFFSET);
+                                      xspi->regs + XSPI_CR_OFFSET);
+                       sr = XSPI_SR_TX_EMPTY_MASK;
+               } else
+                       sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
 
                /* Read out all the data from the Rx FIFO */
                rx_words = n_words;
-               while (rx_words--)
-                       xilinx_spi_rx(xspi);
+               while (rx_words) {
+                       if ((sr & XSPI_SR_TX_EMPTY_MASK) && (rx_words > 1)) {
+                               xilinx_spi_rx(xspi);
+                               rx_words--;
+                               continue;
+                       }
+
+                       sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET);
+                       if (!(sr & XSPI_SR_RX_EMPTY_MASK)) {
+                               xilinx_spi_rx(xspi);
+                               rx_words--;
+                       }
+               }
 
                remaining_words -= n_words;
        }
index 2e32ea2f194f3f0d92c4410be212d65b4be75b0d..be6155cba9de721b4a4ff6983bc6d8bc1e37ed3f 100644 (file)
@@ -34,13 +34,13 @@ struct xtfpga_spi {
 static inline void xtfpga_spi_write32(const struct xtfpga_spi *spi,
                                      unsigned addr, u32 val)
 {
-       iowrite32(val, spi->regs + addr);
+       __raw_writel(val, spi->regs + addr);
 }
 
 static inline unsigned int xtfpga_spi_read32(const struct xtfpga_spi *spi,
                                             unsigned addr)
 {
-       return ioread32(spi->regs + addr);
+       return __raw_readl(spi->regs + addr);
 }
 
 static inline void xtfpga_spi_wait_busy(struct xtfpga_spi *xspi)
index 3abb3903f2ad454ef964299204bd3c2454890062..f9e92f535cbb1ba427a77ab40b0266d453a75d3b 100644 (file)
@@ -123,6 +123,28 @@ SPI_STATISTICS_SHOW(bytes, "%llu");
 SPI_STATISTICS_SHOW(bytes_rx, "%llu");
 SPI_STATISTICS_SHOW(bytes_tx, "%llu");
 
+#define SPI_STATISTICS_TRANSFER_BYTES_HISTO(index, number)             \
+       SPI_STATISTICS_SHOW_NAME(transfer_bytes_histo##index,           \
+                                "transfer_bytes_histo_" number,        \
+                                transfer_bytes_histo[index],  "%lu")
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(0,  "0-1");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(1,  "2-3");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(2,  "4-7");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(3,  "8-15");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(4,  "16-31");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(5,  "32-63");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(6,  "64-127");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(7,  "128-255");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(8,  "256-511");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(9,  "512-1023");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(10, "1024-2047");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(11, "2048-4095");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(12, "4096-8191");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(13, "8192-16383");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(14, "16384-32767");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(15, "32768-65535");
+SPI_STATISTICS_TRANSFER_BYTES_HISTO(16, "65536+");
+
 static struct attribute *spi_dev_attrs[] = {
        &dev_attr_modalias.attr,
        NULL,
@@ -143,6 +165,23 @@ static struct attribute *spi_device_statistics_attrs[] = {
        &dev_attr_spi_device_bytes.attr,
        &dev_attr_spi_device_bytes_rx.attr,
        &dev_attr_spi_device_bytes_tx.attr,
+       &dev_attr_spi_device_transfer_bytes_histo0.attr,
+       &dev_attr_spi_device_transfer_bytes_histo1.attr,
+       &dev_attr_spi_device_transfer_bytes_histo2.attr,
+       &dev_attr_spi_device_transfer_bytes_histo3.attr,
+       &dev_attr_spi_device_transfer_bytes_histo4.attr,
+       &dev_attr_spi_device_transfer_bytes_histo5.attr,
+       &dev_attr_spi_device_transfer_bytes_histo6.attr,
+       &dev_attr_spi_device_transfer_bytes_histo7.attr,
+       &dev_attr_spi_device_transfer_bytes_histo8.attr,
+       &dev_attr_spi_device_transfer_bytes_histo9.attr,
+       &dev_attr_spi_device_transfer_bytes_histo10.attr,
+       &dev_attr_spi_device_transfer_bytes_histo11.attr,
+       &dev_attr_spi_device_transfer_bytes_histo12.attr,
+       &dev_attr_spi_device_transfer_bytes_histo13.attr,
+       &dev_attr_spi_device_transfer_bytes_histo14.attr,
+       &dev_attr_spi_device_transfer_bytes_histo15.attr,
+       &dev_attr_spi_device_transfer_bytes_histo16.attr,
        NULL,
 };
 
@@ -168,6 +207,23 @@ static struct attribute *spi_master_statistics_attrs[] = {
        &dev_attr_spi_master_bytes.attr,
        &dev_attr_spi_master_bytes_rx.attr,
        &dev_attr_spi_master_bytes_tx.attr,
+       &dev_attr_spi_master_transfer_bytes_histo0.attr,
+       &dev_attr_spi_master_transfer_bytes_histo1.attr,
+       &dev_attr_spi_master_transfer_bytes_histo2.attr,
+       &dev_attr_spi_master_transfer_bytes_histo3.attr,
+       &dev_attr_spi_master_transfer_bytes_histo4.attr,
+       &dev_attr_spi_master_transfer_bytes_histo5.attr,
+       &dev_attr_spi_master_transfer_bytes_histo6.attr,
+       &dev_attr_spi_master_transfer_bytes_histo7.attr,
+       &dev_attr_spi_master_transfer_bytes_histo8.attr,
+       &dev_attr_spi_master_transfer_bytes_histo9.attr,
+       &dev_attr_spi_master_transfer_bytes_histo10.attr,
+       &dev_attr_spi_master_transfer_bytes_histo11.attr,
+       &dev_attr_spi_master_transfer_bytes_histo12.attr,
+       &dev_attr_spi_master_transfer_bytes_histo13.attr,
+       &dev_attr_spi_master_transfer_bytes_histo14.attr,
+       &dev_attr_spi_master_transfer_bytes_histo15.attr,
+       &dev_attr_spi_master_transfer_bytes_histo16.attr,
        NULL,
 };
 
@@ -186,10 +242,15 @@ void spi_statistics_add_transfer_stats(struct spi_statistics *stats,
                                       struct spi_master *master)
 {
        unsigned long flags;
+       int l2len = min(fls(xfer->len), SPI_STATISTICS_HISTO_SIZE) - 1;
+
+       if (l2len < 0)
+               l2len = 0;
 
        spin_lock_irqsave(&stats->lock, flags);
 
        stats->transfers++;
+       stats->transfer_bytes_histo[l2len]++;
 
        stats->bytes += xfer->len;
        if ((xfer->tx_buf) &&
@@ -270,15 +331,24 @@ EXPORT_SYMBOL_GPL(spi_bus_type);
 static int spi_drv_probe(struct device *dev)
 {
        const struct spi_driver         *sdrv = to_spi_driver(dev->driver);
+       struct spi_device               *spi = to_spi_device(dev);
        int ret;
 
        ret = of_clk_set_defaults(dev->of_node, false);
        if (ret)
                return ret;
 
+       if (dev->of_node) {
+               spi->irq = of_irq_get(dev->of_node, 0);
+               if (spi->irq == -EPROBE_DEFER)
+                       return -EPROBE_DEFER;
+               if (spi->irq < 0)
+                       spi->irq = 0;
+       }
+
        ret = dev_pm_domain_attach(dev, true);
        if (ret != -EPROBE_DEFER) {
-               ret = sdrv->probe(to_spi_device(dev));
+               ret = sdrv->probe(spi);
                if (ret)
                        dev_pm_domain_detach(dev, true);
        }
@@ -308,6 +378,8 @@ static void spi_drv_shutdown(struct device *dev)
  * spi_register_driver - register a SPI driver
  * @sdrv: the driver to register
  * Context: can sleep
+ *
+ * Return: zero on success, else a negative error code.
  */
 int spi_register_driver(struct spi_driver *sdrv)
 {
@@ -359,7 +431,7 @@ static DEFINE_MUTEX(board_lock);
  * needs to discard the spi_device without adding it, then it should
  * call spi_dev_put() on it.
  *
- * Returns a pointer to the new device, or NULL.
+ * Return: a pointer to the new device, or NULL.
  */
 struct spi_device *spi_alloc_device(struct spi_master *master)
 {
@@ -418,7 +490,7 @@ static int spi_dev_check(struct device *dev, void *data)
  * Companion function to spi_alloc_device.  Devices allocated with
  * spi_alloc_device can be added onto the spi bus with this function.
  *
- * Returns 0 on success; negative errno on failure
+ * Return: 0 on success; negative errno on failure
  */
 int spi_add_device(struct spi_device *spi)
 {
@@ -491,7 +563,7 @@ EXPORT_SYMBOL_GPL(spi_add_device);
  * this is exported so that for example a USB or parport based adapter
  * driver could add devices (which it would learn about out-of-band).
  *
- * Returns the new device, or NULL.
+ * Return: the new device, or NULL.
  */
 struct spi_device *spi_new_device(struct spi_master *master,
                                  struct spi_board_info *chip)
@@ -563,6 +635,8 @@ static void spi_match_master_to_boardinfo(struct spi_master *master,
  *
  * The board info passed can safely be __initdata ... but be careful of
  * any embedded pointers (platform_data, etc), they're copied as-is.
+ *
+ * Return: zero on success, else a negative error code.
  */
 int spi_register_board_info(struct spi_board_info const *info, unsigned n)
 {
@@ -597,7 +671,7 @@ static void spi_set_cs(struct spi_device *spi, bool enable)
        if (spi->mode & SPI_CS_HIGH)
                enable = !enable;
 
-       if (spi->cs_gpio >= 0)
+       if (gpio_is_valid(spi->cs_gpio))
                gpio_set_value(spi->cs_gpio, !enable);
        else if (spi->master->set_cs)
                spi->master->set_cs(spi, !enable);
@@ -1140,6 +1214,8 @@ static int spi_init_queue(struct spi_master *master)
  *
  * If there are more messages in the queue, the next message is returned from
  * this call.
+ *
+ * Return: the next message in the queue, else NULL if the queue is empty.
  */
 struct spi_message *spi_get_next_queued_message(struct spi_master *master)
 {
@@ -1303,6 +1379,8 @@ static int __spi_queued_transfer(struct spi_device *spi,
  * spi_queued_transfer - transfer function for queued transfers
  * @spi: spi device which is requesting transfer
  * @msg: spi message which is to handled is queued to driver queue
+ *
+ * Return: zero on success, else a negative error code.
  */
 static int spi_queued_transfer(struct spi_device *spi, struct spi_message *msg)
 {
@@ -1433,9 +1511,6 @@ of_register_spi_device(struct spi_master *master, struct device_node *nc)
        }
        spi->max_speed_hz = value;
 
-       /* IRQ */
-       spi->irq = irq_of_parse_and_map(nc, 0);
-
        /* Store a pointer to the node in the device structure */
        of_node_get(nc);
        spi->dev.of_node = nc;
@@ -1605,13 +1680,13 @@ static struct class spi_master_class = {
  * only ones directly touching chip registers.  It's how they allocate
  * an spi_master structure, prior to calling spi_register_master().
  *
- * This must be called from context that can sleep.  It returns the SPI
- * master structure on success, else NULL.
+ * This must be called from context that can sleep.
  *
  * The caller is responsible for assigning the bus number and initializing
  * the master's methods before calling spi_register_master(); and (after errors
- * adding the device) calling spi_master_put() and kfree() to prevent a memory
- * leak.
+ * adding the device) calling spi_master_put() to prevent a memory leak.
+ *
+ * Return: the SPI master structure on success, else NULL.
  */
 struct spi_master *spi_alloc_master(struct device *dev, unsigned size)
 {
@@ -1695,6 +1770,8 @@ static int of_spi_register_master(struct spi_master *master)
  * success, else a negative error code (dropping the master's refcount).
  * After a successful return, the caller is responsible for calling
  * spi_unregister_master().
+ *
+ * Return: zero on success, else a negative error code.
  */
 int spi_register_master(struct spi_master *master)
 {
@@ -1788,6 +1865,8 @@ static void devm_spi_unregister(struct device *dev, void *res)
  *
  * Register a SPI device as with spi_register_master() which will
  * automatically be unregister
+ *
+ * Return: zero on success, else a negative error code.
  */
 int devm_spi_register_master(struct device *dev, struct spi_master *master)
 {
@@ -1893,6 +1972,8 @@ static int __spi_master_match(struct device *dev, const void *data)
  * arch init time.  It returns a refcounted pointer to the relevant
  * spi_master (which the caller must release), or NULL if there is
  * no such master registered.
+ *
+ * Return: the SPI master structure on success, else NULL.
  */
 struct spi_master *spi_busnum_to_master(u16 bus_num)
 {
@@ -1946,11 +2027,13 @@ static int __spi_validate_bits_per_word(struct spi_master *master, u8 bits_per_w
  * that the underlying controller or its driver does not support.  For
  * example, not all hardware supports wire transfers using nine bit words,
  * LSB-first wire encoding, or active-high chipselects.
+ *
+ * Return: zero on success, else a negative error code.
  */
 int spi_setup(struct spi_device *spi)
 {
        unsigned        bad_bits, ugly_bits;
-       int             status = 0;
+       int             status;
 
        /* check mode to prevent that DUAL and QUAD set at the same time
         */
@@ -1987,17 +2070,18 @@ int spi_setup(struct spi_device *spi)
        if (!spi->bits_per_word)
                spi->bits_per_word = 8;
 
-       if (__spi_validate_bits_per_word(spi->master, spi->bits_per_word))
-               return -EINVAL;
+       status = __spi_validate_bits_per_word(spi->master, spi->bits_per_word);
+       if (status)
+               return status;
 
        if (!spi->max_speed_hz)
                spi->max_speed_hz = spi->master->max_speed_hz;
 
-       spi_set_cs(spi, false);
-
        if (spi->master->setup)
                status = spi->master->setup(spi);
 
+       spi_set_cs(spi, false);
+
        dev_dbg(&spi->dev, "setup mode %d, %s%s%s%s%u bits/w, %u Hz max --> %d\n",
                        (int) (spi->mode & (SPI_CPOL | SPI_CPHA)),
                        (spi->mode & SPI_CS_HIGH) ? "cs_high, " : "",
@@ -2163,6 +2247,8 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
  * no other spi_message queued to that device will be processed.
  * (This rule applies equally to all the synchronous transfer calls,
  * which are wrappers around this core asynchronous primitive.)
+ *
+ * Return: zero on success, else a negative error code.
  */
 int spi_async(struct spi_device *spi, struct spi_message *message)
 {
@@ -2215,6 +2301,8 @@ EXPORT_SYMBOL_GPL(spi_async);
  * no other spi_message queued to that device will be processed.
  * (This rule applies equally to all the synchronous transfer calls,
  * which are wrappers around this core asynchronous primitive.)
+ *
+ * Return: zero on success, else a negative error code.
  */
 int spi_async_locked(struct spi_device *spi, struct spi_message *message)
 {
@@ -2330,7 +2418,7 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message,
  * Also, the caller is guaranteeing that the memory associated with the
  * message will not be freed before this call returns.
  *
- * It returns zero on success, else a negative error code.
+ * Return: zero on success, else a negative error code.
  */
 int spi_sync(struct spi_device *spi, struct spi_message *message)
 {
@@ -2352,7 +2440,7 @@ EXPORT_SYMBOL_GPL(spi_sync);
  * SPI bus. It has to be preceded by a spi_bus_lock call. The SPI bus must
  * be released by a spi_bus_unlock call when the exclusive access is over.
  *
- * It returns zero on success, else a negative error code.
+ * Return: zero on success, else a negative error code.
  */
 int spi_sync_locked(struct spi_device *spi, struct spi_message *message)
 {
@@ -2373,7 +2461,7 @@ EXPORT_SYMBOL_GPL(spi_sync_locked);
  * exclusive access is over. Data transfer must be done by spi_sync_locked
  * and spi_async_locked calls when the SPI bus lock is held.
  *
- * It returns zero on success, else a negative error code.
+ * Return: always zero.
  */
 int spi_bus_lock(struct spi_master *master)
 {
@@ -2402,7 +2490,7 @@ EXPORT_SYMBOL_GPL(spi_bus_lock);
  * This call releases an SPI bus lock previously obtained by an spi_bus_lock
  * call.
  *
- * It returns zero on success, else a negative error code.
+ * Return: always zero.
  */
 int spi_bus_unlock(struct spi_master *master)
 {
@@ -2437,6 +2525,8 @@ static u8 *buf;
  * portable code should never use this for more than 32 bytes.
  * Performance-sensitive or bulk transfer code should instead use
  * spi_{async,sync}() calls with dma-safe buffers.
+ *
+ * Return: zero on success, else a negative error code.
  */
 int spi_write_then_read(struct spi_device *spi,
                const void *txbuf, unsigned n_tx,
index fba92a5265310c78acd9fb7e9c621f6d88942d24..ef008e52f9537e788389b641f1707c72e0212ec9 100644 (file)
@@ -651,7 +651,8 @@ static int spidev_release(struct inode *inode, struct file *filp)
                kfree(spidev->rx_buffer);
                spidev->rx_buffer = NULL;
 
-               spidev->speed_hz = spidev->spi->max_speed_hz;
+               if (spidev->spi)
+                       spidev->speed_hz = spidev->spi->max_speed_hz;
 
                /* ... after we unbound from the underlying device? */
                spin_lock_irq(&spidev->spi_lock);
index bdfb3c84c3cb43a652dcb36fb449758807f58fa4..4a3cf9ba152f6b8060e3c7709550dfdc7ec9fe17 100644 (file)
@@ -451,7 +451,7 @@ static void periph_interrupt(struct spmi_pmic_arb_dev *pa, u8 apid)
        }
 }
 
-static void pmic_arb_chained_irq(unsigned int irq, struct irq_desc *desc)
+static void pmic_arb_chained_irq(struct irq_desc *desc)
 {
        struct spmi_pmic_arb_dev *pa = irq_desc_get_handler_data(desc);
        struct irq_chip *chip = irq_desc_get_chip(desc);
index 20288fc53946ce9648b36d8af821f74e1c833abd..8f3ac37bfe12e71cb9b0f2e936664ffe7ba20737 100644 (file)
@@ -5,5 +5,25 @@ TODO:
        - add proper arch dependencies as needed
        - audit userspace interfaces to make sure they are sane
 
+
+ion/
+ - Remove ION_IOC_SYNC: Flushing for devices should be purely a kernel internal
+   interface on top of dma-buf. flush_for_device needs to be added to dma-buf
+   first.
+ - Remove ION_IOC_CUSTOM: Atm used for cache flushing for cpu access in some
+   vendor trees. Should be replaced with an ioctl on the dma-buf to expose the
+   begin/end_cpu_access hooks to userspace.
+ - Clarify the tricks ion plays with explicitly managing coherency behind the
+   dma api's back (this is absolutely needed for high-perf gpu drivers): Add an
+   explicit coherency management mode to flush_for_device to be used by drivers
+   which want to manage caches themselves and which indicates whether cpu caches
+   need flushing.
+ - With those removed there's probably no use for ION_IOC_IMPORT anymore either
+   since ion would just be the central allocator for shared buffers.
+ - Add dt-binding to expose cma regions as ion heaps, with the rule that any
+   such cma regions must already be used by some device for dma. I.e. ion only
+   exposes existing cma regions and doesn't reserve unecessarily memory when
+   booting a system which doesn't use ion.
+
 Please send patches to Greg Kroah-Hartman <greg@kroah.com> and Cc:
 Arve HjønnevÃ¥g <arve@android.com> and Riley Andrews <riandrews@android.com>
index 217aa537c4eb9770a0ca0abf34626a8146f5049b..6e8d8392ca386e8ddd76e705ac8364a2555c178f 100644 (file)
@@ -1179,13 +1179,13 @@ struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd)
                mutex_unlock(&client->lock);
                goto end;
        }
-       mutex_unlock(&client->lock);
 
        handle = ion_handle_create(client, buffer);
-       if (IS_ERR(handle))
+       if (IS_ERR(handle)) {
+               mutex_unlock(&client->lock);
                goto end;
+       }
 
-       mutex_lock(&client->lock);
        ret = ion_handle_add(client, handle);
        mutex_unlock(&client->lock);
        if (ret) {
index 32f3a9d921d6adf8c86e5df8632e9c9d6b4a2e4e..5cafa50d1facee4292916852274f3bfa8aff8281 100644 (file)
@@ -76,7 +76,7 @@ static int init_display(struct fbtft_par *par)
 
        /* Set CS active high */
        par->spi->mode |= SPI_CS_HIGH;
-       ret = par->spi->master->setup(par->spi);
+       ret = spi_setup(par->spi);
        if (ret) {
                dev_err(par->info->device, "Could not set SPI_CS_HIGH\n");
                return ret;
index 88fb2c0132d5257542c9e75964c47f164c5e36f5..8eae6ef25846bfb1c6fe17365af757286e85faf3 100644 (file)
@@ -169,7 +169,7 @@ static int init_display(struct fbtft_par *par)
        /* enable SPI interface by having CS and MOSI low during reset */
        save_mode = par->spi->mode;
        par->spi->mode |= SPI_CS_HIGH;
-       ret = par->spi->master->setup(par->spi); /* set CS inactive low */
+       ret = spi_setup(par->spi); /* set CS inactive low */
        if (ret) {
                dev_err(par->info->device, "Could not set SPI_CS_HIGH\n");
                return ret;
@@ -180,7 +180,7 @@ static int init_display(struct fbtft_par *par)
        par->fbtftops.reset(par);
        mdelay(1000);
        par->spi->mode = save_mode;
-       ret = par->spi->master->setup(par->spi);
+       ret = spi_setup(par->spi);
        if (ret) {
                dev_err(par->info->device, "Could not restore SPI mode\n");
                return ret;
index 23392eb6799ec0e946f238b42b9d02c0673e92d8..7f5fa3d1cab049fecfeca3bc221536a6c218524b 100644 (file)
@@ -1436,15 +1436,11 @@ int fbtft_probe_common(struct fbtft_display *display,
 
        /* 9-bit SPI setup */
        if (par->spi && display->buswidth == 9) {
-               par->spi->bits_per_word = 9;
-               ret = par->spi->master->setup(par->spi);
-               if (ret) {
+               if (par->spi->master->bits_per_word_mask & SPI_BPW_MASK(9)) {
+                       par->spi->bits_per_word = 9;
+               } else {
                        dev_warn(&par->spi->dev,
                                "9-bit SPI not available, emulating using 8-bit.\n");
-                       par->spi->bits_per_word = 8;
-                       ret = par->spi->master->setup(par->spi);
-                       if (ret)
-                               goto out_release;
                        /* allocate buffer with room for dc bits */
                        par->extra = devm_kzalloc(par->info->device,
                                par->txbuf.len + (par->txbuf.len / 8) + 8,
index c763efc5de7dc468708945845b22154860b00869..3f380a0086c3d191b21e5f6889232bf23f190413 100644 (file)
@@ -463,15 +463,12 @@ static int flexfb_probe_common(struct spi_device *sdev,
                        }
                        par->fbtftops.write_register = fbtft_write_reg8_bus9;
                        par->fbtftops.write_vmem = fbtft_write_vmem16_bus9;
-                       sdev->bits_per_word = 9;
-                       ret = sdev->master->setup(sdev);
-                       if (ret) {
+                       if (par->spi->master->bits_per_word_mask
+                           & SPI_BPW_MASK(9)) {
+                               par->spi->bits_per_word = 9;
+                       } else {
                                dev_warn(dev,
                                        "9-bit SPI not available, emulating using 8-bit.\n");
-                               sdev->bits_per_word = 8;
-                               ret = sdev->master->setup(sdev);
-                               if (ret)
-                                       goto out_release;
                                /* allocate buffer with room for dc bits */
                                par->extra = devm_kzalloc(par->info->device,
                                                par->txbuf.len + (par->txbuf.len / 8) + 8,
index 23685e74917e2a5c3f3ab6dc6542f48d5ecbb2a9..bd2c69f85949ba6ce40b80c588a2e6a4036964a2 100644 (file)
@@ -116,7 +116,7 @@ static int sca3000_read_first_n_hw_rb(struct iio_buffer *r,
        if (ret)
                goto error_ret;
 
-       for (i = 0; i < num_read; i++)
+       for (i = 0; i < num_read / sizeof(u16); i++)
                *(((u16 *)rx) + i) = be16_to_cpup((__be16 *)rx + i);
 
        if (copy_to_user(buf, rx, num_read))
index 3f7715c9968b83b25d6d1a4f6099c29b051db5fd..47fc00a3f63bc9e5106f0c77354c7cf8e309f36e 100644 (file)
@@ -915,11 +915,12 @@ static int mxs_lradc_read_raw(struct iio_dev *iio_dev,
        case IIO_CHAN_INFO_OFFSET:
                if (chan->type == IIO_TEMP) {
                        /* The calculated value from the ADC is in Kelvin, we
-                        * want Celsius for hwmon so the offset is
-                        * -272.15 * scale
+                        * want Celsius for hwmon so the offset is -273.15
+                        * The offset is applied before scaling so it is
+                        * actually -213.15 * 4 / 1.012 = -1079.644268
                         */
-                       *val = -1075;
-                       *val2 = 691699;
+                       *val = -1079;
+                       *val2 = 644268;
 
                        return IIO_VAL_INT_PLUS_MICRO;
                }
index cf0ca50ff83b2acc3159808731a54c00643bd3e1..0676243eea9e4063fa37ff962fa1ac0e5c308bab 100644 (file)
@@ -14,10 +14,8 @@ Unlike shared disk storage cluster filesystems (e.g. OCFS2, GFS, GPFS),
 Lustre has independent Metadata and Data servers that clients can access
 in parallel to maximize performance.
 
-In order to use Lustre client you will need to download lustre client
-tools from
-https://downloads.hpdd.intel.com/public/lustre/latest-feature-release/
-the package name is lustre-client.
+In order to use Lustre client you will need to download the "lustre-client"
+package that contains the userspace tools from http://lustre.org/download/
 
 You will need to install and configure your Lustre servers separately.
 
@@ -76,12 +74,10 @@ Mount Options
 
 More Information
 ================
-You can get more information at
-OpenSFS website: http://lustre.opensfs.org/about/
-Intel HPDD wiki: https://wiki.hpdd.intel.com
+You can get more information at the Lustre website: http://wiki.lustre.org/
 
-Out of tree Lustre client and server code is available at:
-http://git.whamcloud.com/fs/lustre-release.git
+Source for the userspace tools and out-of-tree client and server code
+is available at: http://git.hpdd.intel.com/fs/lustre-release.git
 
 Latest binary packages:
-http://lustre.opensfs.org/download-lustre/
+http://lustre.org/download/
index 769b61193d87ef29c7868465c50e9b8ab87ee045..a9bc6e23fc2582f39c5a753638979fba15451e61 100644 (file)
@@ -224,7 +224,7 @@ static int ll_dir_filler(void *_hash, struct page *page0)
 
                prefetchw(&page->flags);
                ret = add_to_page_cache_lru(page, inode->i_mapping, offset,
-                                           GFP_KERNEL);
+                                           GFP_NOFS);
                if (ret == 0) {
                        unlock_page(page);
                } else {
index d50de03de7b9897252007d7f35b2e1769bbb2a45..0b9b9b539f70562d2a908e6741df729d0ea2d9fc 100644 (file)
@@ -1,5 +1,6 @@
 menuconfig MOST
         tristate "MOST driver"
+       depends on HAS_DMA
         select MOSTCORE
         default n
         ---help---
index 1d4ad1d67758c3f5abbf842b7678f32bb0ab90b0..fc548769479b7a0c583a5028a38909a51f537caa 100644 (file)
@@ -5,6 +5,7 @@
 config HDM_DIM2
        tristate "DIM2 HDM"
        depends on AIM_NETWORK
+       depends on HAS_IOMEM
 
        ---help---
          Say Y here if you want to connect via MediaLB to network transceiver.
index a482c3fdf34b9d82648efdb8bc029c42196c7e49..ec1546312ee67034d3cee21457937bea25324a3a 100644 (file)
@@ -4,7 +4,7 @@
 
 config HDM_USB
        tristate "USB HDM"
-       depends on USB
+       depends on USB && NET
        select AIM_NETWORK
        ---help---
          Say Y here if you want to connect via USB to network tranceiver.
index 38abf1b21b6623c7973c4a41821be2a97938b7fb..47172546d7280ee6d10f9bb35d5339b3a58d8c6a 100644 (file)
@@ -4,6 +4,7 @@
 
 config MOSTCORE
        tristate "MOST Core"
+       depends on HAS_DMA
 
        ---help---
          Say Y here if you want to enable MOST support.
index cf5fe9bb87a16c8a339ae2a25955352d18c71221..d7f62359d7430fd0933ca84481db701073aee5b1 100644 (file)
@@ -24,6 +24,8 @@ if STAGING_RDMA
 
 source "drivers/staging/rdma/amso1100/Kconfig"
 
+source "drivers/staging/rdma/ehca/Kconfig"
+
 source "drivers/staging/rdma/hfi1/Kconfig"
 
 source "drivers/staging/rdma/ipath/Kconfig"
index cbd915ac7f20a85b8ab9a09d882ba7dffb60e54c..139d78ef2c24388b93ed6a008090190cff6de663 100644 (file)
@@ -1,4 +1,5 @@
 # Entries for RDMA_STAGING tree
 obj-$(CONFIG_INFINIBAND_AMSO1100)      += amso1100/
+obj-$(CONFIG_INFINIBAND_EHCA)  += ehca/
 obj-$(CONFIG_INFINIBAND_HFI1)  += hfi1/
 obj-$(CONFIG_INFINIBAND_IPATH) += ipath/
diff --git a/drivers/staging/rdma/ehca/Kconfig b/drivers/staging/rdma/ehca/Kconfig
new file mode 100644 (file)
index 0000000..3fadd2a
--- /dev/null
@@ -0,0 +1,10 @@
+config INFINIBAND_EHCA
+       tristate "eHCA support"
+       depends on IBMEBUS
+       ---help---
+       This driver supports the deprecated IBM pSeries eHCA InfiniBand
+       adapter.
+
+       To compile the driver as a module, choose M here. The module
+       will be called ib_ehca.
+
diff --git a/drivers/staging/rdma/ehca/Makefile b/drivers/staging/rdma/ehca/Makefile
new file mode 100644 (file)
index 0000000..74d284e
--- /dev/null
@@ -0,0 +1,16 @@
+#  Authors: Heiko J Schick <schickhj@de.ibm.com>
+#           Christoph Raisch <raisch@de.ibm.com>
+#           Joachim Fenkes <fenkes@de.ibm.com>
+#
+#  Copyright (c) 2005 IBM Corporation
+#
+#  All rights reserved.
+#
+#  This source code is distributed under a dual license of GPL v2.0 and OpenIB BSD.
+
+obj-$(CONFIG_INFINIBAND_EHCA) += ib_ehca.o
+
+ib_ehca-objs  = ehca_main.o ehca_hca.o ehca_mcast.o ehca_pd.o ehca_av.o ehca_eq.o \
+               ehca_cq.o ehca_qp.o ehca_sqp.o ehca_mrmw.o ehca_reqs.o ehca_irq.o \
+               ehca_uverbs.o ipz_pt_fn.o hcp_if.o hcp_phyp.o
+
diff --git a/drivers/staging/rdma/ehca/TODO b/drivers/staging/rdma/ehca/TODO
new file mode 100644 (file)
index 0000000..199a4a6
--- /dev/null
@@ -0,0 +1,4 @@
+9/2015
+
+The ehca driver has been deprecated and moved to drivers/staging/rdma.
+It will be removed in the 4.6 merge window.
diff --git a/drivers/staging/rdma/ehca/ehca_av.c b/drivers/staging/rdma/ehca/ehca_av.c
new file mode 100644 (file)
index 0000000..4659263
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+ *  IBM eServer eHCA Infiniband device driver for Linux on POWER
+ *
+ *  address vector functions
+ *
+ *  Authors: Hoang-Nam Nguyen <hnguyen@de.ibm.com>
+ *           Khadija Souissi <souissik@de.ibm.com>
+ *           Reinhard Ernst <rernst@de.ibm.com>
+ *           Christoph Raisch <raisch@de.ibm.com>
+ *
+ *  Copyright (c) 2005 IBM Corporation
+ *
+ *  All rights reserved.
+ *
+ *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
+ *  BSD.
+ *
+ * OpenIB BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/slab.h>
+
+#include "ehca_tools.h"
+#include "ehca_iverbs.h"
+#include "hcp_if.h"
+
+static struct kmem_cache *av_cache;
+
+int ehca_calc_ipd(struct ehca_shca *shca, int port,
+                 enum ib_rate path_rate, u32 *ipd)
+{
+       int path = ib_rate_to_mult(path_rate);
+       int link, ret;
+       struct ib_port_attr pa;
+
+       if (path_rate == IB_RATE_PORT_CURRENT) {
+               *ipd = 0;
+               return 0;
+       }
+
+       if (unlikely(path < 0)) {
+               ehca_err(&shca->ib_device, "Invalid static rate! path_rate=%x",
+                        path_rate);
+               return -EINVAL;
+       }
+
+       ret = ehca_query_port(&shca->ib_device, port, &pa);
+       if (unlikely(ret < 0)) {
+               ehca_err(&shca->ib_device, "Failed to query port  ret=%i", ret);
+               return ret;
+       }
+
+       link = ib_width_enum_to_int(pa.active_width) * pa.active_speed;
+
+       if (path >= link)
+               /* no need to throttle if path faster than link */
+               *ipd = 0;
+       else
+               /* IPD = round((link / path) - 1) */
+               *ipd = ((link + (path >> 1)) / path) - 1;
+
+       return 0;
+}
+
+struct ib_ah *ehca_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
+{
+       int ret;
+       struct ehca_av *av;
+       struct ehca_shca *shca = container_of(pd->device, struct ehca_shca,
+                                             ib_device);
+
+       av = kmem_cache_alloc(av_cache, GFP_KERNEL);
+       if (!av) {
+               ehca_err(pd->device, "Out of memory pd=%p ah_attr=%p",
+                        pd, ah_attr);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       av->av.sl = ah_attr->sl;
+       av->av.dlid = ah_attr->dlid;
+       av->av.slid_path_bits = ah_attr->src_path_bits;
+
+       if (ehca_static_rate < 0) {
+               u32 ipd;
+               if (ehca_calc_ipd(shca, ah_attr->port_num,
+                                 ah_attr->static_rate, &ipd)) {
+                       ret = -EINVAL;
+                       goto create_ah_exit1;
+               }
+               av->av.ipd = ipd;
+       } else
+               av->av.ipd = ehca_static_rate;
+
+       av->av.lnh = ah_attr->ah_flags;
+       av->av.grh.word_0 = EHCA_BMASK_SET(GRH_IPVERSION_MASK, 6);
+       av->av.grh.word_0 |= EHCA_BMASK_SET(GRH_TCLASS_MASK,
+                                           ah_attr->grh.traffic_class);
+       av->av.grh.word_0 |= EHCA_BMASK_SET(GRH_FLOWLABEL_MASK,
+                                           ah_attr->grh.flow_label);
+       av->av.grh.word_0 |= EHCA_BMASK_SET(GRH_HOPLIMIT_MASK,
+                                           ah_attr->grh.hop_limit);
+       av->av.grh.word_0 |= EHCA_BMASK_SET(GRH_NEXTHEADER_MASK, 0x1B);
+       /* set sgid in grh.word_1 */
+       if (ah_attr->ah_flags & IB_AH_GRH) {
+               int rc;
+               struct ib_port_attr port_attr;
+               union ib_gid gid;
+               memset(&port_attr, 0, sizeof(port_attr));
+               rc = ehca_query_port(pd->device, ah_attr->port_num,
+                                    &port_attr);
+               if (rc) { /* invalid port number */
+                       ret = -EINVAL;
+                       ehca_err(pd->device, "Invalid port number "
+                                "ehca_query_port() returned %x "
+                                "pd=%p ah_attr=%p", rc, pd, ah_attr);
+                       goto create_ah_exit1;
+               }
+               memset(&gid, 0, sizeof(gid));
+               rc = ehca_query_gid(pd->device,
+                                   ah_attr->port_num,
+                                   ah_attr->grh.sgid_index, &gid);
+               if (rc) {
+                       ret = -EINVAL;
+                       ehca_err(pd->device, "Failed to retrieve sgid "
+                                "ehca_query_gid() returned %x "
+                                "pd=%p ah_attr=%p", rc, pd, ah_attr);
+                       goto create_ah_exit1;
+               }
+               memcpy(&av->av.grh.word_1, &gid, sizeof(gid));
+       }
+       av->av.pmtu = shca->max_mtu;
+
+       /* dgid comes in grh.word_3 */
+       memcpy(&av->av.grh.word_3, &ah_attr->grh.dgid,
+              sizeof(ah_attr->grh.dgid));
+
+       return &av->ib_ah;
+
+create_ah_exit1:
+       kmem_cache_free(av_cache, av);
+
+       return ERR_PTR(ret);
+}
+
+int ehca_modify_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr)
+{
+       struct ehca_av *av;
+       struct ehca_ud_av new_ehca_av;
+       struct ehca_shca *shca = container_of(ah->pd->device, struct ehca_shca,
+                                             ib_device);
+
+       memset(&new_ehca_av, 0, sizeof(new_ehca_av));
+       new_ehca_av.sl = ah_attr->sl;
+       new_ehca_av.dlid = ah_attr->dlid;
+       new_ehca_av.slid_path_bits = ah_attr->src_path_bits;
+       new_ehca_av.ipd = ah_attr->static_rate;
+       new_ehca_av.lnh = EHCA_BMASK_SET(GRH_FLAG_MASK,
+                                        (ah_attr->ah_flags & IB_AH_GRH) > 0);
+       new_ehca_av.grh.word_0 = EHCA_BMASK_SET(GRH_TCLASS_MASK,
+                                               ah_attr->grh.traffic_class);
+       new_ehca_av.grh.word_0 |= EHCA_BMASK_SET(GRH_FLOWLABEL_MASK,
+                                                ah_attr->grh.flow_label);
+       new_ehca_av.grh.word_0 |= EHCA_BMASK_SET(GRH_HOPLIMIT_MASK,
+                                                ah_attr->grh.hop_limit);
+       new_ehca_av.grh.word_0 |= EHCA_BMASK_SET(GRH_NEXTHEADER_MASK, 0x1b);
+
+       /* set sgid in grh.word_1 */
+       if (ah_attr->ah_flags & IB_AH_GRH) {
+               int rc;
+               struct ib_port_attr port_attr;
+               union ib_gid gid;
+               memset(&port_attr, 0, sizeof(port_attr));
+               rc = ehca_query_port(ah->device, ah_attr->port_num,
+                                    &port_attr);
+               if (rc) { /* invalid port number */
+                       ehca_err(ah->device, "Invalid port number "
+                                "ehca_query_port() returned %x "
+                                "ah=%p ah_attr=%p port_num=%x",
+                                rc, ah, ah_attr, ah_attr->port_num);
+                       return -EINVAL;
+               }
+               memset(&gid, 0, sizeof(gid));
+               rc = ehca_query_gid(ah->device,
+                                   ah_attr->port_num,
+                                   ah_attr->grh.sgid_index, &gid);
+               if (rc) {
+                       ehca_err(ah->device, "Failed to retrieve sgid "
+                                "ehca_query_gid() returned %x "
+                                "ah=%p ah_attr=%p port_num=%x "
+                                "sgid_index=%x",
+                                rc, ah, ah_attr, ah_attr->port_num,
+                                ah_attr->grh.sgid_index);
+                       return -EINVAL;
+               }
+               memcpy(&new_ehca_av.grh.word_1, &gid, sizeof(gid));
+       }
+
+       new_ehca_av.pmtu = shca->max_mtu;
+
+       memcpy(&new_ehca_av.grh.word_3, &ah_attr->grh.dgid,
+              sizeof(ah_attr->grh.dgid));
+
+       av = container_of(ah, struct ehca_av, ib_ah);
+       av->av = new_ehca_av;
+
+       return 0;
+}
+
+int ehca_query_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr)
+{
+       struct ehca_av *av = container_of(ah, struct ehca_av, ib_ah);
+
+       memcpy(&ah_attr->grh.dgid, &av->av.grh.word_3,
+              sizeof(ah_attr->grh.dgid));
+       ah_attr->sl = av->av.sl;
+
+       ah_attr->dlid = av->av.dlid;
+
+       ah_attr->src_path_bits = av->av.slid_path_bits;
+       ah_attr->static_rate = av->av.ipd;
+       ah_attr->ah_flags = EHCA_BMASK_GET(GRH_FLAG_MASK, av->av.lnh);
+       ah_attr->grh.traffic_class = EHCA_BMASK_GET(GRH_TCLASS_MASK,
+                                                   av->av.grh.word_0);
+       ah_attr->grh.hop_limit = EHCA_BMASK_GET(GRH_HOPLIMIT_MASK,
+                                               av->av.grh.word_0);
+       ah_attr->grh.flow_label = EHCA_BMASK_GET(GRH_FLOWLABEL_MASK,
+                                                av->av.grh.word_0);
+
+       return 0;
+}
+
+int ehca_destroy_ah(struct ib_ah *ah)
+{
+       kmem_cache_free(av_cache, container_of(ah, struct ehca_av, ib_ah));
+
+       return 0;
+}
+
+int ehca_init_av_cache(void)
+{
+       av_cache = kmem_cache_create("ehca_cache_av",
+                                  sizeof(struct ehca_av), 0,
+                                  SLAB_HWCACHE_ALIGN,
+                                  NULL);
+       if (!av_cache)
+               return -ENOMEM;
+       return 0;
+}
+
+void ehca_cleanup_av_cache(void)
+{
+       if (av_cache)
+               kmem_cache_destroy(av_cache);
+}
diff --git a/drivers/staging/rdma/ehca/ehca_classes.h b/drivers/staging/rdma/ehca/ehca_classes.h
new file mode 100644 (file)
index 0000000..bd45e0f
--- /dev/null
@@ -0,0 +1,482 @@
+/*
+ *  IBM eServer eHCA Infiniband device driver for Linux on POWER
+ *
+ *  Struct definition for eHCA internal structures
+ *
+ *  Authors: Heiko J Schick <schickhj@de.ibm.com>
+ *           Christoph Raisch <raisch@de.ibm.com>
+ *           Joachim Fenkes <fenkes@de.ibm.com>
+ *
+ *  Copyright (c) 2005 IBM Corporation
+ *
+ *  All rights reserved.
+ *
+ *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
+ *  BSD.
+ *
+ * OpenIB BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __EHCA_CLASSES_H__
+#define __EHCA_CLASSES_H__
+
+struct ehca_module;
+struct ehca_qp;
+struct ehca_cq;
+struct ehca_eq;
+struct ehca_mr;
+struct ehca_mw;
+struct ehca_pd;
+struct ehca_av;
+
+#include <linux/wait.h>
+#include <linux/mutex.h>
+
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_user_verbs.h>
+
+#ifdef CONFIG_PPC64
+#include "ehca_classes_pSeries.h"
+#endif
+#include "ipz_pt_fn.h"
+#include "ehca_qes.h"
+#include "ehca_irq.h"
+
+#define EHCA_EQE_CACHE_SIZE 20
+#define EHCA_MAX_NUM_QUEUES 0xffff
+
+struct ehca_eqe_cache_entry {
+       struct ehca_eqe *eqe;
+       struct ehca_cq *cq;
+};
+
+struct ehca_eq {
+       u32 length;
+       struct ipz_queue ipz_queue;
+       struct ipz_eq_handle ipz_eq_handle;
+       struct work_struct work;
+       struct h_galpas galpas;
+       int is_initialized;
+       struct ehca_pfeq pf;
+       spinlock_t spinlock;
+       struct tasklet_struct interrupt_task;
+       u32 ist;
+       spinlock_t irq_spinlock;
+       struct ehca_eqe_cache_entry eqe_cache[EHCA_EQE_CACHE_SIZE];
+};
+
+struct ehca_sma_attr {
+       u16 lid, lmc, sm_sl, sm_lid;
+       u16 pkey_tbl_len, pkeys[16];
+};
+
+struct ehca_sport {
+       struct ib_cq *ibcq_aqp1;
+       struct ib_qp *ibqp_sqp[2];
+       /* lock to serialze modify_qp() calls for sqp in normal
+        * and irq path (when event PORT_ACTIVE is received first time)
+        */
+       spinlock_t mod_sqp_lock;
+       enum ib_port_state port_state;
+       struct ehca_sma_attr saved_attr;
+       u32 pma_qp_nr;
+};
+
+#define HCA_CAP_MR_PGSIZE_4K  0x80000000
+#define HCA_CAP_MR_PGSIZE_64K 0x40000000
+#define HCA_CAP_MR_PGSIZE_1M  0x20000000
+#define HCA_CAP_MR_PGSIZE_16M 0x10000000
+
+struct ehca_shca {
+       struct ib_device ib_device;
+       struct platform_device *ofdev;
+       u8 num_ports;
+       int hw_level;
+       struct list_head shca_list;
+       struct ipz_adapter_handle ipz_hca_handle;
+       struct ehca_sport sport[2];
+       struct ehca_eq eq;
+       struct ehca_eq neq;
+       struct ehca_mr *maxmr;
+       struct ehca_pd *pd;
+       struct h_galpas galpas;
+       struct mutex modify_mutex;
+       u64 hca_cap;
+       /* MR pgsize: bit 0-3 means 4K, 64K, 1M, 16M respectively */
+       u32 hca_cap_mr_pgsize;
+       int max_mtu;
+       int max_num_qps;
+       int max_num_cqs;
+       atomic_t num_cqs;
+       atomic_t num_qps;
+};
+
+struct ehca_pd {
+       struct ib_pd ib_pd;
+       struct ipz_pd fw_pd;
+       /* small queue mgmt */
+       struct mutex lock;
+       struct list_head free[2];
+       struct list_head full[2];
+};
+
+enum ehca_ext_qp_type {
+       EQPT_NORMAL    = 0,
+       EQPT_LLQP      = 1,
+       EQPT_SRQBASE   = 2,
+       EQPT_SRQ       = 3,
+};
+
+/* struct to cache modify_qp()'s parms for GSI/SMI qp */
+struct ehca_mod_qp_parm {
+       int mask;
+       struct ib_qp_attr attr;
+};
+
+#define EHCA_MOD_QP_PARM_MAX 4
+
+#define QMAP_IDX_MASK 0xFFFFULL
+
+/* struct for tracking if cqes have been reported to the application */
+struct ehca_qmap_entry {
+       u16 app_wr_id;
+       u8 reported;
+       u8 cqe_req;
+};
+
+struct ehca_queue_map {
+       struct ehca_qmap_entry *map;
+       unsigned int entries;
+       unsigned int tail;
+       unsigned int left_to_poll;
+       unsigned int next_wqe_idx;   /* Idx to first wqe to be flushed */
+};
+
+/* function to calculate the next index for the qmap */
+static inline unsigned int next_index(unsigned int cur_index, unsigned int limit)
+{
+       unsigned int temp = cur_index + 1;
+       return (temp == limit) ? 0 : temp;
+}
+
+struct ehca_qp {
+       union {
+               struct ib_qp ib_qp;
+               struct ib_srq ib_srq;
+       };
+       u32 qp_type;
+       enum ehca_ext_qp_type ext_type;
+       enum ib_qp_state state;
+       struct ipz_queue ipz_squeue;
+       struct ehca_queue_map sq_map;
+       struct ipz_queue ipz_rqueue;
+       struct ehca_queue_map rq_map;
+       struct h_galpas galpas;
+       u32 qkey;
+       u32 real_qp_num;
+       u32 token;
+       spinlock_t spinlock_s;
+       spinlock_t spinlock_r;
+       u32 sq_max_inline_data_size;
+       struct ipz_qp_handle ipz_qp_handle;
+       struct ehca_pfqp pf;
+       struct ib_qp_init_attr init_attr;
+       struct ehca_cq *send_cq;
+       struct ehca_cq *recv_cq;
+       unsigned int sqerr_purgeflag;
+       struct hlist_node list_entries;
+       /* array to cache modify_qp()'s parms for GSI/SMI qp */
+       struct ehca_mod_qp_parm *mod_qp_parm;
+       int mod_qp_parm_idx;
+       /* mmap counter for resources mapped into user space */
+       u32 mm_count_squeue;
+       u32 mm_count_rqueue;
+       u32 mm_count_galpa;
+       /* unsolicited ack circumvention */
+       int unsol_ack_circ;
+       int mtu_shift;
+       u32 message_count;
+       u32 packet_count;
+       atomic_t nr_events; /* events seen */
+       wait_queue_head_t wait_completion;
+       int mig_armed;
+       struct list_head sq_err_node;
+       struct list_head rq_err_node;
+};
+
+#define IS_SRQ(qp) (qp->ext_type == EQPT_SRQ)
+#define HAS_SQ(qp) (qp->ext_type != EQPT_SRQ)
+#define HAS_RQ(qp) (qp->ext_type != EQPT_SRQBASE)
+
+/* must be power of 2 */
+#define QP_HASHTAB_LEN 8
+
+struct ehca_cq {
+       struct ib_cq ib_cq;
+       struct ipz_queue ipz_queue;
+       struct h_galpas galpas;
+       spinlock_t spinlock;
+       u32 cq_number;
+       u32 token;
+       u32 nr_of_entries;
+       struct ipz_cq_handle ipz_cq_handle;
+       struct ehca_pfcq pf;
+       spinlock_t cb_lock;
+       struct hlist_head qp_hashtab[QP_HASHTAB_LEN];
+       struct list_head entry;
+       u32 nr_callbacks;   /* #events assigned to cpu by scaling code */
+       atomic_t nr_events; /* #events seen */
+       wait_queue_head_t wait_completion;
+       spinlock_t task_lock;
+       /* mmap counter for resources mapped into user space */
+       u32 mm_count_queue;
+       u32 mm_count_galpa;
+       struct list_head sqp_err_list;
+       struct list_head rqp_err_list;
+};
+
+enum ehca_mr_flag {
+       EHCA_MR_FLAG_FMR = 0x80000000,   /* FMR, created with ehca_alloc_fmr */
+       EHCA_MR_FLAG_MAXMR = 0x40000000, /* max-MR                           */
+};
+
+struct ehca_mr {
+       union {
+               struct ib_mr ib_mr;     /* must always be first in ehca_mr */
+               struct ib_fmr ib_fmr;   /* must always be first in ehca_mr */
+       } ib;
+       struct ib_umem *umem;
+       spinlock_t mrlock;
+
+       enum ehca_mr_flag flags;
+       u32 num_kpages;         /* number of kernel pages */
+       u32 num_hwpages;        /* number of hw pages to form MR */
+       u64 hwpage_size;        /* hw page size used for this MR */
+       int acl;                /* ACL (stored here for usage in reregister) */
+       u64 *start;             /* virtual start address (stored here for */
+                               /* usage in reregister) */
+       u64 size;               /* size (stored here for usage in reregister) */
+       u32 fmr_page_size;      /* page size for FMR */
+       u32 fmr_max_pages;      /* max pages for FMR */
+       u32 fmr_max_maps;       /* max outstanding maps for FMR */
+       u32 fmr_map_cnt;        /* map counter for FMR */
+       /* fw specific data */
+       struct ipz_mrmw_handle ipz_mr_handle;   /* MR handle for h-calls */
+       struct h_galpas galpas;
+};
+
+struct ehca_mw {
+       struct ib_mw ib_mw;     /* gen2 mw, must always be first in ehca_mw */
+       spinlock_t mwlock;
+
+       u8 never_bound;         /* indication MW was never bound */
+       struct ipz_mrmw_handle ipz_mw_handle;   /* MW handle for h-calls */
+       struct h_galpas galpas;
+};
+
+enum ehca_mr_pgi_type {
+       EHCA_MR_PGI_PHYS   = 1,  /* type of ehca_reg_phys_mr,
+                                 * ehca_rereg_phys_mr,
+                                 * ehca_reg_internal_maxmr */
+       EHCA_MR_PGI_USER   = 2,  /* type of ehca_reg_user_mr */
+       EHCA_MR_PGI_FMR    = 3   /* type of ehca_map_phys_fmr */
+};
+
+struct ehca_mr_pginfo {
+       enum ehca_mr_pgi_type type;
+       u64 num_kpages;
+       u64 kpage_cnt;
+       u64 hwpage_size;     /* hw page size used for this MR */
+       u64 num_hwpages;     /* number of hw pages */
+       u64 hwpage_cnt;      /* counter for hw pages */
+       u64 next_hwpage;     /* next hw page in buffer/chunk/listelem */
+
+       union {
+               struct { /* type EHCA_MR_PGI_PHYS section */
+                       int num_phys_buf;
+                       struct ib_phys_buf *phys_buf_array;
+                       u64 next_buf;
+               } phy;
+               struct { /* type EHCA_MR_PGI_USER section */
+                       struct ib_umem *region;
+                       struct scatterlist *next_sg;
+                       u64 next_nmap;
+               } usr;
+               struct { /* type EHCA_MR_PGI_FMR section */
+                       u64 fmr_pgsize;
+                       u64 *page_list;
+                       u64 next_listelem;
+               } fmr;
+       } u;
+};
+
+/* output parameters for MR/FMR hipz calls */
+struct ehca_mr_hipzout_parms {
+       struct ipz_mrmw_handle handle;
+       u32 lkey;
+       u32 rkey;
+       u64 len;
+       u64 vaddr;
+       u32 acl;
+};
+
+/* output parameters for MW hipz calls */
+struct ehca_mw_hipzout_parms {
+       struct ipz_mrmw_handle handle;
+       u32 rkey;
+};
+
+struct ehca_av {
+       struct ib_ah ib_ah;
+       struct ehca_ud_av av;
+};
+
+struct ehca_ucontext {
+       struct ib_ucontext ib_ucontext;
+};
+
+int ehca_init_pd_cache(void);
+void ehca_cleanup_pd_cache(void);
+int ehca_init_cq_cache(void);
+void ehca_cleanup_cq_cache(void);
+int ehca_init_qp_cache(void);
+void ehca_cleanup_qp_cache(void);
+int ehca_init_av_cache(void);
+void ehca_cleanup_av_cache(void);
+int ehca_init_mrmw_cache(void);
+void ehca_cleanup_mrmw_cache(void);
+int ehca_init_small_qp_cache(void);
+void ehca_cleanup_small_qp_cache(void);
+
+extern rwlock_t ehca_qp_idr_lock;
+extern rwlock_t ehca_cq_idr_lock;
+extern struct idr ehca_qp_idr;
+extern struct idr ehca_cq_idr;
+extern spinlock_t shca_list_lock;
+
+extern int ehca_static_rate;
+extern int ehca_port_act_time;
+extern bool ehca_use_hp_mr;
+extern bool ehca_scaling_code;
+extern int ehca_lock_hcalls;
+extern int ehca_nr_ports;
+extern int ehca_max_cq;
+extern int ehca_max_qp;
+
+struct ipzu_queue_resp {
+       u32 qe_size;      /* queue entry size */
+       u32 act_nr_of_sg;
+       u32 queue_length; /* queue length allocated in bytes */
+       u32 pagesize;
+       u32 toggle_state;
+       u32 offset; /* save offset within a page for small_qp */
+};
+
+struct ehca_create_cq_resp {
+       u32 cq_number;
+       u32 token;
+       struct ipzu_queue_resp ipz_queue;
+       u32 fw_handle_ofs;
+       u32 dummy;
+};
+
+struct ehca_create_qp_resp {
+       u32 qp_num;
+       u32 token;
+       u32 qp_type;
+       u32 ext_type;
+       u32 qkey;
+       /* qp_num assigned by ehca: sqp0/1 may have got different numbers */
+       u32 real_qp_num;
+       u32 fw_handle_ofs;
+       u32 dummy;
+       struct ipzu_queue_resp ipz_squeue;
+       struct ipzu_queue_resp ipz_rqueue;
+};
+
+struct ehca_alloc_cq_parms {
+       u32 nr_cqe;
+       u32 act_nr_of_entries;
+       u32 act_pages;
+       struct ipz_eq_handle eq_handle;
+};
+
+enum ehca_service_type {
+       ST_RC  = 0,
+       ST_UC  = 1,
+       ST_RD  = 2,
+       ST_UD  = 3,
+};
+
+enum ehca_ll_comp_flags {
+       LLQP_SEND_COMP = 0x20,
+       LLQP_RECV_COMP = 0x40,
+       LLQP_COMP_MASK = 0x60,
+};
+
+struct ehca_alloc_queue_parms {
+       /* input parameters */
+       int max_wr;
+       int max_sge;
+       int page_size;
+       int is_small;
+
+       /* output parameters */
+       u16 act_nr_wqes;
+       u8  act_nr_sges;
+       u32 queue_size; /* bytes for small queues, pages otherwise */
+};
+
+struct ehca_alloc_qp_parms {
+       struct ehca_alloc_queue_parms squeue;
+       struct ehca_alloc_queue_parms rqueue;
+
+       /* input parameters */
+       enum ehca_service_type servicetype;
+       int qp_storage;
+       int sigtype;
+       enum ehca_ext_qp_type ext_type;
+       enum ehca_ll_comp_flags ll_comp_flags;
+       int ud_av_l_key_ctl;
+
+       u32 token;
+       struct ipz_eq_handle eq_handle;
+       struct ipz_pd pd;
+       struct ipz_cq_handle send_cq_handle, recv_cq_handle;
+
+       u32 srq_qpn, srq_token, srq_limit;
+
+       /* output parameters */
+       u32 real_qp_num;
+       struct ipz_qp_handle qp_handle;
+       struct h_galpas galpas;
+};
+
+int ehca_cq_assign_qp(struct ehca_cq *cq, struct ehca_qp *qp);
+int ehca_cq_unassign_qp(struct ehca_cq *cq, unsigned int qp_num);
+struct ehca_qp *ehca_cq_get_qp(struct ehca_cq *cq, int qp_num);
+
+#endif
diff --git a/drivers/staging/rdma/ehca/ehca_classes_pSeries.h b/drivers/staging/rdma/ehca/ehca_classes_pSeries.h
new file mode 100644 (file)
index 0000000..689c357
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ *  IBM eServer eHCA Infiniband device driver for Linux on POWER
+ *
+ *  pSeries interface definitions
+ *
+ *  Authors: Waleri Fomin <fomin@de.ibm.com>
+ *           Christoph Raisch <raisch@de.ibm.com>
+ *
+ *  Copyright (c) 2005 IBM Corporation
+ *
+ *  All rights reserved.
+ *
+ *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
+ *  BSD.
+ *
+ * OpenIB BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __EHCA_CLASSES_PSERIES_H__
+#define __EHCA_CLASSES_PSERIES_H__
+
+#include "hcp_phyp.h"
+#include "ipz_pt_fn.h"
+
+
+struct ehca_pfqp {
+       struct ipz_qpt sqpt;
+       struct ipz_qpt rqpt;
+};
+
+struct ehca_pfcq {
+       struct ipz_qpt qpt;
+       u32 cqnr;
+};
+
+struct ehca_pfeq {
+       struct ipz_qpt qpt;
+       struct h_galpa galpa;
+       u32 eqnr;
+};
+
+struct ipz_adapter_handle {
+       u64 handle;
+};
+
+struct ipz_cq_handle {
+       u64 handle;
+};
+
+struct ipz_eq_handle {
+       u64 handle;
+};
+
+struct ipz_qp_handle {
+       u64 handle;
+};
+struct ipz_mrmw_handle {
+       u64 handle;
+};
+
+struct ipz_pd {
+       u32 value;
+};
+
+struct hcp_modify_qp_control_block {
+       u32 qkey;                      /* 00 */
+       u32 rdd;                       /* reliable datagram domain */
+       u32 send_psn;                  /* 02 */
+       u32 receive_psn;               /* 03 */
+       u32 prim_phys_port;            /* 04 */
+       u32 alt_phys_port;             /* 05 */
+       u32 prim_p_key_idx;            /* 06 */
+       u32 alt_p_key_idx;             /* 07 */
+       u32 rdma_atomic_ctrl;          /* 08 */
+       u32 qp_state;                  /* 09 */
+       u32 reserved_10;               /* 10 */
+       u32 rdma_nr_atomic_resp_res;   /* 11 */
+       u32 path_migration_state;      /* 12 */
+       u32 rdma_atomic_outst_dest_qp; /* 13 */
+       u32 dest_qp_nr;                /* 14 */
+       u32 min_rnr_nak_timer_field;   /* 15 */
+       u32 service_level;             /* 16 */
+       u32 send_grh_flag;             /* 17 */
+       u32 retry_count;               /* 18 */
+       u32 timeout;                   /* 19 */
+       u32 path_mtu;                  /* 20 */
+       u32 max_static_rate;           /* 21 */
+       u32 dlid;                      /* 22 */
+       u32 rnr_retry_count;           /* 23 */
+       u32 source_path_bits;          /* 24 */
+       u32 traffic_class;             /* 25 */
+       u32 hop_limit;                 /* 26 */
+       u32 source_gid_idx;            /* 27 */
+       u32 flow_label;                /* 28 */
+       u32 reserved_29;               /* 29 */
+       union {                        /* 30 */
+               u64 dw[2];
+               u8 byte[16];
+       } dest_gid;
+       u32 service_level_al;          /* 34 */
+       u32 send_grh_flag_al;          /* 35 */
+       u32 retry_count_al;            /* 36 */
+       u32 timeout_al;                /* 37 */
+       u32 max_static_rate_al;        /* 38 */
+       u32 dlid_al;                   /* 39 */
+       u32 rnr_retry_count_al;        /* 40 */
+       u32 source_path_bits_al;       /* 41 */
+       u32 traffic_class_al;          /* 42 */
+       u32 hop_limit_al;              /* 43 */
+       u32 source_gid_idx_al;         /* 44 */
+       u32 flow_label_al;             /* 45 */
+       u32 reserved_46;               /* 46 */
+       u32 reserved_47;               /* 47 */
+       union {                        /* 48 */
+               u64 dw[2];
+               u8 byte[16];
+       } dest_gid_al;
+       u32 max_nr_outst_send_wr;      /* 52 */
+       u32 max_nr_outst_recv_wr;      /* 53 */
+       u32 disable_ete_credit_check;  /* 54 */
+       u32 qp_number;                 /* 55 */
+       u64 send_queue_handle;         /* 56 */
+       u64 recv_queue_handle;         /* 58 */
+       u32 actual_nr_sges_in_sq_wqe;  /* 60 */
+       u32 actual_nr_sges_in_rq_wqe;  /* 61 */
+       u32 qp_enable;                 /* 62 */
+       u32 curr_srq_limit;            /* 63 */
+       u64 qp_aff_asyn_ev_log_reg;    /* 64 */
+       u64 shared_rq_hndl;            /* 66 */
+       u64 trigg_doorbell_qp_hndl;    /* 68 */
+       u32 reserved_70_127[58];       /* 70 */
+};
+
+#define MQPCB_MASK_QKEY                         EHCA_BMASK_IBM( 0,  0)
+#define MQPCB_MASK_SEND_PSN                     EHCA_BMASK_IBM( 2,  2)
+#define MQPCB_MASK_RECEIVE_PSN                  EHCA_BMASK_IBM( 3,  3)
+#define MQPCB_MASK_PRIM_PHYS_PORT               EHCA_BMASK_IBM( 4,  4)
+#define MQPCB_PRIM_PHYS_PORT                    EHCA_BMASK_IBM(24, 31)
+#define MQPCB_MASK_ALT_PHYS_PORT                EHCA_BMASK_IBM( 5,  5)
+#define MQPCB_MASK_PRIM_P_KEY_IDX               EHCA_BMASK_IBM( 6,  6)
+#define MQPCB_PRIM_P_KEY_IDX                    EHCA_BMASK_IBM(24, 31)
+#define MQPCB_MASK_ALT_P_KEY_IDX                EHCA_BMASK_IBM( 7,  7)
+#define MQPCB_MASK_RDMA_ATOMIC_CTRL             EHCA_BMASK_IBM( 8,  8)
+#define MQPCB_MASK_QP_STATE                     EHCA_BMASK_IBM( 9,  9)
+#define MQPCB_MASK_RDMA_NR_ATOMIC_RESP_RES      EHCA_BMASK_IBM(11, 11)
+#define MQPCB_MASK_PATH_MIGRATION_STATE         EHCA_BMASK_IBM(12, 12)
+#define MQPCB_MASK_RDMA_ATOMIC_OUTST_DEST_QP    EHCA_BMASK_IBM(13, 13)
+#define MQPCB_MASK_DEST_QP_NR                   EHCA_BMASK_IBM(14, 14)
+#define MQPCB_MASK_MIN_RNR_NAK_TIMER_FIELD      EHCA_BMASK_IBM(15, 15)
+#define MQPCB_MASK_SERVICE_LEVEL                EHCA_BMASK_IBM(16, 16)
+#define MQPCB_MASK_SEND_GRH_FLAG                EHCA_BMASK_IBM(17, 17)
+#define MQPCB_MASK_RETRY_COUNT                  EHCA_BMASK_IBM(18, 18)
+#define MQPCB_MASK_TIMEOUT                      EHCA_BMASK_IBM(19, 19)
+#define MQPCB_MASK_PATH_MTU                     EHCA_BMASK_IBM(20, 20)
+#define MQPCB_MASK_MAX_STATIC_RATE              EHCA_BMASK_IBM(21, 21)
+#define MQPCB_MASK_DLID                         EHCA_BMASK_IBM(22, 22)
+#define MQPCB_MASK_RNR_RETRY_COUNT              EHCA_BMASK_IBM(23, 23)
+#define MQPCB_MASK_SOURCE_PATH_BITS             EHCA_BMASK_IBM(24, 24)
+#define MQPCB_MASK_TRAFFIC_CLASS                EHCA_BMASK_IBM(25, 25)
+#define MQPCB_MASK_HOP_LIMIT                    EHCA_BMASK_IBM(26, 26)
+#define MQPCB_MASK_SOURCE_GID_IDX               EHCA_BMASK_IBM(27, 27)
+#define MQPCB_MASK_FLOW_LABEL                   EHCA_BMASK_IBM(28, 28)
+#define MQPCB_MASK_DEST_GID                     EHCA_BMASK_IBM(30, 30)
+#define MQPCB_MASK_SERVICE_LEVEL_AL             EHCA_BMASK_IBM(31, 31)
+#define MQPCB_MASK_SEND_GRH_FLAG_AL             EHCA_BMASK_IBM(32, 32)
+#define MQPCB_MASK_RETRY_COUNT_AL               EHCA_BMASK_IBM(33, 33)
+#define MQPCB_MASK_TIMEOUT_AL                   EHCA_BMASK_IBM(34, 34)
+#define MQPCB_MASK_MAX_STATIC_RATE_AL           EHCA_BMASK_IBM(35, 35)
+#define MQPCB_MASK_DLID_AL                      EHCA_BMASK_IBM(36, 36)
+#define MQPCB_MASK_RNR_RETRY_COUNT_AL           EHCA_BMASK_IBM(37, 37)
+#define MQPCB_MASK_SOURCE_PATH_BITS_AL          EHCA_BMASK_IBM(38, 38)
+#define MQPCB_MASK_TRAFFIC_CLASS_AL             EHCA_BMASK_IBM(39, 39)
+#define MQPCB_MASK_HOP_LIMIT_AL                 EHCA_BMASK_IBM(40, 40)
+#define MQPCB_MASK_SOURCE_GID_IDX_AL            EHCA_BMASK_IBM(41, 41)
+#define MQPCB_MASK_FLOW_LABEL_AL                EHCA_BMASK_IBM(42, 42)
+#define MQPCB_MASK_DEST_GID_AL                  EHCA_BMASK_IBM(44, 44)
+#define MQPCB_MASK_MAX_NR_OUTST_SEND_WR         EHCA_BMASK_IBM(45, 45)
+#define MQPCB_MASK_MAX_NR_OUTST_RECV_WR         EHCA_BMASK_IBM(46, 46)
+#define MQPCB_MASK_DISABLE_ETE_CREDIT_CHECK     EHCA_BMASK_IBM(47, 47)
+#define MQPCB_MASK_QP_ENABLE                    EHCA_BMASK_IBM(48, 48)
+#define MQPCB_MASK_CURR_SRQ_LIMIT               EHCA_BMASK_IBM(49, 49)
+#define MQPCB_MASK_QP_AFF_ASYN_EV_LOG_REG       EHCA_BMASK_IBM(50, 50)
+#define MQPCB_MASK_SHARED_RQ_HNDL               EHCA_BMASK_IBM(51, 51)
+
+#endif /* __EHCA_CLASSES_PSERIES_H__ */
diff --git a/drivers/staging/rdma/ehca/ehca_cq.c b/drivers/staging/rdma/ehca/ehca_cq.c
new file mode 100644 (file)
index 0000000..9b68b17
--- /dev/null
@@ -0,0 +1,397 @@
+/*
+ *  IBM eServer eHCA Infiniband device driver for Linux on POWER
+ *
+ *  Completion queue handling
+ *
+ *  Authors: Waleri Fomin <fomin@de.ibm.com>
+ *           Khadija Souissi <souissi@de.ibm.com>
+ *           Reinhard Ernst <rernst@de.ibm.com>
+ *           Heiko J Schick <schickhj@de.ibm.com>
+ *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
+ *
+ *
+ *  Copyright (c) 2005 IBM Corporation
+ *
+ *  All rights reserved.
+ *
+ *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
+ *  BSD.
+ *
+ * OpenIB BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/slab.h>
+
+#include "ehca_iverbs.h"
+#include "ehca_classes.h"
+#include "ehca_irq.h"
+#include "hcp_if.h"
+
+static struct kmem_cache *cq_cache;
+
+int ehca_cq_assign_qp(struct ehca_cq *cq, struct ehca_qp *qp)
+{
+       unsigned int qp_num = qp->real_qp_num;
+       unsigned int key = qp_num & (QP_HASHTAB_LEN-1);
+       unsigned long flags;
+
+       spin_lock_irqsave(&cq->spinlock, flags);
+       hlist_add_head(&qp->list_entries, &cq->qp_hashtab[key]);
+       spin_unlock_irqrestore(&cq->spinlock, flags);
+
+       ehca_dbg(cq->ib_cq.device, "cq_num=%x real_qp_num=%x",
+                cq->cq_number, qp_num);
+
+       return 0;
+}
+
+int ehca_cq_unassign_qp(struct ehca_cq *cq, unsigned int real_qp_num)
+{
+       int ret = -EINVAL;
+       unsigned int key = real_qp_num & (QP_HASHTAB_LEN-1);
+       struct hlist_node *iter;
+       struct ehca_qp *qp;
+       unsigned long flags;
+
+       spin_lock_irqsave(&cq->spinlock, flags);
+       hlist_for_each(iter, &cq->qp_hashtab[key]) {
+               qp = hlist_entry(iter, struct ehca_qp, list_entries);
+               if (qp->real_qp_num == real_qp_num) {
+                       hlist_del(iter);
+                       ehca_dbg(cq->ib_cq.device,
+                                "removed qp from cq .cq_num=%x real_qp_num=%x",
+                                cq->cq_number, real_qp_num);
+                       ret = 0;
+                       break;
+               }
+       }
+       spin_unlock_irqrestore(&cq->spinlock, flags);
+       if (ret)
+               ehca_err(cq->ib_cq.device,
+                        "qp not found cq_num=%x real_qp_num=%x",
+                        cq->cq_number, real_qp_num);
+
+       return ret;
+}
+
+struct ehca_qp *ehca_cq_get_qp(struct ehca_cq *cq, int real_qp_num)
+{
+       struct ehca_qp *ret = NULL;
+       unsigned int key = real_qp_num & (QP_HASHTAB_LEN-1);
+       struct hlist_node *iter;
+       struct ehca_qp *qp;
+       hlist_for_each(iter, &cq->qp_hashtab[key]) {
+               qp = hlist_entry(iter, struct ehca_qp, list_entries);
+               if (qp->real_qp_num == real_qp_num) {
+                       ret = qp;
+                       break;
+               }
+       }
+       return ret;
+}
+
+struct ib_cq *ehca_create_cq(struct ib_device *device,
+                            const struct ib_cq_init_attr *attr,
+                            struct ib_ucontext *context,
+                            struct ib_udata *udata)
+{
+       int cqe = attr->cqe;
+       static const u32 additional_cqe = 20;
+       struct ib_cq *cq;
+       struct ehca_cq *my_cq;
+       struct ehca_shca *shca =
+               container_of(device, struct ehca_shca, ib_device);
+       struct ipz_adapter_handle adapter_handle;
+       struct ehca_alloc_cq_parms param; /* h_call's out parameters */
+       struct h_galpa gal;
+       void *vpage;
+       u32 counter;
+       u64 rpage, cqx_fec, h_ret;
+       int ipz_rc, i;
+       unsigned long flags;
+
+       if (attr->flags)
+               return ERR_PTR(-EINVAL);
+
+       if (cqe >= 0xFFFFFFFF - 64 - additional_cqe)
+               return ERR_PTR(-EINVAL);
+
+       if (!atomic_add_unless(&shca->num_cqs, 1, shca->max_num_cqs)) {
+               ehca_err(device, "Unable to create CQ, max number of %i "
+                       "CQs reached.", shca->max_num_cqs);
+               ehca_err(device, "To increase the maximum number of CQs "
+                       "use the number_of_cqs module parameter.\n");
+               return ERR_PTR(-ENOSPC);
+       }
+
+       my_cq = kmem_cache_zalloc(cq_cache, GFP_KERNEL);
+       if (!my_cq) {
+               ehca_err(device, "Out of memory for ehca_cq struct device=%p",
+                        device);
+               atomic_dec(&shca->num_cqs);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       memset(&param, 0, sizeof(struct ehca_alloc_cq_parms));
+
+       spin_lock_init(&my_cq->spinlock);
+       spin_lock_init(&my_cq->cb_lock);
+       spin_lock_init(&my_cq->task_lock);
+       atomic_set(&my_cq->nr_events, 0);
+       init_waitqueue_head(&my_cq->wait_completion);
+
+       cq = &my_cq->ib_cq;
+
+       adapter_handle = shca->ipz_hca_handle;
+       param.eq_handle = shca->eq.ipz_eq_handle;
+
+       idr_preload(GFP_KERNEL);
+       write_lock_irqsave(&ehca_cq_idr_lock, flags);
+       my_cq->token = idr_alloc(&ehca_cq_idr, my_cq, 0, 0x2000000, GFP_NOWAIT);
+       write_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+       idr_preload_end();
+
+       if (my_cq->token < 0) {
+               cq = ERR_PTR(-ENOMEM);
+               ehca_err(device, "Can't allocate new idr entry. device=%p",
+                        device);
+               goto create_cq_exit1;
+       }
+
+       /*
+        * CQs maximum depth is 4GB-64, but we need additional 20 as buffer
+        * for receiving errors CQEs.
+        */
+       param.nr_cqe = cqe + additional_cqe;
+       h_ret = hipz_h_alloc_resource_cq(adapter_handle, my_cq, &param);
+
+       if (h_ret != H_SUCCESS) {
+               ehca_err(device, "hipz_h_alloc_resource_cq() failed "
+                        "h_ret=%lli device=%p", h_ret, device);
+               cq = ERR_PTR(ehca2ib_return_code(h_ret));
+               goto create_cq_exit2;
+       }
+
+       ipz_rc = ipz_queue_ctor(NULL, &my_cq->ipz_queue, param.act_pages,
+                               EHCA_PAGESIZE, sizeof(struct ehca_cqe), 0, 0);
+       if (!ipz_rc) {
+               ehca_err(device, "ipz_queue_ctor() failed ipz_rc=%i device=%p",
+                        ipz_rc, device);
+               cq = ERR_PTR(-EINVAL);
+               goto create_cq_exit3;
+       }
+
+       for (counter = 0; counter < param.act_pages; counter++) {
+               vpage = ipz_qpageit_get_inc(&my_cq->ipz_queue);
+               if (!vpage) {
+                       ehca_err(device, "ipz_qpageit_get_inc() "
+                                "returns NULL device=%p", device);
+                       cq = ERR_PTR(-EAGAIN);
+                       goto create_cq_exit4;
+               }
+               rpage = __pa(vpage);
+
+               h_ret = hipz_h_register_rpage_cq(adapter_handle,
+                                                my_cq->ipz_cq_handle,
+                                                &my_cq->pf,
+                                                0,
+                                                0,
+                                                rpage,
+                                                1,
+                                                my_cq->galpas.
+                                                kernel);
+
+               if (h_ret < H_SUCCESS) {
+                       ehca_err(device, "hipz_h_register_rpage_cq() failed "
+                                "ehca_cq=%p cq_num=%x h_ret=%lli counter=%i "
+                                "act_pages=%i", my_cq, my_cq->cq_number,
+                                h_ret, counter, param.act_pages);
+                       cq = ERR_PTR(-EINVAL);
+                       goto create_cq_exit4;
+               }
+
+               if (counter == (param.act_pages - 1)) {
+                       vpage = ipz_qpageit_get_inc(&my_cq->ipz_queue);
+                       if ((h_ret != H_SUCCESS) || vpage) {
+                               ehca_err(device, "Registration of pages not "
+                                        "complete ehca_cq=%p cq_num=%x "
+                                        "h_ret=%lli", my_cq, my_cq->cq_number,
+                                        h_ret);
+                               cq = ERR_PTR(-EAGAIN);
+                               goto create_cq_exit4;
+                       }
+               } else {
+                       if (h_ret != H_PAGE_REGISTERED) {
+                               ehca_err(device, "Registration of page failed "
+                                        "ehca_cq=%p cq_num=%x h_ret=%lli "
+                                        "counter=%i act_pages=%i",
+                                        my_cq, my_cq->cq_number,
+                                        h_ret, counter, param.act_pages);
+                               cq = ERR_PTR(-ENOMEM);
+                               goto create_cq_exit4;
+                       }
+               }
+       }
+
+       ipz_qeit_reset(&my_cq->ipz_queue);
+
+       gal = my_cq->galpas.kernel;
+       cqx_fec = hipz_galpa_load(gal, CQTEMM_OFFSET(cqx_fec));
+       ehca_dbg(device, "ehca_cq=%p cq_num=%x CQX_FEC=%llx",
+                my_cq, my_cq->cq_number, cqx_fec);
+
+       my_cq->ib_cq.cqe = my_cq->nr_of_entries =
+               param.act_nr_of_entries - additional_cqe;
+       my_cq->cq_number = (my_cq->ipz_cq_handle.handle) & 0xffff;
+
+       for (i = 0; i < QP_HASHTAB_LEN; i++)
+               INIT_HLIST_HEAD(&my_cq->qp_hashtab[i]);
+
+       INIT_LIST_HEAD(&my_cq->sqp_err_list);
+       INIT_LIST_HEAD(&my_cq->rqp_err_list);
+
+       if (context) {
+               struct ipz_queue *ipz_queue = &my_cq->ipz_queue;
+               struct ehca_create_cq_resp resp;
+               memset(&resp, 0, sizeof(resp));
+               resp.cq_number = my_cq->cq_number;
+               resp.token = my_cq->token;
+               resp.ipz_queue.qe_size = ipz_queue->qe_size;
+               resp.ipz_queue.act_nr_of_sg = ipz_queue->act_nr_of_sg;
+               resp.ipz_queue.queue_length = ipz_queue->queue_length;
+               resp.ipz_queue.pagesize = ipz_queue->pagesize;
+               resp.ipz_queue.toggle_state = ipz_queue->toggle_state;
+               resp.fw_handle_ofs = (u32)
+                       (my_cq->galpas.user.fw_handle & (PAGE_SIZE - 1));
+               if (ib_copy_to_udata(udata, &resp, sizeof(resp))) {
+                       ehca_err(device, "Copy to udata failed.");
+                       cq = ERR_PTR(-EFAULT);
+                       goto create_cq_exit4;
+               }
+       }
+
+       return cq;
+
+create_cq_exit4:
+       ipz_queue_dtor(NULL, &my_cq->ipz_queue);
+
+create_cq_exit3:
+       h_ret = hipz_h_destroy_cq(adapter_handle, my_cq, 1);
+       if (h_ret != H_SUCCESS)
+               ehca_err(device, "hipz_h_destroy_cq() failed ehca_cq=%p "
+                        "cq_num=%x h_ret=%lli", my_cq, my_cq->cq_number, h_ret);
+
+create_cq_exit2:
+       write_lock_irqsave(&ehca_cq_idr_lock, flags);
+       idr_remove(&ehca_cq_idr, my_cq->token);
+       write_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+
+create_cq_exit1:
+       kmem_cache_free(cq_cache, my_cq);
+
+       atomic_dec(&shca->num_cqs);
+       return cq;
+}
+
+int ehca_destroy_cq(struct ib_cq *cq)
+{
+       u64 h_ret;
+       struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq);
+       int cq_num = my_cq->cq_number;
+       struct ib_device *device = cq->device;
+       struct ehca_shca *shca = container_of(device, struct ehca_shca,
+                                             ib_device);
+       struct ipz_adapter_handle adapter_handle = shca->ipz_hca_handle;
+       unsigned long flags;
+
+       if (cq->uobject) {
+               if (my_cq->mm_count_galpa || my_cq->mm_count_queue) {
+                       ehca_err(device, "Resources still referenced in "
+                                "user space cq_num=%x", my_cq->cq_number);
+                       return -EINVAL;
+               }
+       }
+
+       /*
+        * remove the CQ from the idr first to make sure
+        * no more interrupt tasklets will touch this CQ
+        */
+       write_lock_irqsave(&ehca_cq_idr_lock, flags);
+       idr_remove(&ehca_cq_idr, my_cq->token);
+       write_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+
+       /* now wait until all pending events have completed */
+       wait_event(my_cq->wait_completion, !atomic_read(&my_cq->nr_events));
+
+       /* nobody's using our CQ any longer -- we can destroy it */
+       h_ret = hipz_h_destroy_cq(adapter_handle, my_cq, 0);
+       if (h_ret == H_R_STATE) {
+               /* cq in err: read err data and destroy it forcibly */
+               ehca_dbg(device, "ehca_cq=%p cq_num=%x resource=%llx in err "
+                        "state. Try to delete it forcibly.",
+                        my_cq, cq_num, my_cq->ipz_cq_handle.handle);
+               ehca_error_data(shca, my_cq, my_cq->ipz_cq_handle.handle);
+               h_ret = hipz_h_destroy_cq(adapter_handle, my_cq, 1);
+               if (h_ret == H_SUCCESS)
+                       ehca_dbg(device, "cq_num=%x deleted successfully.",
+                                cq_num);
+       }
+       if (h_ret != H_SUCCESS) {
+               ehca_err(device, "hipz_h_destroy_cq() failed h_ret=%lli "
+                        "ehca_cq=%p cq_num=%x", h_ret, my_cq, cq_num);
+               return ehca2ib_return_code(h_ret);
+       }
+       ipz_queue_dtor(NULL, &my_cq->ipz_queue);
+       kmem_cache_free(cq_cache, my_cq);
+
+       atomic_dec(&shca->num_cqs);
+       return 0;
+}
+
+int ehca_resize_cq(struct ib_cq *cq, int cqe, struct ib_udata *udata)
+{
+       /* TODO: proper resize needs to be done */
+       ehca_err(cq->device, "not implemented yet");
+
+       return -EFAULT;
+}
+
+int ehca_init_cq_cache(void)
+{
+       cq_cache = kmem_cache_create("ehca_cache_cq",
+                                    sizeof(struct ehca_cq), 0,
+                                    SLAB_HWCACHE_ALIGN,
+                                    NULL);
+       if (!cq_cache)
+               return -ENOMEM;
+       return 0;
+}
+
+void ehca_cleanup_cq_cache(void)
+{
+       if (cq_cache)
+               kmem_cache_destroy(cq_cache);
+}
diff --git a/drivers/staging/rdma/ehca/ehca_eq.c b/drivers/staging/rdma/ehca/ehca_eq.c
new file mode 100644 (file)
index 0000000..90da674
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ *  IBM eServer eHCA Infiniband device driver for Linux on POWER
+ *
+ *  Event queue handling
+ *
+ *  Authors: Waleri Fomin <fomin@de.ibm.com>
+ *           Khadija Souissi <souissi@de.ibm.com>
+ *           Reinhard Ernst <rernst@de.ibm.com>
+ *           Heiko J Schick <schickhj@de.ibm.com>
+ *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
+ *
+ *
+ *  Copyright (c) 2005 IBM Corporation
+ *
+ *  All rights reserved.
+ *
+ *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
+ *  BSD.
+ *
+ * OpenIB BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "ehca_classes.h"
+#include "ehca_irq.h"
+#include "ehca_iverbs.h"
+#include "ehca_qes.h"
+#include "hcp_if.h"
+#include "ipz_pt_fn.h"
+
+int ehca_create_eq(struct ehca_shca *shca,
+                  struct ehca_eq *eq,
+                  const enum ehca_eq_type type, const u32 length)
+{
+       int ret;
+       u64 h_ret;
+       u32 nr_pages;
+       u32 i;
+       void *vpage;
+       struct ib_device *ib_dev = &shca->ib_device;
+
+       spin_lock_init(&eq->spinlock);
+       spin_lock_init(&eq->irq_spinlock);
+       eq->is_initialized = 0;
+
+       if (type != EHCA_EQ && type != EHCA_NEQ) {
+               ehca_err(ib_dev, "Invalid EQ type %x. eq=%p", type, eq);
+               return -EINVAL;
+       }
+       if (!length) {
+               ehca_err(ib_dev, "EQ length must not be zero. eq=%p", eq);
+               return -EINVAL;
+       }
+
+       h_ret = hipz_h_alloc_resource_eq(shca->ipz_hca_handle,
+                                        &eq->pf,
+                                        type,
+                                        length,
+                                        &eq->ipz_eq_handle,
+                                        &eq->length,
+                                        &nr_pages, &eq->ist);
+
+       if (h_ret != H_SUCCESS) {
+               ehca_err(ib_dev, "Can't allocate EQ/NEQ. eq=%p", eq);
+               return -EINVAL;
+       }
+
+       ret = ipz_queue_ctor(NULL, &eq->ipz_queue, nr_pages,
+                            EHCA_PAGESIZE, sizeof(struct ehca_eqe), 0, 0);
+       if (!ret) {
+               ehca_err(ib_dev, "Can't allocate EQ pages eq=%p", eq);
+               goto create_eq_exit1;
+       }
+
+       for (i = 0; i < nr_pages; i++) {
+               u64 rpage;
+
+               vpage = ipz_qpageit_get_inc(&eq->ipz_queue);
+               if (!vpage)
+                       goto create_eq_exit2;
+
+               rpage = __pa(vpage);
+               h_ret = hipz_h_register_rpage_eq(shca->ipz_hca_handle,
+                                                eq->ipz_eq_handle,
+                                                &eq->pf,
+                                                0, 0, rpage, 1);
+
+               if (i == (nr_pages - 1)) {
+                       /* last page */
+                       vpage = ipz_qpageit_get_inc(&eq->ipz_queue);
+                       if (h_ret != H_SUCCESS || vpage)
+                               goto create_eq_exit2;
+               } else {
+                       if (h_ret != H_PAGE_REGISTERED)
+                               goto create_eq_exit2;
+               }
+       }
+
+       ipz_qeit_reset(&eq->ipz_queue);
+
+       /* register interrupt handlers and initialize work queues */
+       if (type == EHCA_EQ) {
+               tasklet_init(&eq->interrupt_task, ehca_tasklet_eq, (long)shca);
+
+               ret = ibmebus_request_irq(eq->ist, ehca_interrupt_eq,
+                                         0, "ehca_eq",
+                                         (void *)shca);
+               if (ret < 0)
+                       ehca_err(ib_dev, "Can't map interrupt handler.");
+       } else if (type == EHCA_NEQ) {
+               tasklet_init(&eq->interrupt_task, ehca_tasklet_neq, (long)shca);
+
+               ret = ibmebus_request_irq(eq->ist, ehca_interrupt_neq,
+                                         0, "ehca_neq",
+                                         (void *)shca);
+               if (ret < 0)
+                       ehca_err(ib_dev, "Can't map interrupt handler.");
+       }
+
+       eq->is_initialized = 1;
+
+       return 0;
+
+create_eq_exit2:
+       ipz_queue_dtor(NULL, &eq->ipz_queue);
+
+create_eq_exit1:
+       hipz_h_destroy_eq(shca->ipz_hca_handle, eq);
+
+       return -EINVAL;
+}
+
+void *ehca_poll_eq(struct ehca_shca *shca, struct ehca_eq *eq)
+{
+       unsigned long flags;
+       void *eqe;
+
+       spin_lock_irqsave(&eq->spinlock, flags);
+       eqe = ipz_eqit_eq_get_inc_valid(&eq->ipz_queue);
+       spin_unlock_irqrestore(&eq->spinlock, flags);
+
+       return eqe;
+}
+
+int ehca_destroy_eq(struct ehca_shca *shca, struct ehca_eq *eq)
+{
+       unsigned long flags;
+       u64 h_ret;
+
+       ibmebus_free_irq(eq->ist, (void *)shca);
+
+       spin_lock_irqsave(&shca_list_lock, flags);
+       eq->is_initialized = 0;
+       spin_unlock_irqrestore(&shca_list_lock, flags);
+
+       tasklet_kill(&eq->interrupt_task);
+
+       h_ret = hipz_h_destroy_eq(shca->ipz_hca_handle, eq);
+
+       if (h_ret != H_SUCCESS) {
+               ehca_err(&shca->ib_device, "Can't free EQ resources.");
+               return -EINVAL;
+       }
+       ipz_queue_dtor(NULL, &eq->ipz_queue);
+
+       return 0;
+}
diff --git a/drivers/staging/rdma/ehca/ehca_hca.c b/drivers/staging/rdma/ehca/ehca_hca.c
new file mode 100644 (file)
index 0000000..e8b1bb6
--- /dev/null
@@ -0,0 +1,414 @@
+/*
+ *  IBM eServer eHCA Infiniband device driver for Linux on POWER
+ *
+ *  HCA query functions
+ *
+ *  Authors: Heiko J Schick <schickhj@de.ibm.com>
+ *           Christoph Raisch <raisch@de.ibm.com>
+ *
+ *  Copyright (c) 2005 IBM Corporation
+ *
+ *  All rights reserved.
+ *
+ *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
+ *  BSD.
+ *
+ * OpenIB BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/gfp.h>
+
+#include "ehca_tools.h"
+#include "ehca_iverbs.h"
+#include "hcp_if.h"
+
+static unsigned int limit_uint(unsigned int value)
+{
+       return min_t(unsigned int, value, INT_MAX);
+}
+
+int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props,
+                     struct ib_udata *uhw)
+{
+       int i, ret = 0;
+       struct ehca_shca *shca = container_of(ibdev, struct ehca_shca,
+                                             ib_device);
+       struct hipz_query_hca *rblock;
+
+       static const u32 cap_mapping[] = {
+               IB_DEVICE_RESIZE_MAX_WR,      HCA_CAP_WQE_RESIZE,
+               IB_DEVICE_BAD_PKEY_CNTR,      HCA_CAP_BAD_P_KEY_CTR,
+               IB_DEVICE_BAD_QKEY_CNTR,      HCA_CAP_Q_KEY_VIOL_CTR,
+               IB_DEVICE_RAW_MULTI,          HCA_CAP_RAW_PACKET_MCAST,
+               IB_DEVICE_AUTO_PATH_MIG,      HCA_CAP_AUTO_PATH_MIG,
+               IB_DEVICE_CHANGE_PHY_PORT,    HCA_CAP_SQD_RTS_PORT_CHANGE,
+               IB_DEVICE_UD_AV_PORT_ENFORCE, HCA_CAP_AH_PORT_NR_CHECK,
+               IB_DEVICE_CURR_QP_STATE_MOD,  HCA_CAP_CUR_QP_STATE_MOD,
+               IB_DEVICE_SHUTDOWN_PORT,      HCA_CAP_SHUTDOWN_PORT,
+               IB_DEVICE_INIT_TYPE,          HCA_CAP_INIT_TYPE,
+               IB_DEVICE_PORT_ACTIVE_EVENT,  HCA_CAP_PORT_ACTIVE_EVENT,
+       };
+
+       if (uhw->inlen || uhw->outlen)
+               return -EINVAL;
+
+       rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
+       if (!rblock) {
+               ehca_err(&shca->ib_device, "Can't allocate rblock memory.");
+               return -ENOMEM;
+       }
+
+       if (hipz_h_query_hca(shca->ipz_hca_handle, rblock) != H_SUCCESS) {
+               ehca_err(&shca->ib_device, "Can't query device properties");
+               ret = -EINVAL;
+               goto query_device1;
+       }
+
+       memset(props, 0, sizeof(struct ib_device_attr));
+       props->page_size_cap   = shca->hca_cap_mr_pgsize;
+       props->fw_ver          = rblock->hw_ver;
+       props->max_mr_size     = rblock->max_mr_size;
+       props->vendor_id       = rblock->vendor_id >> 8;
+       props->vendor_part_id  = rblock->vendor_part_id >> 16;
+       props->hw_ver          = rblock->hw_ver;
+       props->max_qp          = limit_uint(rblock->max_qp);
+       props->max_qp_wr       = limit_uint(rblock->max_wqes_wq);
+       props->max_sge         = limit_uint(rblock->max_sge);
+       props->max_sge_rd      = limit_uint(rblock->max_sge_rd);
+       props->max_cq          = limit_uint(rblock->max_cq);
+       props->max_cqe         = limit_uint(rblock->max_cqe);
+       props->max_mr          = limit_uint(rblock->max_mr);
+       props->max_mw          = limit_uint(rblock->max_mw);
+       props->max_pd          = limit_uint(rblock->max_pd);
+       props->max_ah          = limit_uint(rblock->max_ah);
+       props->max_ee          = limit_uint(rblock->max_rd_ee_context);
+       props->max_rdd         = limit_uint(rblock->max_rd_domain);
+       props->max_fmr         = limit_uint(rblock->max_mr);
+       props->max_qp_rd_atom  = limit_uint(rblock->max_rr_qp);
+       props->max_ee_rd_atom  = limit_uint(rblock->max_rr_ee_context);
+       props->max_res_rd_atom = limit_uint(rblock->max_rr_hca);
+       props->max_qp_init_rd_atom = limit_uint(rblock->max_act_wqs_qp);
+       props->max_ee_init_rd_atom = limit_uint(rblock->max_act_wqs_ee_context);
+
+       if (EHCA_BMASK_GET(HCA_CAP_SRQ, shca->hca_cap)) {
+               props->max_srq         = limit_uint(props->max_qp);
+               props->max_srq_wr      = limit_uint(props->max_qp_wr);
+               props->max_srq_sge     = 3;
+       }
+
+       props->max_pkeys           = 16;
+       /* Some FW versions say 0 here; insert sensible value in that case */
+       props->local_ca_ack_delay  = rblock->local_ca_ack_delay ?
+               min_t(u8, rblock->local_ca_ack_delay, 255) : 12;
+       props->max_raw_ipv6_qp     = limit_uint(rblock->max_raw_ipv6_qp);
+       props->max_raw_ethy_qp     = limit_uint(rblock->max_raw_ethy_qp);
+       props->max_mcast_grp       = limit_uint(rblock->max_mcast_grp);
+       props->max_mcast_qp_attach = limit_uint(rblock->max_mcast_qp_attach);
+       props->max_total_mcast_qp_attach
+               = limit_uint(rblock->max_total_mcast_qp_attach);
+
+       /* translate device capabilities */
+       props->device_cap_flags = IB_DEVICE_SYS_IMAGE_GUID |
+               IB_DEVICE_RC_RNR_NAK_GEN | IB_DEVICE_N_NOTIFY_CQ;
+       for (i = 0; i < ARRAY_SIZE(cap_mapping); i += 2)
+               if (rblock->hca_cap_indicators & cap_mapping[i + 1])
+                       props->device_cap_flags |= cap_mapping[i];
+
+query_device1:
+       ehca_free_fw_ctrlblock(rblock);
+
+       return ret;
+}
+
+static enum ib_mtu map_mtu(struct ehca_shca *shca, u32 fw_mtu)
+{
+       switch (fw_mtu) {
+       case 0x1:
+               return IB_MTU_256;
+       case 0x2:
+               return IB_MTU_512;
+       case 0x3:
+               return IB_MTU_1024;
+       case 0x4:
+               return IB_MTU_2048;
+       case 0x5:
+               return IB_MTU_4096;
+       default:
+               ehca_err(&shca->ib_device, "Unknown MTU size: %x.",
+                        fw_mtu);
+               return 0;
+       }
+}
+
+static u8 map_number_of_vls(struct ehca_shca *shca, u32 vl_cap)
+{
+       switch (vl_cap) {
+       case 0x1:
+               return 1;
+       case 0x2:
+               return 2;
+       case 0x3:
+               return 4;
+       case 0x4:
+               return 8;
+       case 0x5:
+               return 15;
+       default:
+               ehca_err(&shca->ib_device, "invalid Vl Capability: %x.",
+                        vl_cap);
+               return 0;
+       }
+}
+
+int ehca_query_port(struct ib_device *ibdev,
+                   u8 port, struct ib_port_attr *props)
+{
+       int ret = 0;
+       u64 h_ret;
+       struct ehca_shca *shca = container_of(ibdev, struct ehca_shca,
+                                             ib_device);
+       struct hipz_query_port *rblock;
+
+       rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
+       if (!rblock) {
+               ehca_err(&shca->ib_device, "Can't allocate rblock memory.");
+               return -ENOMEM;
+       }
+
+       h_ret = hipz_h_query_port(shca->ipz_hca_handle, port, rblock);
+       if (h_ret != H_SUCCESS) {
+               ehca_err(&shca->ib_device, "Can't query port properties");
+               ret = -EINVAL;
+               goto query_port1;
+       }
+
+       memset(props, 0, sizeof(struct ib_port_attr));
+
+       props->active_mtu = props->max_mtu = map_mtu(shca, rblock->max_mtu);
+       props->port_cap_flags  = rblock->capability_mask;
+       props->gid_tbl_len     = rblock->gid_tbl_len;
+       if (rblock->max_msg_sz)
+               props->max_msg_sz      = rblock->max_msg_sz;
+       else
+               props->max_msg_sz      = 0x1 << 31;
+       props->bad_pkey_cntr   = rblock->bad_pkey_cntr;
+       props->qkey_viol_cntr  = rblock->qkey_viol_cntr;
+       props->pkey_tbl_len    = rblock->pkey_tbl_len;
+       props->lid             = rblock->lid;
+       props->sm_lid          = rblock->sm_lid;
+       props->lmc             = rblock->lmc;
+       props->sm_sl           = rblock->sm_sl;
+       props->subnet_timeout  = rblock->subnet_timeout;
+       props->init_type_reply = rblock->init_type_reply;
+       props->max_vl_num      = map_number_of_vls(shca, rblock->vl_cap);
+
+       if (rblock->state && rblock->phys_width) {
+               props->phys_state      = rblock->phys_pstate;
+               props->state           = rblock->phys_state;
+               props->active_width    = rblock->phys_width;
+               props->active_speed    = rblock->phys_speed;
+       } else {
+               /* old firmware releases don't report physical
+                * port info, so use default values
+                */
+               props->phys_state      = 5;
+               props->state           = rblock->state;
+               props->active_width    = IB_WIDTH_12X;
+               props->active_speed    = IB_SPEED_SDR;
+       }
+
+query_port1:
+       ehca_free_fw_ctrlblock(rblock);
+
+       return ret;
+}
+
+int ehca_query_sma_attr(struct ehca_shca *shca,
+                       u8 port, struct ehca_sma_attr *attr)
+{
+       int ret = 0;
+       u64 h_ret;
+       struct hipz_query_port *rblock;
+
+       rblock = ehca_alloc_fw_ctrlblock(GFP_ATOMIC);
+       if (!rblock) {
+               ehca_err(&shca->ib_device, "Can't allocate rblock memory.");
+               return -ENOMEM;
+       }
+
+       h_ret = hipz_h_query_port(shca->ipz_hca_handle, port, rblock);
+       if (h_ret != H_SUCCESS) {
+               ehca_err(&shca->ib_device, "Can't query port properties");
+               ret = -EINVAL;
+               goto query_sma_attr1;
+       }
+
+       memset(attr, 0, sizeof(struct ehca_sma_attr));
+
+       attr->lid    = rblock->lid;
+       attr->lmc    = rblock->lmc;
+       attr->sm_sl  = rblock->sm_sl;
+       attr->sm_lid = rblock->sm_lid;
+
+       attr->pkey_tbl_len = rblock->pkey_tbl_len;
+       memcpy(attr->pkeys, rblock->pkey_entries, sizeof(attr->pkeys));
+
+query_sma_attr1:
+       ehca_free_fw_ctrlblock(rblock);
+
+       return ret;
+}
+
+int ehca_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 *pkey)
+{
+       int ret = 0;
+       u64 h_ret;
+       struct ehca_shca *shca;
+       struct hipz_query_port *rblock;
+
+       shca = container_of(ibdev, struct ehca_shca, ib_device);
+       if (index > 16) {
+               ehca_err(&shca->ib_device, "Invalid index: %x.", index);
+               return -EINVAL;
+       }
+
+       rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
+       if (!rblock) {
+               ehca_err(&shca->ib_device,  "Can't allocate rblock memory.");
+               return -ENOMEM;
+       }
+
+       h_ret = hipz_h_query_port(shca->ipz_hca_handle, port, rblock);
+       if (h_ret != H_SUCCESS) {
+               ehca_err(&shca->ib_device, "Can't query port properties");
+               ret = -EINVAL;
+               goto query_pkey1;
+       }
+
+       memcpy(pkey, &rblock->pkey_entries + index, sizeof(u16));
+
+query_pkey1:
+       ehca_free_fw_ctrlblock(rblock);
+
+       return ret;
+}
+
+int ehca_query_gid(struct ib_device *ibdev, u8 port,
+                  int index, union ib_gid *gid)
+{
+       int ret = 0;
+       u64 h_ret;
+       struct ehca_shca *shca = container_of(ibdev, struct ehca_shca,
+                                             ib_device);
+       struct hipz_query_port *rblock;
+
+       if (index < 0 || index > 255) {
+               ehca_err(&shca->ib_device, "Invalid index: %x.", index);
+               return -EINVAL;
+       }
+
+       rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
+       if (!rblock) {
+               ehca_err(&shca->ib_device, "Can't allocate rblock memory.");
+               return -ENOMEM;
+       }
+
+       h_ret = hipz_h_query_port(shca->ipz_hca_handle, port, rblock);
+       if (h_ret != H_SUCCESS) {
+               ehca_err(&shca->ib_device, "Can't query port properties");
+               ret = -EINVAL;
+               goto query_gid1;
+       }
+
+       memcpy(&gid->raw[0], &rblock->gid_prefix, sizeof(u64));
+       memcpy(&gid->raw[8], &rblock->guid_entries[index], sizeof(u64));
+
+query_gid1:
+       ehca_free_fw_ctrlblock(rblock);
+
+       return ret;
+}
+
+static const u32 allowed_port_caps = (
+       IB_PORT_SM | IB_PORT_LED_INFO_SUP | IB_PORT_CM_SUP |
+       IB_PORT_SNMP_TUNNEL_SUP | IB_PORT_DEVICE_MGMT_SUP |
+       IB_PORT_VENDOR_CLASS_SUP);
+
+int ehca_modify_port(struct ib_device *ibdev,
+                    u8 port, int port_modify_mask,
+                    struct ib_port_modify *props)
+{
+       int ret = 0;
+       struct ehca_shca *shca;
+       struct hipz_query_port *rblock;
+       u32 cap;
+       u64 hret;
+
+       shca = container_of(ibdev, struct ehca_shca, ib_device);
+       if ((props->set_port_cap_mask | props->clr_port_cap_mask)
+           & ~allowed_port_caps) {
+               ehca_err(&shca->ib_device, "Non-changeable bits set in masks  "
+                        "set=%x  clr=%x  allowed=%x", props->set_port_cap_mask,
+                        props->clr_port_cap_mask, allowed_port_caps);
+               return -EINVAL;
+       }
+
+       if (mutex_lock_interruptible(&shca->modify_mutex))
+               return -ERESTARTSYS;
+
+       rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
+       if (!rblock) {
+               ehca_err(&shca->ib_device,  "Can't allocate rblock memory.");
+               ret = -ENOMEM;
+               goto modify_port1;
+       }
+
+       hret = hipz_h_query_port(shca->ipz_hca_handle, port, rblock);
+       if (hret != H_SUCCESS) {
+               ehca_err(&shca->ib_device, "Can't query port properties");
+               ret = -EINVAL;
+               goto modify_port2;
+       }
+
+       cap = (rblock->capability_mask | props->set_port_cap_mask)
+               & ~props->clr_port_cap_mask;
+
+       hret = hipz_h_modify_port(shca->ipz_hca_handle, port,
+                                 cap, props->init_type, port_modify_mask);
+       if (hret != H_SUCCESS) {
+               ehca_err(&shca->ib_device, "Modify port failed  h_ret=%lli",
+                        hret);
+               ret = -EINVAL;
+       }
+
+modify_port2:
+       ehca_free_fw_ctrlblock(rblock);
+
+modify_port1:
+       mutex_unlock(&shca->modify_mutex);
+
+       return ret;
+}
diff --git a/drivers/staging/rdma/ehca/ehca_irq.c b/drivers/staging/rdma/ehca/ehca_irq.c
new file mode 100644 (file)
index 0000000..8615d7c
--- /dev/null
@@ -0,0 +1,870 @@
+/*
+ *  IBM eServer eHCA Infiniband device driver for Linux on POWER
+ *
+ *  Functions for EQs, NEQs and interrupts
+ *
+ *  Authors: Heiko J Schick <schickhj@de.ibm.com>
+ *           Khadija Souissi <souissi@de.ibm.com>
+ *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
+ *           Joachim Fenkes <fenkes@de.ibm.com>
+ *
+ *  Copyright (c) 2005 IBM Corporation
+ *
+ *  All rights reserved.
+ *
+ *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
+ *  BSD.
+ *
+ * OpenIB BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/slab.h>
+#include <linux/smpboot.h>
+
+#include "ehca_classes.h"
+#include "ehca_irq.h"
+#include "ehca_iverbs.h"
+#include "ehca_tools.h"
+#include "hcp_if.h"
+#include "hipz_fns.h"
+#include "ipz_pt_fn.h"
+
+#define EQE_COMPLETION_EVENT   EHCA_BMASK_IBM( 1,  1)
+#define EQE_CQ_QP_NUMBER       EHCA_BMASK_IBM( 8, 31)
+#define EQE_EE_IDENTIFIER      EHCA_BMASK_IBM( 2,  7)
+#define EQE_CQ_NUMBER          EHCA_BMASK_IBM( 8, 31)
+#define EQE_QP_NUMBER          EHCA_BMASK_IBM( 8, 31)
+#define EQE_QP_TOKEN           EHCA_BMASK_IBM(32, 63)
+#define EQE_CQ_TOKEN           EHCA_BMASK_IBM(32, 63)
+
+#define NEQE_COMPLETION_EVENT  EHCA_BMASK_IBM( 1,  1)
+#define NEQE_EVENT_CODE        EHCA_BMASK_IBM( 2,  7)
+#define NEQE_PORT_NUMBER       EHCA_BMASK_IBM( 8, 15)
+#define NEQE_PORT_AVAILABILITY EHCA_BMASK_IBM(16, 16)
+#define NEQE_DISRUPTIVE        EHCA_BMASK_IBM(16, 16)
+#define NEQE_SPECIFIC_EVENT    EHCA_BMASK_IBM(16, 23)
+
+#define ERROR_DATA_LENGTH      EHCA_BMASK_IBM(52, 63)
+#define ERROR_DATA_TYPE        EHCA_BMASK_IBM( 0,  7)
+
+static void queue_comp_task(struct ehca_cq *__cq);
+
+static struct ehca_comp_pool *pool;
+
+static inline void comp_event_callback(struct ehca_cq *cq)
+{
+       if (!cq->ib_cq.comp_handler)
+               return;
+
+       spin_lock(&cq->cb_lock);
+       cq->ib_cq.comp_handler(&cq->ib_cq, cq->ib_cq.cq_context);
+       spin_unlock(&cq->cb_lock);
+
+       return;
+}
+
+static void print_error_data(struct ehca_shca *shca, void *data,
+                            u64 *rblock, int length)
+{
+       u64 type = EHCA_BMASK_GET(ERROR_DATA_TYPE, rblock[2]);
+       u64 resource = rblock[1];
+
+       switch (type) {
+       case 0x1: /* Queue Pair */
+       {
+               struct ehca_qp *qp = (struct ehca_qp *)data;
+
+               /* only print error data if AER is set */
+               if (rblock[6] == 0)
+                       return;
+
+               ehca_err(&shca->ib_device,
+                        "QP 0x%x (resource=%llx) has errors.",
+                        qp->ib_qp.qp_num, resource);
+               break;
+       }
+       case 0x4: /* Completion Queue */
+       {
+               struct ehca_cq *cq = (struct ehca_cq *)data;
+
+               ehca_err(&shca->ib_device,
+                        "CQ 0x%x (resource=%llx) has errors.",
+                        cq->cq_number, resource);
+               break;
+       }
+       default:
+               ehca_err(&shca->ib_device,
+                        "Unknown error type: %llx on %s.",
+                        type, shca->ib_device.name);
+               break;
+       }
+
+       ehca_err(&shca->ib_device, "Error data is available: %llx.", resource);
+       ehca_err(&shca->ib_device, "EHCA ----- error data begin "
+                "---------------------------------------------------");
+       ehca_dmp(rblock, length, "resource=%llx", resource);
+       ehca_err(&shca->ib_device, "EHCA ----- error data end "
+                "----------------------------------------------------");
+
+       return;
+}
+
+int ehca_error_data(struct ehca_shca *shca, void *data,
+                   u64 resource)
+{
+
+       unsigned long ret;
+       u64 *rblock;
+       unsigned long block_count;
+
+       rblock = ehca_alloc_fw_ctrlblock(GFP_ATOMIC);
+       if (!rblock) {
+               ehca_err(&shca->ib_device, "Cannot allocate rblock memory.");
+               ret = -ENOMEM;
+               goto error_data1;
+       }
+
+       /* rblock must be 4K aligned and should be 4K large */
+       ret = hipz_h_error_data(shca->ipz_hca_handle,
+                               resource,
+                               rblock,
+                               &block_count);
+
+       if (ret == H_R_STATE)
+               ehca_err(&shca->ib_device,
+                        "No error data is available: %llx.", resource);
+       else if (ret == H_SUCCESS) {
+               int length;
+
+               length = EHCA_BMASK_GET(ERROR_DATA_LENGTH, rblock[0]);
+
+               if (length > EHCA_PAGESIZE)
+                       length = EHCA_PAGESIZE;
+
+               print_error_data(shca, data, rblock, length);
+       } else
+               ehca_err(&shca->ib_device,
+                        "Error data could not be fetched: %llx", resource);
+
+       ehca_free_fw_ctrlblock(rblock);
+
+error_data1:
+       return ret;
+
+}
+
+static void dispatch_qp_event(struct ehca_shca *shca, struct ehca_qp *qp,
+                             enum ib_event_type event_type)
+{
+       struct ib_event event;
+
+       /* PATH_MIG without the QP ever having been armed is false alarm */
+       if (event_type == IB_EVENT_PATH_MIG && !qp->mig_armed)
+               return;
+
+       event.device = &shca->ib_device;
+       event.event = event_type;
+
+       if (qp->ext_type == EQPT_SRQ) {
+               if (!qp->ib_srq.event_handler)
+                       return;
+
+               event.element.srq = &qp->ib_srq;
+               qp->ib_srq.event_handler(&event, qp->ib_srq.srq_context);
+       } else {
+               if (!qp->ib_qp.event_handler)
+                       return;
+
+               event.element.qp = &qp->ib_qp;
+               qp->ib_qp.event_handler(&event, qp->ib_qp.qp_context);
+       }
+}
+
+static void qp_event_callback(struct ehca_shca *shca, u64 eqe,
+                             enum ib_event_type event_type, int fatal)
+{
+       struct ehca_qp *qp;
+       u32 token = EHCA_BMASK_GET(EQE_QP_TOKEN, eqe);
+
+       read_lock(&ehca_qp_idr_lock);
+       qp = idr_find(&ehca_qp_idr, token);
+       if (qp)
+               atomic_inc(&qp->nr_events);
+       read_unlock(&ehca_qp_idr_lock);
+
+       if (!qp)
+               return;
+
+       if (fatal)
+               ehca_error_data(shca, qp, qp->ipz_qp_handle.handle);
+
+       dispatch_qp_event(shca, qp, fatal && qp->ext_type == EQPT_SRQ ?
+                         IB_EVENT_SRQ_ERR : event_type);
+
+       /*
+        * eHCA only processes one WQE at a time for SRQ base QPs,
+        * so the last WQE has been processed as soon as the QP enters
+        * error state.
+        */
+       if (fatal && qp->ext_type == EQPT_SRQBASE)
+               dispatch_qp_event(shca, qp, IB_EVENT_QP_LAST_WQE_REACHED);
+
+       if (atomic_dec_and_test(&qp->nr_events))
+               wake_up(&qp->wait_completion);
+       return;
+}
+
+static void cq_event_callback(struct ehca_shca *shca,
+                             u64 eqe)
+{
+       struct ehca_cq *cq;
+       u32 token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe);
+
+       read_lock(&ehca_cq_idr_lock);
+       cq = idr_find(&ehca_cq_idr, token);
+       if (cq)
+               atomic_inc(&cq->nr_events);
+       read_unlock(&ehca_cq_idr_lock);
+
+       if (!cq)
+               return;
+
+       ehca_error_data(shca, cq, cq->ipz_cq_handle.handle);
+
+       if (atomic_dec_and_test(&cq->nr_events))
+               wake_up(&cq->wait_completion);
+
+       return;
+}
+
+static void parse_identifier(struct ehca_shca *shca, u64 eqe)
+{
+       u8 identifier = EHCA_BMASK_GET(EQE_EE_IDENTIFIER, eqe);
+
+       switch (identifier) {
+       case 0x02: /* path migrated */
+               qp_event_callback(shca, eqe, IB_EVENT_PATH_MIG, 0);
+               break;
+       case 0x03: /* communication established */
+               qp_event_callback(shca, eqe, IB_EVENT_COMM_EST, 0);
+               break;
+       case 0x04: /* send queue drained */
+               qp_event_callback(shca, eqe, IB_EVENT_SQ_DRAINED, 0);
+               break;
+       case 0x05: /* QP error */
+       case 0x06: /* QP error */
+               qp_event_callback(shca, eqe, IB_EVENT_QP_FATAL, 1);
+               break;
+       case 0x07: /* CQ error */
+       case 0x08: /* CQ error */
+               cq_event_callback(shca, eqe);
+               break;
+       case 0x09: /* MRMWPTE error */
+               ehca_err(&shca->ib_device, "MRMWPTE error.");
+               break;
+       case 0x0A: /* port event */
+               ehca_err(&shca->ib_device, "Port event.");
+               break;
+       case 0x0B: /* MR access error */
+               ehca_err(&shca->ib_device, "MR access error.");
+               break;
+       case 0x0C: /* EQ error */
+               ehca_err(&shca->ib_device, "EQ error.");
+               break;
+       case 0x0D: /* P/Q_Key mismatch */
+               ehca_err(&shca->ib_device, "P/Q_Key mismatch.");
+               break;
+       case 0x10: /* sampling complete */
+               ehca_err(&shca->ib_device, "Sampling complete.");
+               break;
+       case 0x11: /* unaffiliated access error */
+               ehca_err(&shca->ib_device, "Unaffiliated access error.");
+               break;
+       case 0x12: /* path migrating */
+               ehca_err(&shca->ib_device, "Path migrating.");
+               break;
+       case 0x13: /* interface trace stopped */
+               ehca_err(&shca->ib_device, "Interface trace stopped.");
+               break;
+       case 0x14: /* first error capture info available */
+               ehca_info(&shca->ib_device, "First error capture available");
+               break;
+       case 0x15: /* SRQ limit reached */
+               qp_event_callback(shca, eqe, IB_EVENT_SRQ_LIMIT_REACHED, 0);
+               break;
+       default:
+               ehca_err(&shca->ib_device, "Unknown identifier: %x on %s.",
+                        identifier, shca->ib_device.name);
+               break;
+       }
+
+       return;
+}
+
+static void dispatch_port_event(struct ehca_shca *shca, int port_num,
+                               enum ib_event_type type, const char *msg)
+{
+       struct ib_event event;
+
+       ehca_info(&shca->ib_device, "port %d %s.", port_num, msg);
+       event.device = &shca->ib_device;
+       event.event = type;
+       event.element.port_num = port_num;
+       ib_dispatch_event(&event);
+}
+
+static void notify_port_conf_change(struct ehca_shca *shca, int port_num)
+{
+       struct ehca_sma_attr  new_attr;
+       struct ehca_sma_attr *old_attr = &shca->sport[port_num - 1].saved_attr;
+
+       ehca_query_sma_attr(shca, port_num, &new_attr);
+
+       if (new_attr.sm_sl  != old_attr->sm_sl ||
+           new_attr.sm_lid != old_attr->sm_lid)
+               dispatch_port_event(shca, port_num, IB_EVENT_SM_CHANGE,
+                                   "SM changed");
+
+       if (new_attr.lid != old_attr->lid ||
+           new_attr.lmc != old_attr->lmc)
+               dispatch_port_event(shca, port_num, IB_EVENT_LID_CHANGE,
+                                   "LID changed");
+
+       if (new_attr.pkey_tbl_len != old_attr->pkey_tbl_len ||
+           memcmp(new_attr.pkeys, old_attr->pkeys,
+                  sizeof(u16) * new_attr.pkey_tbl_len))
+               dispatch_port_event(shca, port_num, IB_EVENT_PKEY_CHANGE,
+                                   "P_Key changed");
+
+       *old_attr = new_attr;
+}
+
+/* replay modify_qp for sqps -- return 0 if all is well, 1 if AQP1 destroyed */
+static int replay_modify_qp(struct ehca_sport *sport)
+{
+       int aqp1_destroyed;
+       unsigned long flags;
+
+       spin_lock_irqsave(&sport->mod_sqp_lock, flags);
+
+       aqp1_destroyed = !sport->ibqp_sqp[IB_QPT_GSI];
+
+       if (sport->ibqp_sqp[IB_QPT_SMI])
+               ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_SMI]);
+       if (!aqp1_destroyed)
+               ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_GSI]);
+
+       spin_unlock_irqrestore(&sport->mod_sqp_lock, flags);
+
+       return aqp1_destroyed;
+}
+
+static void parse_ec(struct ehca_shca *shca, u64 eqe)
+{
+       u8 ec   = EHCA_BMASK_GET(NEQE_EVENT_CODE, eqe);
+       u8 port = EHCA_BMASK_GET(NEQE_PORT_NUMBER, eqe);
+       u8 spec_event;
+       struct ehca_sport *sport = &shca->sport[port - 1];
+
+       switch (ec) {
+       case 0x30: /* port availability change */
+               if (EHCA_BMASK_GET(NEQE_PORT_AVAILABILITY, eqe)) {
+                       /* only replay modify_qp calls in autodetect mode;
+                        * if AQP1 was destroyed, the port is already down
+                        * again and we can drop the event.
+                        */
+                       if (ehca_nr_ports < 0)
+                               if (replay_modify_qp(sport))
+                                       break;
+
+                       sport->port_state = IB_PORT_ACTIVE;
+                       dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE,
+                                           "is active");
+                       ehca_query_sma_attr(shca, port, &sport->saved_attr);
+               } else {
+                       sport->port_state = IB_PORT_DOWN;
+                       dispatch_port_event(shca, port, IB_EVENT_PORT_ERR,
+                                           "is inactive");
+               }
+               break;
+       case 0x31:
+               /* port configuration change
+                * disruptive change is caused by
+                * LID, PKEY or SM change
+                */
+               if (EHCA_BMASK_GET(NEQE_DISRUPTIVE, eqe)) {
+                       ehca_warn(&shca->ib_device, "disruptive port "
+                                 "%d configuration change", port);
+
+                       sport->port_state = IB_PORT_DOWN;
+                       dispatch_port_event(shca, port, IB_EVENT_PORT_ERR,
+                                           "is inactive");
+
+                       sport->port_state = IB_PORT_ACTIVE;
+                       dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE,
+                                           "is active");
+                       ehca_query_sma_attr(shca, port,
+                                           &sport->saved_attr);
+               } else
+                       notify_port_conf_change(shca, port);
+               break;
+       case 0x32: /* adapter malfunction */
+               ehca_err(&shca->ib_device, "Adapter malfunction.");
+               break;
+       case 0x33:  /* trace stopped */
+               ehca_err(&shca->ib_device, "Traced stopped.");
+               break;
+       case 0x34: /* util async event */
+               spec_event = EHCA_BMASK_GET(NEQE_SPECIFIC_EVENT, eqe);
+               if (spec_event == 0x80) /* client reregister required */
+                       dispatch_port_event(shca, port,
+                                           IB_EVENT_CLIENT_REREGISTER,
+                                           "client reregister req.");
+               else
+                       ehca_warn(&shca->ib_device, "Unknown util async "
+                                 "event %x on port %x", spec_event, port);
+               break;
+       default:
+               ehca_err(&shca->ib_device, "Unknown event code: %x on %s.",
+                        ec, shca->ib_device.name);
+               break;
+       }
+
+       return;
+}
+
+static inline void reset_eq_pending(struct ehca_cq *cq)
+{
+       u64 CQx_EP;
+       struct h_galpa gal = cq->galpas.kernel;
+
+       hipz_galpa_store_cq(gal, cqx_ep, 0x0);
+       CQx_EP = hipz_galpa_load(gal, CQTEMM_OFFSET(cqx_ep));
+
+       return;
+}
+
+irqreturn_t ehca_interrupt_neq(int irq, void *dev_id)
+{
+       struct ehca_shca *shca = (struct ehca_shca*)dev_id;
+
+       tasklet_hi_schedule(&shca->neq.interrupt_task);
+
+       return IRQ_HANDLED;
+}
+
+void ehca_tasklet_neq(unsigned long data)
+{
+       struct ehca_shca *shca = (struct ehca_shca*)data;
+       struct ehca_eqe *eqe;
+       u64 ret;
+
+       eqe = ehca_poll_eq(shca, &shca->neq);
+
+       while (eqe) {
+               if (!EHCA_BMASK_GET(NEQE_COMPLETION_EVENT, eqe->entry))
+                       parse_ec(shca, eqe->entry);
+
+               eqe = ehca_poll_eq(shca, &shca->neq);
+       }
+
+       ret = hipz_h_reset_event(shca->ipz_hca_handle,
+                                shca->neq.ipz_eq_handle, 0xFFFFFFFFFFFFFFFFL);
+
+       if (ret != H_SUCCESS)
+               ehca_err(&shca->ib_device, "Can't clear notification events.");
+
+       return;
+}
+
+irqreturn_t ehca_interrupt_eq(int irq, void *dev_id)
+{
+       struct ehca_shca *shca = (struct ehca_shca*)dev_id;
+
+       tasklet_hi_schedule(&shca->eq.interrupt_task);
+
+       return IRQ_HANDLED;
+}
+
+
+static inline void process_eqe(struct ehca_shca *shca, struct ehca_eqe *eqe)
+{
+       u64 eqe_value;
+       u32 token;
+       struct ehca_cq *cq;
+
+       eqe_value = eqe->entry;
+       ehca_dbg(&shca->ib_device, "eqe_value=%llx", eqe_value);
+       if (EHCA_BMASK_GET(EQE_COMPLETION_EVENT, eqe_value)) {
+               ehca_dbg(&shca->ib_device, "Got completion event");
+               token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe_value);
+               read_lock(&ehca_cq_idr_lock);
+               cq = idr_find(&ehca_cq_idr, token);
+               if (cq)
+                       atomic_inc(&cq->nr_events);
+               read_unlock(&ehca_cq_idr_lock);
+               if (cq == NULL) {
+                       ehca_err(&shca->ib_device,
+                                "Invalid eqe for non-existing cq token=%x",
+                                token);
+                       return;
+               }
+               reset_eq_pending(cq);
+               if (ehca_scaling_code)
+                       queue_comp_task(cq);
+               else {
+                       comp_event_callback(cq);
+                       if (atomic_dec_and_test(&cq->nr_events))
+                               wake_up(&cq->wait_completion);
+               }
+       } else {
+               ehca_dbg(&shca->ib_device, "Got non completion event");
+               parse_identifier(shca, eqe_value);
+       }
+}
+
+void ehca_process_eq(struct ehca_shca *shca, int is_irq)
+{
+       struct ehca_eq *eq = &shca->eq;
+       struct ehca_eqe_cache_entry *eqe_cache = eq->eqe_cache;
+       u64 eqe_value, ret;
+       int eqe_cnt, i;
+       int eq_empty = 0;
+
+       spin_lock(&eq->irq_spinlock);
+       if (is_irq) {
+               const int max_query_cnt = 100;
+               int query_cnt = 0;
+               int int_state = 1;
+               do {
+                       int_state = hipz_h_query_int_state(
+                               shca->ipz_hca_handle, eq->ist);
+                       query_cnt++;
+                       iosync();
+               } while (int_state && query_cnt < max_query_cnt);
+               if (unlikely((query_cnt == max_query_cnt)))
+                       ehca_dbg(&shca->ib_device, "int_state=%x query_cnt=%x",
+                                int_state, query_cnt);
+       }
+
+       /* read out all eqes */
+       eqe_cnt = 0;
+       do {
+               u32 token;
+               eqe_cache[eqe_cnt].eqe = ehca_poll_eq(shca, eq);
+               if (!eqe_cache[eqe_cnt].eqe)
+                       break;
+               eqe_value = eqe_cache[eqe_cnt].eqe->entry;
+               if (EHCA_BMASK_GET(EQE_COMPLETION_EVENT, eqe_value)) {
+                       token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe_value);
+                       read_lock(&ehca_cq_idr_lock);
+                       eqe_cache[eqe_cnt].cq = idr_find(&ehca_cq_idr, token);
+                       if (eqe_cache[eqe_cnt].cq)
+                               atomic_inc(&eqe_cache[eqe_cnt].cq->nr_events);
+                       read_unlock(&ehca_cq_idr_lock);
+                       if (!eqe_cache[eqe_cnt].cq) {
+                               ehca_err(&shca->ib_device,
+                                        "Invalid eqe for non-existing cq "
+                                        "token=%x", token);
+                               continue;
+                       }
+               } else
+                       eqe_cache[eqe_cnt].cq = NULL;
+               eqe_cnt++;
+       } while (eqe_cnt < EHCA_EQE_CACHE_SIZE);
+       if (!eqe_cnt) {
+               if (is_irq)
+                       ehca_dbg(&shca->ib_device,
+                                "No eqe found for irq event");
+               goto unlock_irq_spinlock;
+       } else if (!is_irq) {
+               ret = hipz_h_eoi(eq->ist);
+               if (ret != H_SUCCESS)
+                       ehca_err(&shca->ib_device,
+                                "bad return code EOI -rc = %lld\n", ret);
+               ehca_dbg(&shca->ib_device, "deadman found %x eqe", eqe_cnt);
+       }
+       if (unlikely(eqe_cnt == EHCA_EQE_CACHE_SIZE))
+               ehca_dbg(&shca->ib_device, "too many eqes for one irq event");
+       /* enable irq for new packets */
+       for (i = 0; i < eqe_cnt; i++) {
+               if (eq->eqe_cache[i].cq)
+                       reset_eq_pending(eq->eqe_cache[i].cq);
+       }
+       /* check eq */
+       spin_lock(&eq->spinlock);
+       eq_empty = (!ipz_eqit_eq_peek_valid(&shca->eq.ipz_queue));
+       spin_unlock(&eq->spinlock);
+       /* call completion handler for cached eqes */
+       for (i = 0; i < eqe_cnt; i++)
+               if (eq->eqe_cache[i].cq) {
+                       if (ehca_scaling_code)
+                               queue_comp_task(eq->eqe_cache[i].cq);
+                       else {
+                               struct ehca_cq *cq = eq->eqe_cache[i].cq;
+                               comp_event_callback(cq);
+                               if (atomic_dec_and_test(&cq->nr_events))
+                                       wake_up(&cq->wait_completion);
+                       }
+               } else {
+                       ehca_dbg(&shca->ib_device, "Got non completion event");
+                       parse_identifier(shca, eq->eqe_cache[i].eqe->entry);
+               }
+       /* poll eq if not empty */
+       if (eq_empty)
+               goto unlock_irq_spinlock;
+       do {
+               struct ehca_eqe *eqe;
+               eqe = ehca_poll_eq(shca, &shca->eq);
+               if (!eqe)
+                       break;
+               process_eqe(shca, eqe);
+       } while (1);
+
+unlock_irq_spinlock:
+       spin_unlock(&eq->irq_spinlock);
+}
+
+void ehca_tasklet_eq(unsigned long data)
+{
+       ehca_process_eq((struct ehca_shca*)data, 1);
+}
+
+static int find_next_online_cpu(struct ehca_comp_pool *pool)
+{
+       int cpu;
+       unsigned long flags;
+
+       WARN_ON_ONCE(!in_interrupt());
+       if (ehca_debug_level >= 3)
+               ehca_dmp(cpu_online_mask, cpumask_size(), "");
+
+       spin_lock_irqsave(&pool->last_cpu_lock, flags);
+       do {
+               cpu = cpumask_next(pool->last_cpu, cpu_online_mask);
+               if (cpu >= nr_cpu_ids)
+                       cpu = cpumask_first(cpu_online_mask);
+               pool->last_cpu = cpu;
+       } while (!per_cpu_ptr(pool->cpu_comp_tasks, cpu)->active);
+       spin_unlock_irqrestore(&pool->last_cpu_lock, flags);
+
+       return cpu;
+}
+
+static void __queue_comp_task(struct ehca_cq *__cq,
+                             struct ehca_cpu_comp_task *cct,
+                             struct task_struct *thread)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&cct->task_lock, flags);
+       spin_lock(&__cq->task_lock);
+
+       if (__cq->nr_callbacks == 0) {
+               __cq->nr_callbacks++;
+               list_add_tail(&__cq->entry, &cct->cq_list);
+               cct->cq_jobs++;
+               wake_up_process(thread);
+       } else
+               __cq->nr_callbacks++;
+
+       spin_unlock(&__cq->task_lock);
+       spin_unlock_irqrestore(&cct->task_lock, flags);
+}
+
+static void queue_comp_task(struct ehca_cq *__cq)
+{
+       int cpu_id;
+       struct ehca_cpu_comp_task *cct;
+       struct task_struct *thread;
+       int cq_jobs;
+       unsigned long flags;
+
+       cpu_id = find_next_online_cpu(pool);
+       BUG_ON(!cpu_online(cpu_id));
+
+       cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu_id);
+       thread = *per_cpu_ptr(pool->cpu_comp_threads, cpu_id);
+       BUG_ON(!cct || !thread);
+
+       spin_lock_irqsave(&cct->task_lock, flags);
+       cq_jobs = cct->cq_jobs;
+       spin_unlock_irqrestore(&cct->task_lock, flags);
+       if (cq_jobs > 0) {
+               cpu_id = find_next_online_cpu(pool);
+               cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu_id);
+               thread = *per_cpu_ptr(pool->cpu_comp_threads, cpu_id);
+               BUG_ON(!cct || !thread);
+       }
+       __queue_comp_task(__cq, cct, thread);
+}
+
+static void run_comp_task(struct ehca_cpu_comp_task *cct)
+{
+       struct ehca_cq *cq;
+
+       while (!list_empty(&cct->cq_list)) {
+               cq = list_entry(cct->cq_list.next, struct ehca_cq, entry);
+               spin_unlock_irq(&cct->task_lock);
+
+               comp_event_callback(cq);
+               if (atomic_dec_and_test(&cq->nr_events))
+                       wake_up(&cq->wait_completion);
+
+               spin_lock_irq(&cct->task_lock);
+               spin_lock(&cq->task_lock);
+               cq->nr_callbacks--;
+               if (!cq->nr_callbacks) {
+                       list_del_init(cct->cq_list.next);
+                       cct->cq_jobs--;
+               }
+               spin_unlock(&cq->task_lock);
+       }
+}
+
+static void comp_task_park(unsigned int cpu)
+{
+       struct ehca_cpu_comp_task *cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu);
+       struct ehca_cpu_comp_task *target;
+       struct task_struct *thread;
+       struct ehca_cq *cq, *tmp;
+       LIST_HEAD(list);
+
+       spin_lock_irq(&cct->task_lock);
+       cct->cq_jobs = 0;
+       cct->active = 0;
+       list_splice_init(&cct->cq_list, &list);
+       spin_unlock_irq(&cct->task_lock);
+
+       cpu = find_next_online_cpu(pool);
+       target = per_cpu_ptr(pool->cpu_comp_tasks, cpu);
+       thread = *per_cpu_ptr(pool->cpu_comp_threads, cpu);
+       spin_lock_irq(&target->task_lock);
+       list_for_each_entry_safe(cq, tmp, &list, entry) {
+               list_del(&cq->entry);
+               __queue_comp_task(cq, target, thread);
+       }
+       spin_unlock_irq(&target->task_lock);
+}
+
+static void comp_task_stop(unsigned int cpu, bool online)
+{
+       struct ehca_cpu_comp_task *cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu);
+
+       spin_lock_irq(&cct->task_lock);
+       cct->cq_jobs = 0;
+       cct->active = 0;
+       WARN_ON(!list_empty(&cct->cq_list));
+       spin_unlock_irq(&cct->task_lock);
+}
+
+static int comp_task_should_run(unsigned int cpu)
+{
+       struct ehca_cpu_comp_task *cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu);
+
+       return cct->cq_jobs;
+}
+
+static void comp_task(unsigned int cpu)
+{
+       struct ehca_cpu_comp_task *cct = this_cpu_ptr(pool->cpu_comp_tasks);
+       int cql_empty;
+
+       spin_lock_irq(&cct->task_lock);
+       cql_empty = list_empty(&cct->cq_list);
+       if (!cql_empty) {
+               __set_current_state(TASK_RUNNING);
+               run_comp_task(cct);
+       }
+       spin_unlock_irq(&cct->task_lock);
+}
+
+static struct smp_hotplug_thread comp_pool_threads = {
+       .thread_should_run      = comp_task_should_run,
+       .thread_fn              = comp_task,
+       .thread_comm            = "ehca_comp/%u",
+       .cleanup                = comp_task_stop,
+       .park                   = comp_task_park,
+};
+
+int ehca_create_comp_pool(void)
+{
+       int cpu, ret = -ENOMEM;
+
+       if (!ehca_scaling_code)
+               return 0;
+
+       pool = kzalloc(sizeof(struct ehca_comp_pool), GFP_KERNEL);
+       if (pool == NULL)
+               return -ENOMEM;
+
+       spin_lock_init(&pool->last_cpu_lock);
+       pool->last_cpu = cpumask_any(cpu_online_mask);
+
+       pool->cpu_comp_tasks = alloc_percpu(struct ehca_cpu_comp_task);
+       if (!pool->cpu_comp_tasks)
+               goto out_pool;
+
+       pool->cpu_comp_threads = alloc_percpu(struct task_struct *);
+       if (!pool->cpu_comp_threads)
+               goto out_tasks;
+
+       for_each_present_cpu(cpu) {
+               struct ehca_cpu_comp_task *cct;
+
+               cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu);
+               spin_lock_init(&cct->task_lock);
+               INIT_LIST_HEAD(&cct->cq_list);
+       }
+
+       comp_pool_threads.store = pool->cpu_comp_threads;
+       ret = smpboot_register_percpu_thread(&comp_pool_threads);
+       if (ret)
+               goto out_threads;
+
+       pr_info("eHCA scaling code enabled\n");
+       return ret;
+
+out_threads:
+       free_percpu(pool->cpu_comp_threads);
+out_tasks:
+       free_percpu(pool->cpu_comp_tasks);
+out_pool:
+       kfree(pool);
+       return ret;
+}
+
+void ehca_destroy_comp_pool(void)
+{
+       if (!ehca_scaling_code)
+               return;
+
+       smpboot_unregister_percpu_thread(&comp_pool_threads);
+
+       free_percpu(pool->cpu_comp_threads);
+       free_percpu(pool->cpu_comp_tasks);
+       kfree(pool);
+}
diff --git a/drivers/staging/rdma/ehca/ehca_irq.h b/drivers/staging/rdma/ehca/ehca_irq.h
new file mode 100644 (file)
index 0000000..5370199
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ *  IBM eServer eHCA Infiniband device driver for Linux on POWER
+ *
+ *  Function definitions and structs for EQs, NEQs and interrupts
+ *
+ *  Authors: Heiko J Schick <schickhj@de.ibm.com>
+ *           Khadija Souissi <souissi@de.ibm.com>
+ *
+ *  Copyright (c) 2005 IBM Corporation
+ *
+ *  All rights reserved.
+ *
+ *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
+ *  BSD.
+ *
+ * OpenIB BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __EHCA_IRQ_H
+#define __EHCA_IRQ_H
+
+
+struct ehca_shca;
+
+#include <linux/interrupt.h>
+#include <linux/types.h>
+
+int ehca_error_data(struct ehca_shca *shca, void *data, u64 resource);
+
+irqreturn_t ehca_interrupt_neq(int irq, void *dev_id);
+void ehca_tasklet_neq(unsigned long data);
+
+irqreturn_t ehca_interrupt_eq(int irq, void *dev_id);
+void ehca_tasklet_eq(unsigned long data);
+void ehca_process_eq(struct ehca_shca *shca, int is_irq);
+
+struct ehca_cpu_comp_task {
+       struct list_head cq_list;
+       spinlock_t task_lock;
+       int cq_jobs;
+       int active;
+};
+
+struct ehca_comp_pool {
+       struct ehca_cpu_comp_task __percpu *cpu_comp_tasks;
+       struct task_struct * __percpu *cpu_comp_threads;
+       int last_cpu;
+       spinlock_t last_cpu_lock;
+};
+
+int ehca_create_comp_pool(void);
+void ehca_destroy_comp_pool(void);
+
+#endif
diff --git a/drivers/staging/rdma/ehca/ehca_iverbs.h b/drivers/staging/rdma/ehca/ehca_iverbs.h
new file mode 100644 (file)
index 0000000..80e6a3d
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ *  IBM eServer eHCA Infiniband device driver for Linux on POWER
+ *
+ *  Function definitions for internal functions
+ *
+ *  Authors: Heiko J Schick <schickhj@de.ibm.com>
+ *           Dietmar Decker <ddecker@de.ibm.com>
+ *
+ *  Copyright (c) 2005 IBM Corporation
+ *
+ *  All rights reserved.
+ *
+ *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
+ *  BSD.
+ *
+ * OpenIB BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __EHCA_IVERBS_H__
+#define __EHCA_IVERBS_H__
+
+#include "ehca_classes.h"
+
+int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props,
+                     struct ib_udata *uhw);
+
+int ehca_query_port(struct ib_device *ibdev, u8 port,
+                   struct ib_port_attr *props);
+
+enum rdma_protocol_type
+ehca_query_protocol(struct ib_device *device, u8 port_num);
+
+int ehca_query_sma_attr(struct ehca_shca *shca, u8 port,
+                       struct ehca_sma_attr *attr);
+
+int ehca_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 * pkey);
+
+int ehca_query_gid(struct ib_device *ibdev, u8 port, int index,
+                  union ib_gid *gid);
+
+int ehca_modify_port(struct ib_device *ibdev, u8 port, int port_modify_mask,
+                    struct ib_port_modify *props);
+
+struct ib_pd *ehca_alloc_pd(struct ib_device *device,
+                           struct ib_ucontext *context,
+                           struct ib_udata *udata);
+
+int ehca_dealloc_pd(struct ib_pd *pd);
+
+struct ib_ah *ehca_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr);
+
+int ehca_modify_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr);
+
+int ehca_query_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr);
+
+int ehca_destroy_ah(struct ib_ah *ah);
+
+struct ib_mr *ehca_get_dma_mr(struct ib_pd *pd, int mr_access_flags);
+
+struct ib_mr *ehca_reg_phys_mr(struct ib_pd *pd,
+                              struct ib_phys_buf *phys_buf_array,
+                              int num_phys_buf,
+                              int mr_access_flags, u64 *iova_start);
+
+struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
+                              u64 virt, int mr_access_flags,
+                              struct ib_udata *udata);
+
+int ehca_rereg_phys_mr(struct ib_mr *mr,
+                      int mr_rereg_mask,
+                      struct ib_pd *pd,
+                      struct ib_phys_buf *phys_buf_array,
+                      int num_phys_buf, int mr_access_flags, u64 *iova_start);
+
+int ehca_query_mr(struct ib_mr *mr, struct ib_mr_attr *mr_attr);
+
+int ehca_dereg_mr(struct ib_mr *mr);
+
+struct ib_mw *ehca_alloc_mw(struct ib_pd *pd, enum ib_mw_type type);
+
+int ehca_bind_mw(struct ib_qp *qp, struct ib_mw *mw,
+                struct ib_mw_bind *mw_bind);
+
+int ehca_dealloc_mw(struct ib_mw *mw);
+
+struct ib_fmr *ehca_alloc_fmr(struct ib_pd *pd,
+                             int mr_access_flags,
+                             struct ib_fmr_attr *fmr_attr);
+
+int ehca_map_phys_fmr(struct ib_fmr *fmr,
+                     u64 *page_list, int list_len, u64 iova);
+
+int ehca_unmap_fmr(struct list_head *fmr_list);
+
+int ehca_dealloc_fmr(struct ib_fmr *fmr);
+
+enum ehca_eq_type {
+       EHCA_EQ = 0, /* Event Queue              */
+       EHCA_NEQ     /* Notification Event Queue */
+};
+
+int ehca_create_eq(struct ehca_shca *shca, struct ehca_eq *eq,
+                  enum ehca_eq_type type, const u32 length);
+
+int ehca_destroy_eq(struct ehca_shca *shca, struct ehca_eq *eq);
+
+void *ehca_poll_eq(struct ehca_shca *shca, struct ehca_eq *eq);
+
+
+struct ib_cq *ehca_create_cq(struct ib_device *device,
+                            const struct ib_cq_init_attr *attr,
+                            struct ib_ucontext *context,
+                            struct ib_udata *udata);
+
+int ehca_destroy_cq(struct ib_cq *cq);
+
+int ehca_resize_cq(struct ib_cq *cq, int cqe, struct ib_udata *udata);
+
+int ehca_poll_cq(struct ib_cq *cq, int num_entries, struct ib_wc *wc);
+
+int ehca_peek_cq(struct ib_cq *cq, int wc_cnt);
+
+int ehca_req_notify_cq(struct ib_cq *cq, enum ib_cq_notify_flags notify_flags);
+
+struct ib_qp *ehca_create_qp(struct ib_pd *pd,
+                            struct ib_qp_init_attr *init_attr,
+                            struct ib_udata *udata);
+
+int ehca_destroy_qp(struct ib_qp *qp);
+
+int ehca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
+                  struct ib_udata *udata);
+
+int ehca_query_qp(struct ib_qp *qp, struct ib_qp_attr *qp_attr,
+                 int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr);
+
+int ehca_post_send(struct ib_qp *qp, struct ib_send_wr *send_wr,
+                  struct ib_send_wr **bad_send_wr);
+
+int ehca_post_recv(struct ib_qp *qp, struct ib_recv_wr *recv_wr,
+                  struct ib_recv_wr **bad_recv_wr);
+
+int ehca_post_srq_recv(struct ib_srq *srq,
+                      struct ib_recv_wr *recv_wr,
+                      struct ib_recv_wr **bad_recv_wr);
+
+struct ib_srq *ehca_create_srq(struct ib_pd *pd,
+                              struct ib_srq_init_attr *init_attr,
+                              struct ib_udata *udata);
+
+int ehca_modify_srq(struct ib_srq *srq, struct ib_srq_attr *attr,
+                   enum ib_srq_attr_mask attr_mask, struct ib_udata *udata);
+
+int ehca_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr);
+
+int ehca_destroy_srq(struct ib_srq *srq);
+
+u64 ehca_define_sqp(struct ehca_shca *shca, struct ehca_qp *ibqp,
+                   struct ib_qp_init_attr *qp_init_attr);
+
+int ehca_attach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid);
+
+int ehca_detach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid);
+
+struct ib_ucontext *ehca_alloc_ucontext(struct ib_device *device,
+                                       struct ib_udata *udata);
+
+int ehca_dealloc_ucontext(struct ib_ucontext *context);
+
+int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma);
+
+int ehca_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
+                    const struct ib_wc *in_wc, const struct ib_grh *in_grh,
+                    const struct ib_mad_hdr *in, size_t in_mad_size,
+                    struct ib_mad_hdr *out, size_t *out_mad_size,
+                    u16 *out_mad_pkey_index);
+
+void ehca_poll_eqs(unsigned long data);
+
+int ehca_calc_ipd(struct ehca_shca *shca, int port,
+                 enum ib_rate path_rate, u32 *ipd);
+
+void ehca_add_to_err_list(struct ehca_qp *qp, int on_sq);
+
+#ifdef CONFIG_PPC_64K_PAGES
+void *ehca_alloc_fw_ctrlblock(gfp_t flags);
+void ehca_free_fw_ctrlblock(void *ptr);
+#else
+#define ehca_alloc_fw_ctrlblock(flags) ((void *)get_zeroed_page(flags))
+#define ehca_free_fw_ctrlblock(ptr) free_page((unsigned long)(ptr))
+#endif
+
+void ehca_recover_sqp(struct ib_qp *sqp);
+
+#endif
diff --git a/drivers/staging/rdma/ehca/ehca_main.c b/drivers/staging/rdma/ehca/ehca_main.c
new file mode 100644 (file)
index 0000000..8246418
--- /dev/null
@@ -0,0 +1,1123 @@
+/*
+ *  IBM eServer eHCA Infiniband device driver for Linux on POWER
+ *
+ *  module start stop, hca detection
+ *
+ *  Authors: Heiko J Schick <schickhj@de.ibm.com>
+ *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
+ *           Joachim Fenkes <fenkes@de.ibm.com>
+ *
+ *  Copyright (c) 2005 IBM Corporation
+ *
+ *  All rights reserved.
+ *
+ *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
+ *  BSD.
+ *
+ * OpenIB BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef CONFIG_PPC_64K_PAGES
+#include <linux/slab.h>
+#endif
+
+#include <linux/notifier.h>
+#include <linux/memory.h>
+#include <rdma/ib_mad.h>
+#include "ehca_classes.h"
+#include "ehca_iverbs.h"
+#include "ehca_mrmw.h"
+#include "ehca_tools.h"
+#include "hcp_if.h"
+
+#define HCAD_VERSION "0029"
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Christoph Raisch <raisch@de.ibm.com>");
+MODULE_DESCRIPTION("IBM eServer HCA InfiniBand Device Driver");
+MODULE_VERSION(HCAD_VERSION);
+
+static bool ehca_open_aqp1    = 0;
+static int ehca_hw_level      = 0;
+static bool ehca_poll_all_eqs = 1;
+
+int ehca_debug_level   = 0;
+int ehca_nr_ports      = -1;
+bool ehca_use_hp_mr    = 0;
+int ehca_port_act_time = 30;
+int ehca_static_rate   = -1;
+bool ehca_scaling_code = 0;
+int ehca_lock_hcalls   = -1;
+int ehca_max_cq        = -1;
+int ehca_max_qp        = -1;
+
+module_param_named(open_aqp1,     ehca_open_aqp1,     bool, S_IRUGO);
+module_param_named(debug_level,   ehca_debug_level,   int,  S_IRUGO);
+module_param_named(hw_level,      ehca_hw_level,      int,  S_IRUGO);
+module_param_named(nr_ports,      ehca_nr_ports,      int,  S_IRUGO);
+module_param_named(use_hp_mr,     ehca_use_hp_mr,     bool, S_IRUGO);
+module_param_named(port_act_time, ehca_port_act_time, int,  S_IRUGO);
+module_param_named(poll_all_eqs,  ehca_poll_all_eqs,  bool, S_IRUGO);
+module_param_named(static_rate,   ehca_static_rate,   int,  S_IRUGO);
+module_param_named(scaling_code,  ehca_scaling_code,  bool, S_IRUGO);
+module_param_named(lock_hcalls,   ehca_lock_hcalls,   bint, S_IRUGO);
+module_param_named(number_of_cqs, ehca_max_cq,        int,  S_IRUGO);
+module_param_named(number_of_qps, ehca_max_qp,        int,  S_IRUGO);
+
+MODULE_PARM_DESC(open_aqp1,
+                "Open AQP1 on startup (default: no)");
+MODULE_PARM_DESC(debug_level,
+                "Amount of debug output (0: none (default), 1: traces, "
+                "2: some dumps, 3: lots)");
+MODULE_PARM_DESC(hw_level,
+                "Hardware level (0: autosensing (default), "
+                "0x10..0x14: eHCA, 0x20..0x23: eHCA2)");
+MODULE_PARM_DESC(nr_ports,
+                "number of connected ports (-1: autodetect (default), "
+                "1: port one only, 2: two ports)");
+MODULE_PARM_DESC(use_hp_mr,
+                "Use high performance MRs (default: no)");
+MODULE_PARM_DESC(port_act_time,
+                "Time to wait for port activation (default: 30 sec)");
+MODULE_PARM_DESC(poll_all_eqs,
+                "Poll all event queues periodically (default: yes)");
+MODULE_PARM_DESC(static_rate,
+                "Set permanent static rate (default: no static rate)");
+MODULE_PARM_DESC(scaling_code,
+                "Enable scaling code (default: no)");
+MODULE_PARM_DESC(lock_hcalls,
+                "Serialize all hCalls made by the driver "
+                "(default: autodetect)");
+MODULE_PARM_DESC(number_of_cqs,
+               "Max number of CQs which can be allocated "
+               "(default: autodetect)");
+MODULE_PARM_DESC(number_of_qps,
+               "Max number of QPs which can be allocated "
+               "(default: autodetect)");
+
+DEFINE_RWLOCK(ehca_qp_idr_lock);
+DEFINE_RWLOCK(ehca_cq_idr_lock);
+DEFINE_IDR(ehca_qp_idr);
+DEFINE_IDR(ehca_cq_idr);
+
+static LIST_HEAD(shca_list); /* list of all registered ehcas */
+DEFINE_SPINLOCK(shca_list_lock);
+
+static struct timer_list poll_eqs_timer;
+
+#ifdef CONFIG_PPC_64K_PAGES
+static struct kmem_cache *ctblk_cache;
+
+void *ehca_alloc_fw_ctrlblock(gfp_t flags)
+{
+       void *ret = kmem_cache_zalloc(ctblk_cache, flags);
+       if (!ret)
+               ehca_gen_err("Out of memory for ctblk");
+       return ret;
+}
+
+void ehca_free_fw_ctrlblock(void *ptr)
+{
+       if (ptr)
+               kmem_cache_free(ctblk_cache, ptr);
+
+}
+#endif
+
+int ehca2ib_return_code(u64 ehca_rc)
+{
+       switch (ehca_rc) {
+       case H_SUCCESS:
+               return 0;
+       case H_RESOURCE:             /* Resource in use */
+       case H_BUSY:
+               return -EBUSY;
+       case H_NOT_ENOUGH_RESOURCES: /* insufficient resources */
+       case H_CONSTRAINED:          /* resource constraint */
+       case H_NO_MEM:
+               return -ENOMEM;
+       default:
+               return -EINVAL;
+       }
+}
+
+static int ehca_create_slab_caches(void)
+{
+       int ret;
+
+       ret = ehca_init_pd_cache();
+       if (ret) {
+               ehca_gen_err("Cannot create PD SLAB cache.");
+               return ret;
+       }
+
+       ret = ehca_init_cq_cache();
+       if (ret) {
+               ehca_gen_err("Cannot create CQ SLAB cache.");
+               goto create_slab_caches2;
+       }
+
+       ret = ehca_init_qp_cache();
+       if (ret) {
+               ehca_gen_err("Cannot create QP SLAB cache.");
+               goto create_slab_caches3;
+       }
+
+       ret = ehca_init_av_cache();
+       if (ret) {
+               ehca_gen_err("Cannot create AV SLAB cache.");
+               goto create_slab_caches4;
+       }
+
+       ret = ehca_init_mrmw_cache();
+       if (ret) {
+               ehca_gen_err("Cannot create MR&MW SLAB cache.");
+               goto create_slab_caches5;
+       }
+
+       ret = ehca_init_small_qp_cache();
+       if (ret) {
+               ehca_gen_err("Cannot create small queue SLAB cache.");
+               goto create_slab_caches6;
+       }
+
+#ifdef CONFIG_PPC_64K_PAGES
+       ctblk_cache = kmem_cache_create("ehca_cache_ctblk",
+                                       EHCA_PAGESIZE, H_CB_ALIGNMENT,
+                                       SLAB_HWCACHE_ALIGN,
+                                       NULL);
+       if (!ctblk_cache) {
+               ehca_gen_err("Cannot create ctblk SLAB cache.");
+               ehca_cleanup_small_qp_cache();
+               ret = -ENOMEM;
+               goto create_slab_caches6;
+       }
+#endif
+       return 0;
+
+create_slab_caches6:
+       ehca_cleanup_mrmw_cache();
+
+create_slab_caches5:
+       ehca_cleanup_av_cache();
+
+create_slab_caches4:
+       ehca_cleanup_qp_cache();
+
+create_slab_caches3:
+       ehca_cleanup_cq_cache();
+
+create_slab_caches2:
+       ehca_cleanup_pd_cache();
+
+       return ret;
+}
+
+static void ehca_destroy_slab_caches(void)
+{
+       ehca_cleanup_small_qp_cache();
+       ehca_cleanup_mrmw_cache();
+       ehca_cleanup_av_cache();
+       ehca_cleanup_qp_cache();
+       ehca_cleanup_cq_cache();
+       ehca_cleanup_pd_cache();
+#ifdef CONFIG_PPC_64K_PAGES
+       if (ctblk_cache)
+               kmem_cache_destroy(ctblk_cache);
+#endif
+}
+
+#define EHCA_HCAAVER  EHCA_BMASK_IBM(32, 39)
+#define EHCA_REVID    EHCA_BMASK_IBM(40, 63)
+
+static struct cap_descr {
+       u64 mask;
+       char *descr;
+} hca_cap_descr[] = {
+       { HCA_CAP_AH_PORT_NR_CHECK, "HCA_CAP_AH_PORT_NR_CHECK" },
+       { HCA_CAP_ATOMIC, "HCA_CAP_ATOMIC" },
+       { HCA_CAP_AUTO_PATH_MIG, "HCA_CAP_AUTO_PATH_MIG" },
+       { HCA_CAP_BAD_P_KEY_CTR, "HCA_CAP_BAD_P_KEY_CTR" },
+       { HCA_CAP_SQD_RTS_PORT_CHANGE, "HCA_CAP_SQD_RTS_PORT_CHANGE" },
+       { HCA_CAP_CUR_QP_STATE_MOD, "HCA_CAP_CUR_QP_STATE_MOD" },
+       { HCA_CAP_INIT_TYPE, "HCA_CAP_INIT_TYPE" },
+       { HCA_CAP_PORT_ACTIVE_EVENT, "HCA_CAP_PORT_ACTIVE_EVENT" },
+       { HCA_CAP_Q_KEY_VIOL_CTR, "HCA_CAP_Q_KEY_VIOL_CTR" },
+       { HCA_CAP_WQE_RESIZE, "HCA_CAP_WQE_RESIZE" },
+       { HCA_CAP_RAW_PACKET_MCAST, "HCA_CAP_RAW_PACKET_MCAST" },
+       { HCA_CAP_SHUTDOWN_PORT, "HCA_CAP_SHUTDOWN_PORT" },
+       { HCA_CAP_RC_LL_QP, "HCA_CAP_RC_LL_QP" },
+       { HCA_CAP_SRQ, "HCA_CAP_SRQ" },
+       { HCA_CAP_UD_LL_QP, "HCA_CAP_UD_LL_QP" },
+       { HCA_CAP_RESIZE_MR, "HCA_CAP_RESIZE_MR" },
+       { HCA_CAP_MINI_QP, "HCA_CAP_MINI_QP" },
+       { HCA_CAP_H_ALLOC_RES_SYNC, "HCA_CAP_H_ALLOC_RES_SYNC" },
+};
+
+static int ehca_sense_attributes(struct ehca_shca *shca)
+{
+       int i, ret = 0;
+       u64 h_ret;
+       struct hipz_query_hca *rblock;
+       struct hipz_query_port *port;
+       const char *loc_code;
+
+       static const u32 pgsize_map[] = {
+               HCA_CAP_MR_PGSIZE_4K,  0x1000,
+               HCA_CAP_MR_PGSIZE_64K, 0x10000,
+               HCA_CAP_MR_PGSIZE_1M,  0x100000,
+               HCA_CAP_MR_PGSIZE_16M, 0x1000000,
+       };
+
+       ehca_gen_dbg("Probing adapter %s...",
+                    shca->ofdev->dev.of_node->full_name);
+       loc_code = of_get_property(shca->ofdev->dev.of_node, "ibm,loc-code",
+                                  NULL);
+       if (loc_code)
+               ehca_gen_dbg(" ... location lode=%s", loc_code);
+
+       rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
+       if (!rblock) {
+               ehca_gen_err("Cannot allocate rblock memory.");
+               return -ENOMEM;
+       }
+
+       h_ret = hipz_h_query_hca(shca->ipz_hca_handle, rblock);
+       if (h_ret != H_SUCCESS) {
+               ehca_gen_err("Cannot query device properties. h_ret=%lli",
+                            h_ret);
+               ret = -EPERM;
+               goto sense_attributes1;
+       }
+
+       if (ehca_nr_ports == 1)
+               shca->num_ports = 1;
+       else
+               shca->num_ports = (u8)rblock->num_ports;
+
+       ehca_gen_dbg(" ... found %x ports", rblock->num_ports);
+
+       if (ehca_hw_level == 0) {
+               u32 hcaaver;
+               u32 revid;
+
+               hcaaver = EHCA_BMASK_GET(EHCA_HCAAVER, rblock->hw_ver);
+               revid   = EHCA_BMASK_GET(EHCA_REVID, rblock->hw_ver);
+
+               ehca_gen_dbg(" ... hardware version=%x:%x", hcaaver, revid);
+
+               if (hcaaver == 1) {
+                       if (revid <= 3)
+                               shca->hw_level = 0x10 | (revid + 1);
+                       else
+                               shca->hw_level = 0x14;
+               } else if (hcaaver == 2) {
+                       if (revid == 0)
+                               shca->hw_level = 0x21;
+                       else if (revid == 0x10)
+                               shca->hw_level = 0x22;
+                       else if (revid == 0x20 || revid == 0x21)
+                               shca->hw_level = 0x23;
+               }
+
+               if (!shca->hw_level) {
+                       ehca_gen_warn("unknown hardware version"
+                                     " - assuming default level");
+                       shca->hw_level = 0x22;
+               }
+       } else
+               shca->hw_level = ehca_hw_level;
+       ehca_gen_dbg(" ... hardware level=%x", shca->hw_level);
+
+       shca->hca_cap = rblock->hca_cap_indicators;
+       ehca_gen_dbg(" ... HCA capabilities:");
+       for (i = 0; i < ARRAY_SIZE(hca_cap_descr); i++)
+               if (EHCA_BMASK_GET(hca_cap_descr[i].mask, shca->hca_cap))
+                       ehca_gen_dbg("   %s", hca_cap_descr[i].descr);
+
+       /* Autodetect hCall locking -- the "H_ALLOC_RESOURCE synced" flag is
+        * a firmware property, so it's valid across all adapters
+        */
+       if (ehca_lock_hcalls == -1)
+               ehca_lock_hcalls = !EHCA_BMASK_GET(HCA_CAP_H_ALLOC_RES_SYNC,
+                                       shca->hca_cap);
+
+       /* translate supported MR page sizes; always support 4K */
+       shca->hca_cap_mr_pgsize = EHCA_PAGESIZE;
+       for (i = 0; i < ARRAY_SIZE(pgsize_map); i += 2)
+               if (rblock->memory_page_size_supported & pgsize_map[i])
+                       shca->hca_cap_mr_pgsize |= pgsize_map[i + 1];
+
+       /* Set maximum number of CQs and QPs to calculate EQ size */
+       if (shca->max_num_qps == -1)
+               shca->max_num_qps = min_t(int, rblock->max_qp,
+                                         EHCA_MAX_NUM_QUEUES);
+       else if (shca->max_num_qps < 1 || shca->max_num_qps > rblock->max_qp) {
+               ehca_gen_warn("The requested number of QPs is out of range "
+                             "(1 - %i) specified by HW. Value is set to %i",
+                             rblock->max_qp, rblock->max_qp);
+               shca->max_num_qps = rblock->max_qp;
+       }
+
+       if (shca->max_num_cqs == -1)
+               shca->max_num_cqs = min_t(int, rblock->max_cq,
+                                         EHCA_MAX_NUM_QUEUES);
+       else if (shca->max_num_cqs < 1 || shca->max_num_cqs > rblock->max_cq) {
+               ehca_gen_warn("The requested number of CQs is out of range "
+                             "(1 - %i) specified by HW. Value is set to %i",
+                             rblock->max_cq, rblock->max_cq);
+       }
+
+       /* query max MTU from first port -- it's the same for all ports */
+       port = (struct hipz_query_port *)rblock;
+       h_ret = hipz_h_query_port(shca->ipz_hca_handle, 1, port);
+       if (h_ret != H_SUCCESS) {
+               ehca_gen_err("Cannot query port properties. h_ret=%lli",
+                            h_ret);
+               ret = -EPERM;
+               goto sense_attributes1;
+       }
+
+       shca->max_mtu = port->max_mtu;
+
+sense_attributes1:
+       ehca_free_fw_ctrlblock(rblock);
+       return ret;
+}
+
+static int init_node_guid(struct ehca_shca *shca)
+{
+       int ret = 0;
+       struct hipz_query_hca *rblock;
+
+       rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
+       if (!rblock) {
+               ehca_err(&shca->ib_device, "Can't allocate rblock memory.");
+               return -ENOMEM;
+       }
+
+       if (hipz_h_query_hca(shca->ipz_hca_handle, rblock) != H_SUCCESS) {
+               ehca_err(&shca->ib_device, "Can't query device properties");
+               ret = -EINVAL;
+               goto init_node_guid1;
+       }
+
+       memcpy(&shca->ib_device.node_guid, &rblock->node_guid, sizeof(u64));
+
+init_node_guid1:
+       ehca_free_fw_ctrlblock(rblock);
+       return ret;
+}
+
+static int ehca_port_immutable(struct ib_device *ibdev, u8 port_num,
+                              struct ib_port_immutable *immutable)
+{
+       struct ib_port_attr attr;
+       int err;
+
+       err = ehca_query_port(ibdev, port_num, &attr);
+       if (err)
+               return err;
+
+       immutable->pkey_tbl_len = attr.pkey_tbl_len;
+       immutable->gid_tbl_len = attr.gid_tbl_len;
+       immutable->core_cap_flags = RDMA_CORE_PORT_IBA_IB;
+       immutable->max_mad_size = IB_MGMT_MAD_SIZE;
+
+       return 0;
+}
+
+static int ehca_init_device(struct ehca_shca *shca)
+{
+       int ret;
+
+       ret = init_node_guid(shca);
+       if (ret)
+               return ret;
+
+       strlcpy(shca->ib_device.name, "ehca%d", IB_DEVICE_NAME_MAX);
+       shca->ib_device.owner               = THIS_MODULE;
+
+       shca->ib_device.uverbs_abi_ver      = 8;
+       shca->ib_device.uverbs_cmd_mask     =
+               (1ull << IB_USER_VERBS_CMD_GET_CONTEXT)         |
+               (1ull << IB_USER_VERBS_CMD_QUERY_DEVICE)        |
+               (1ull << IB_USER_VERBS_CMD_QUERY_PORT)          |
+               (1ull << IB_USER_VERBS_CMD_ALLOC_PD)            |
+               (1ull << IB_USER_VERBS_CMD_DEALLOC_PD)          |
+               (1ull << IB_USER_VERBS_CMD_REG_MR)              |
+               (1ull << IB_USER_VERBS_CMD_DEREG_MR)            |
+               (1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) |
+               (1ull << IB_USER_VERBS_CMD_CREATE_CQ)           |
+               (1ull << IB_USER_VERBS_CMD_DESTROY_CQ)          |
+               (1ull << IB_USER_VERBS_CMD_CREATE_QP)           |
+               (1ull << IB_USER_VERBS_CMD_MODIFY_QP)           |
+               (1ull << IB_USER_VERBS_CMD_QUERY_QP)            |
+               (1ull << IB_USER_VERBS_CMD_DESTROY_QP)          |
+               (1ull << IB_USER_VERBS_CMD_ATTACH_MCAST)        |
+               (1ull << IB_USER_VERBS_CMD_DETACH_MCAST);
+
+       shca->ib_device.node_type           = RDMA_NODE_IB_CA;
+       shca->ib_device.phys_port_cnt       = shca->num_ports;
+       shca->ib_device.num_comp_vectors    = 1;
+       shca->ib_device.dma_device          = &shca->ofdev->dev;
+       shca->ib_device.query_device        = ehca_query_device;
+       shca->ib_device.query_port          = ehca_query_port;
+       shca->ib_device.query_gid           = ehca_query_gid;
+       shca->ib_device.query_pkey          = ehca_query_pkey;
+       /* shca->in_device.modify_device    = ehca_modify_device    */
+       shca->ib_device.modify_port         = ehca_modify_port;
+       shca->ib_device.alloc_ucontext      = ehca_alloc_ucontext;
+       shca->ib_device.dealloc_ucontext    = ehca_dealloc_ucontext;
+       shca->ib_device.alloc_pd            = ehca_alloc_pd;
+       shca->ib_device.dealloc_pd          = ehca_dealloc_pd;
+       shca->ib_device.create_ah           = ehca_create_ah;
+       /* shca->ib_device.modify_ah        = ehca_modify_ah;       */
+       shca->ib_device.query_ah            = ehca_query_ah;
+       shca->ib_device.destroy_ah          = ehca_destroy_ah;
+       shca->ib_device.create_qp           = ehca_create_qp;
+       shca->ib_device.modify_qp           = ehca_modify_qp;
+       shca->ib_device.query_qp            = ehca_query_qp;
+       shca->ib_device.destroy_qp          = ehca_destroy_qp;
+       shca->ib_device.post_send           = ehca_post_send;
+       shca->ib_device.post_recv           = ehca_post_recv;
+       shca->ib_device.create_cq           = ehca_create_cq;
+       shca->ib_device.destroy_cq          = ehca_destroy_cq;
+       shca->ib_device.resize_cq           = ehca_resize_cq;
+       shca->ib_device.poll_cq             = ehca_poll_cq;
+       /* shca->ib_device.peek_cq          = ehca_peek_cq;         */
+       shca->ib_device.req_notify_cq       = ehca_req_notify_cq;
+       /* shca->ib_device.req_ncomp_notif  = ehca_req_ncomp_notif; */
+       shca->ib_device.get_dma_mr          = ehca_get_dma_mr;
+       shca->ib_device.reg_phys_mr         = ehca_reg_phys_mr;
+       shca->ib_device.reg_user_mr         = ehca_reg_user_mr;
+       shca->ib_device.query_mr            = ehca_query_mr;
+       shca->ib_device.dereg_mr            = ehca_dereg_mr;
+       shca->ib_device.rereg_phys_mr       = ehca_rereg_phys_mr;
+       shca->ib_device.alloc_mw            = ehca_alloc_mw;
+       shca->ib_device.bind_mw             = ehca_bind_mw;
+       shca->ib_device.dealloc_mw          = ehca_dealloc_mw;
+       shca->ib_device.alloc_fmr           = ehca_alloc_fmr;
+       shca->ib_device.map_phys_fmr        = ehca_map_phys_fmr;
+       shca->ib_device.unmap_fmr           = ehca_unmap_fmr;
+       shca->ib_device.dealloc_fmr         = ehca_dealloc_fmr;
+       shca->ib_device.attach_mcast        = ehca_attach_mcast;
+       shca->ib_device.detach_mcast        = ehca_detach_mcast;
+       shca->ib_device.process_mad         = ehca_process_mad;
+       shca->ib_device.mmap                = ehca_mmap;
+       shca->ib_device.dma_ops             = &ehca_dma_mapping_ops;
+       shca->ib_device.get_port_immutable  = ehca_port_immutable;
+
+       if (EHCA_BMASK_GET(HCA_CAP_SRQ, shca->hca_cap)) {
+               shca->ib_device.uverbs_cmd_mask |=
+                       (1ull << IB_USER_VERBS_CMD_CREATE_SRQ) |
+                       (1ull << IB_USER_VERBS_CMD_MODIFY_SRQ) |
+                       (1ull << IB_USER_VERBS_CMD_QUERY_SRQ) |
+                       (1ull << IB_USER_VERBS_CMD_DESTROY_SRQ);
+
+               shca->ib_device.create_srq          = ehca_create_srq;
+               shca->ib_device.modify_srq          = ehca_modify_srq;
+               shca->ib_device.query_srq           = ehca_query_srq;
+               shca->ib_device.destroy_srq         = ehca_destroy_srq;
+               shca->ib_device.post_srq_recv       = ehca_post_srq_recv;
+       }
+
+       return ret;
+}
+
+static int ehca_create_aqp1(struct ehca_shca *shca, u32 port)
+{
+       struct ehca_sport *sport = &shca->sport[port - 1];
+       struct ib_cq *ibcq;
+       struct ib_qp *ibqp;
+       struct ib_qp_init_attr qp_init_attr;
+       struct ib_cq_init_attr cq_attr = {};
+       int ret;
+
+       if (sport->ibcq_aqp1) {
+               ehca_err(&shca->ib_device, "AQP1 CQ is already created.");
+               return -EPERM;
+       }
+
+       cq_attr.cqe = 10;
+       ibcq = ib_create_cq(&shca->ib_device, NULL, NULL, (void *)(-1),
+                           &cq_attr);
+       if (IS_ERR(ibcq)) {
+               ehca_err(&shca->ib_device, "Cannot create AQP1 CQ.");
+               return PTR_ERR(ibcq);
+       }
+       sport->ibcq_aqp1 = ibcq;
+
+       if (sport->ibqp_sqp[IB_QPT_GSI]) {
+               ehca_err(&shca->ib_device, "AQP1 QP is already created.");
+               ret = -EPERM;
+               goto create_aqp1;
+       }
+
+       memset(&qp_init_attr, 0, sizeof(struct ib_qp_init_attr));
+       qp_init_attr.send_cq          = ibcq;
+       qp_init_attr.recv_cq          = ibcq;
+       qp_init_attr.sq_sig_type      = IB_SIGNAL_ALL_WR;
+       qp_init_attr.cap.max_send_wr  = 100;
+       qp_init_attr.cap.max_recv_wr  = 100;
+       qp_init_attr.cap.max_send_sge = 2;
+       qp_init_attr.cap.max_recv_sge = 1;
+       qp_init_attr.qp_type          = IB_QPT_GSI;
+       qp_init_attr.port_num         = port;
+       qp_init_attr.qp_context       = NULL;
+       qp_init_attr.event_handler    = NULL;
+       qp_init_attr.srq              = NULL;
+
+       ibqp = ib_create_qp(&shca->pd->ib_pd, &qp_init_attr);
+       if (IS_ERR(ibqp)) {
+               ehca_err(&shca->ib_device, "Cannot create AQP1 QP.");
+               ret = PTR_ERR(ibqp);
+               goto create_aqp1;
+       }
+       sport->ibqp_sqp[IB_QPT_GSI] = ibqp;
+
+       return 0;
+
+create_aqp1:
+       ib_destroy_cq(sport->ibcq_aqp1);
+       return ret;
+}
+
+static int ehca_destroy_aqp1(struct ehca_sport *sport)
+{
+       int ret;
+
+       ret = ib_destroy_qp(sport->ibqp_sqp[IB_QPT_GSI]);
+       if (ret) {
+               ehca_gen_err("Cannot destroy AQP1 QP. ret=%i", ret);
+               return ret;
+       }
+
+       ret = ib_destroy_cq(sport->ibcq_aqp1);
+       if (ret)
+               ehca_gen_err("Cannot destroy AQP1 CQ. ret=%i", ret);
+
+       return ret;
+}
+
+static ssize_t ehca_show_debug_level(struct device_driver *ddp, char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%d\n", ehca_debug_level);
+}
+
+static ssize_t ehca_store_debug_level(struct device_driver *ddp,
+                                     const char *buf, size_t count)
+{
+       int value = (*buf) - '0';
+       if (value >= 0 && value <= 9)
+               ehca_debug_level = value;
+       return 1;
+}
+
+static DRIVER_ATTR(debug_level, S_IRUSR | S_IWUSR,
+                  ehca_show_debug_level, ehca_store_debug_level);
+
+static struct attribute *ehca_drv_attrs[] = {
+       &driver_attr_debug_level.attr,
+       NULL
+};
+
+static struct attribute_group ehca_drv_attr_grp = {
+       .attrs = ehca_drv_attrs
+};
+
+static const struct attribute_group *ehca_drv_attr_groups[] = {
+       &ehca_drv_attr_grp,
+       NULL,
+};
+
+#define EHCA_RESOURCE_ATTR(name)                                           \
+static ssize_t  ehca_show_##name(struct device *dev,                       \
+                                struct device_attribute *attr,            \
+                                char *buf)                                \
+{                                                                         \
+       struct ehca_shca *shca;                                            \
+       struct hipz_query_hca *rblock;                                     \
+       int data;                                                          \
+                                                                          \
+       shca = dev_get_drvdata(dev);                                       \
+                                                                          \
+       rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);                      \
+       if (!rblock) {                                                     \
+               dev_err(dev, "Can't allocate rblock memory.\n");           \
+               return 0;                                                  \
+       }                                                                  \
+                                                                          \
+       if (hipz_h_query_hca(shca->ipz_hca_handle, rblock) != H_SUCCESS) { \
+               dev_err(dev, "Can't query device properties\n");           \
+               ehca_free_fw_ctrlblock(rblock);                            \
+               return 0;                                                  \
+       }                                                                  \
+                                                                          \
+       data = rblock->name;                                               \
+       ehca_free_fw_ctrlblock(rblock);                                    \
+                                                                          \
+       if ((strcmp(#name, "num_ports") == 0) && (ehca_nr_ports == 1))     \
+               return snprintf(buf, 256, "1\n");                          \
+       else                                                               \
+               return snprintf(buf, 256, "%d\n", data);                   \
+                                                                          \
+}                                                                         \
+static DEVICE_ATTR(name, S_IRUGO, ehca_show_##name, NULL);
+
+EHCA_RESOURCE_ATTR(num_ports);
+EHCA_RESOURCE_ATTR(hw_ver);
+EHCA_RESOURCE_ATTR(max_eq);
+EHCA_RESOURCE_ATTR(cur_eq);
+EHCA_RESOURCE_ATTR(max_cq);
+EHCA_RESOURCE_ATTR(cur_cq);
+EHCA_RESOURCE_ATTR(max_qp);
+EHCA_RESOURCE_ATTR(cur_qp);
+EHCA_RESOURCE_ATTR(max_mr);
+EHCA_RESOURCE_ATTR(cur_mr);
+EHCA_RESOURCE_ATTR(max_mw);
+EHCA_RESOURCE_ATTR(cur_mw);
+EHCA_RESOURCE_ATTR(max_pd);
+EHCA_RESOURCE_ATTR(max_ah);
+
+static ssize_t ehca_show_adapter_handle(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct ehca_shca *shca = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%llx\n", shca->ipz_hca_handle.handle);
+
+}
+static DEVICE_ATTR(adapter_handle, S_IRUGO, ehca_show_adapter_handle, NULL);
+
+static struct attribute *ehca_dev_attrs[] = {
+       &dev_attr_adapter_handle.attr,
+       &dev_attr_num_ports.attr,
+       &dev_attr_hw_ver.attr,
+       &dev_attr_max_eq.attr,
+       &dev_attr_cur_eq.attr,
+       &dev_attr_max_cq.attr,
+       &dev_attr_cur_cq.attr,
+       &dev_attr_max_qp.attr,
+       &dev_attr_cur_qp.attr,
+       &dev_attr_max_mr.attr,
+       &dev_attr_cur_mr.attr,
+       &dev_attr_max_mw.attr,
+       &dev_attr_cur_mw.attr,
+       &dev_attr_max_pd.attr,
+       &dev_attr_max_ah.attr,
+       NULL
+};
+
+static struct attribute_group ehca_dev_attr_grp = {
+       .attrs = ehca_dev_attrs
+};
+
+static int ehca_probe(struct platform_device *dev)
+{
+       struct ehca_shca *shca;
+       const u64 *handle;
+       struct ib_pd *ibpd;
+       int ret, i, eq_size;
+       unsigned long flags;
+
+       handle = of_get_property(dev->dev.of_node, "ibm,hca-handle", NULL);
+       if (!handle) {
+               ehca_gen_err("Cannot get eHCA handle for adapter: %s.",
+                            dev->dev.of_node->full_name);
+               return -ENODEV;
+       }
+
+       if (!(*handle)) {
+               ehca_gen_err("Wrong eHCA handle for adapter: %s.",
+                            dev->dev.of_node->full_name);
+               return -ENODEV;
+       }
+
+       shca = (struct ehca_shca *)ib_alloc_device(sizeof(*shca));
+       if (!shca) {
+               ehca_gen_err("Cannot allocate shca memory.");
+               return -ENOMEM;
+       }
+
+       mutex_init(&shca->modify_mutex);
+       atomic_set(&shca->num_cqs, 0);
+       atomic_set(&shca->num_qps, 0);
+       shca->max_num_qps = ehca_max_qp;
+       shca->max_num_cqs = ehca_max_cq;
+
+       for (i = 0; i < ARRAY_SIZE(shca->sport); i++)
+               spin_lock_init(&shca->sport[i].mod_sqp_lock);
+
+       shca->ofdev = dev;
+       shca->ipz_hca_handle.handle = *handle;
+       dev_set_drvdata(&dev->dev, shca);
+
+       ret = ehca_sense_attributes(shca);
+       if (ret < 0) {
+               ehca_gen_err("Cannot sense eHCA attributes.");
+               goto probe1;
+       }
+
+       ret = ehca_init_device(shca);
+       if (ret) {
+               ehca_gen_err("Cannot init ehca  device struct");
+               goto probe1;
+       }
+
+       eq_size = 2 * shca->max_num_cqs + 4 * shca->max_num_qps;
+       /* create event queues */
+       ret = ehca_create_eq(shca, &shca->eq, EHCA_EQ, eq_size);
+       if (ret) {
+               ehca_err(&shca->ib_device, "Cannot create EQ.");
+               goto probe1;
+       }
+
+       ret = ehca_create_eq(shca, &shca->neq, EHCA_NEQ, 513);
+       if (ret) {
+               ehca_err(&shca->ib_device, "Cannot create NEQ.");
+               goto probe3;
+       }
+
+       /* create internal protection domain */
+       ibpd = ehca_alloc_pd(&shca->ib_device, (void *)(-1), NULL);
+       if (IS_ERR(ibpd)) {
+               ehca_err(&shca->ib_device, "Cannot create internal PD.");
+               ret = PTR_ERR(ibpd);
+               goto probe4;
+       }
+
+       shca->pd = container_of(ibpd, struct ehca_pd, ib_pd);
+       shca->pd->ib_pd.device = &shca->ib_device;
+
+       /* create internal max MR */
+       ret = ehca_reg_internal_maxmr(shca, shca->pd, &shca->maxmr);
+
+       if (ret) {
+               ehca_err(&shca->ib_device, "Cannot create internal MR ret=%i",
+                        ret);
+               goto probe5;
+       }
+
+       ret = ib_register_device(&shca->ib_device, NULL);
+       if (ret) {
+               ehca_err(&shca->ib_device,
+                        "ib_register_device() failed ret=%i", ret);
+               goto probe6;
+       }
+
+       /* create AQP1 for port 1 */
+       if (ehca_open_aqp1 == 1) {
+               shca->sport[0].port_state = IB_PORT_DOWN;
+               ret = ehca_create_aqp1(shca, 1);
+               if (ret) {
+                       ehca_err(&shca->ib_device,
+                                "Cannot create AQP1 for port 1.");
+                       goto probe7;
+               }
+       }
+
+       /* create AQP1 for port 2 */
+       if ((ehca_open_aqp1 == 1) && (shca->num_ports == 2)) {
+               shca->sport[1].port_state = IB_PORT_DOWN;
+               ret = ehca_create_aqp1(shca, 2);
+               if (ret) {
+                       ehca_err(&shca->ib_device,
+                                "Cannot create AQP1 for port 2.");
+                       goto probe8;
+               }
+       }
+
+       ret = sysfs_create_group(&dev->dev.kobj, &ehca_dev_attr_grp);
+       if (ret) /* only complain; we can live without attributes */
+               ehca_err(&shca->ib_device,
+                        "Cannot create device attributes  ret=%d", ret);
+
+       spin_lock_irqsave(&shca_list_lock, flags);
+       list_add(&shca->shca_list, &shca_list);
+       spin_unlock_irqrestore(&shca_list_lock, flags);
+
+       return 0;
+
+probe8:
+       ret = ehca_destroy_aqp1(&shca->sport[0]);
+       if (ret)
+               ehca_err(&shca->ib_device,
+                        "Cannot destroy AQP1 for port 1. ret=%i", ret);
+
+probe7:
+       ib_unregister_device(&shca->ib_device);
+
+probe6:
+       ret = ehca_dereg_internal_maxmr(shca);
+       if (ret)
+               ehca_err(&shca->ib_device,
+                        "Cannot destroy internal MR. ret=%x", ret);
+
+probe5:
+       ret = ehca_dealloc_pd(&shca->pd->ib_pd);
+       if (ret)
+               ehca_err(&shca->ib_device,
+                        "Cannot destroy internal PD. ret=%x", ret);
+
+probe4:
+       ret = ehca_destroy_eq(shca, &shca->neq);
+       if (ret)
+               ehca_err(&shca->ib_device,
+                        "Cannot destroy NEQ. ret=%x", ret);
+
+probe3:
+       ret = ehca_destroy_eq(shca, &shca->eq);
+       if (ret)
+               ehca_err(&shca->ib_device,
+                        "Cannot destroy EQ. ret=%x", ret);
+
+probe1:
+       ib_dealloc_device(&shca->ib_device);
+
+       return -EINVAL;
+}
+
+static int ehca_remove(struct platform_device *dev)
+{
+       struct ehca_shca *shca = dev_get_drvdata(&dev->dev);
+       unsigned long flags;
+       int ret;
+
+       sysfs_remove_group(&dev->dev.kobj, &ehca_dev_attr_grp);
+
+       if (ehca_open_aqp1 == 1) {
+               int i;
+               for (i = 0; i < shca->num_ports; i++) {
+                       ret = ehca_destroy_aqp1(&shca->sport[i]);
+                       if (ret)
+                               ehca_err(&shca->ib_device,
+                                        "Cannot destroy AQP1 for port %x "
+                                        "ret=%i", ret, i);
+               }
+       }
+
+       ib_unregister_device(&shca->ib_device);
+
+       ret = ehca_dereg_internal_maxmr(shca);
+       if (ret)
+               ehca_err(&shca->ib_device,
+                        "Cannot destroy internal MR. ret=%i", ret);
+
+       ret = ehca_dealloc_pd(&shca->pd->ib_pd);
+       if (ret)
+               ehca_err(&shca->ib_device,
+                        "Cannot destroy internal PD. ret=%i", ret);
+
+       ret = ehca_destroy_eq(shca, &shca->eq);
+       if (ret)
+               ehca_err(&shca->ib_device, "Cannot destroy EQ. ret=%i", ret);
+
+       ret = ehca_destroy_eq(shca, &shca->neq);
+       if (ret)
+               ehca_err(&shca->ib_device, "Canot destroy NEQ. ret=%i", ret);
+
+       ib_dealloc_device(&shca->ib_device);
+
+       spin_lock_irqsave(&shca_list_lock, flags);
+       list_del(&shca->shca_list);
+       spin_unlock_irqrestore(&shca_list_lock, flags);
+
+       return ret;
+}
+
+static struct of_device_id ehca_device_table[] =
+{
+       {
+               .name       = "lhca",
+               .compatible = "IBM,lhca",
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(of, ehca_device_table);
+
+static struct platform_driver ehca_driver = {
+       .probe       = ehca_probe,
+       .remove      = ehca_remove,
+       .driver = {
+               .name = "ehca",
+               .owner = THIS_MODULE,
+               .groups = ehca_drv_attr_groups,
+               .of_match_table = ehca_device_table,
+       },
+};
+
+void ehca_poll_eqs(unsigned long data)
+{
+       struct ehca_shca *shca;
+
+       spin_lock(&shca_list_lock);
+       list_for_each_entry(shca, &shca_list, shca_list) {
+               if (shca->eq.is_initialized) {
+                       /* call deadman proc only if eq ptr does not change */
+                       struct ehca_eq *eq = &shca->eq;
+                       int max = 3;
+                       volatile u64 q_ofs, q_ofs2;
+                       unsigned long flags;
+                       spin_lock_irqsave(&eq->spinlock, flags);
+                       q_ofs = eq->ipz_queue.current_q_offset;
+                       spin_unlock_irqrestore(&eq->spinlock, flags);
+                       do {
+                               spin_lock_irqsave(&eq->spinlock, flags);
+                               q_ofs2 = eq->ipz_queue.current_q_offset;
+                               spin_unlock_irqrestore(&eq->spinlock, flags);
+                               max--;
+                       } while (q_ofs == q_ofs2 && max > 0);
+                       if (q_ofs == q_ofs2)
+                               ehca_process_eq(shca, 0);
+               }
+       }
+       mod_timer(&poll_eqs_timer, round_jiffies(jiffies + HZ));
+       spin_unlock(&shca_list_lock);
+}
+
+static int ehca_mem_notifier(struct notifier_block *nb,
+                            unsigned long action, void *data)
+{
+       static unsigned long ehca_dmem_warn_time;
+       unsigned long flags;
+
+       switch (action) {
+       case MEM_CANCEL_OFFLINE:
+       case MEM_CANCEL_ONLINE:
+       case MEM_ONLINE:
+       case MEM_OFFLINE:
+               return NOTIFY_OK;
+       case MEM_GOING_ONLINE:
+       case MEM_GOING_OFFLINE:
+               /* only ok if no hca is attached to the lpar */
+               spin_lock_irqsave(&shca_list_lock, flags);
+               if (list_empty(&shca_list)) {
+                       spin_unlock_irqrestore(&shca_list_lock, flags);
+                       return NOTIFY_OK;
+               } else {
+                       spin_unlock_irqrestore(&shca_list_lock, flags);
+                       if (printk_timed_ratelimit(&ehca_dmem_warn_time,
+                                                  30 * 1000))
+                               ehca_gen_err("DMEM operations are not allowed"
+                                            "in conjunction with eHCA");
+                       return NOTIFY_BAD;
+               }
+       }
+       return NOTIFY_OK;
+}
+
+static struct notifier_block ehca_mem_nb = {
+       .notifier_call = ehca_mem_notifier,
+};
+
+static int __init ehca_module_init(void)
+{
+       int ret;
+
+       printk(KERN_INFO "eHCA Infiniband Device Driver "
+              "(Version " HCAD_VERSION ")\n");
+
+       ret = ehca_create_comp_pool();
+       if (ret) {
+               ehca_gen_err("Cannot create comp pool.");
+               return ret;
+       }
+
+       ret = ehca_create_slab_caches();
+       if (ret) {
+               ehca_gen_err("Cannot create SLAB caches");
+               ret = -ENOMEM;
+               goto module_init1;
+       }
+
+       ret = ehca_create_busmap();
+       if (ret) {
+               ehca_gen_err("Cannot create busmap.");
+               goto module_init2;
+       }
+
+       ret = ibmebus_register_driver(&ehca_driver);
+       if (ret) {
+               ehca_gen_err("Cannot register eHCA device driver");
+               ret = -EINVAL;
+               goto module_init3;
+       }
+
+       ret = register_memory_notifier(&ehca_mem_nb);
+       if (ret) {
+               ehca_gen_err("Failed registering memory add/remove notifier");
+               goto module_init4;
+       }
+
+       if (ehca_poll_all_eqs != 1) {
+               ehca_gen_err("WARNING!!!");
+               ehca_gen_err("It is possible to lose interrupts.");
+       } else {
+               init_timer(&poll_eqs_timer);
+               poll_eqs_timer.function = ehca_poll_eqs;
+               poll_eqs_timer.expires = jiffies + HZ;
+               add_timer(&poll_eqs_timer);
+       }
+
+       return 0;
+
+module_init4:
+       ibmebus_unregister_driver(&ehca_driver);
+
+module_init3:
+       ehca_destroy_busmap();
+
+module_init2:
+       ehca_destroy_slab_caches();
+
+module_init1:
+       ehca_destroy_comp_pool();
+       return ret;
+};
+
+static void __exit ehca_module_exit(void)
+{
+       if (ehca_poll_all_eqs == 1)
+               del_timer_sync(&poll_eqs_timer);
+
+       ibmebus_unregister_driver(&ehca_driver);
+
+       unregister_memory_notifier(&ehca_mem_nb);
+
+       ehca_destroy_busmap();
+
+       ehca_destroy_slab_caches();
+
+       ehca_destroy_comp_pool();
+
+       idr_destroy(&ehca_cq_idr);
+       idr_destroy(&ehca_qp_idr);
+};
+
+module_init(ehca_module_init);
+module_exit(ehca_module_exit);
diff --git a/drivers/staging/rdma/ehca/ehca_mcast.c b/drivers/staging/rdma/ehca/ehca_mcast.c
new file mode 100644 (file)
index 0000000..cec1815
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ *  IBM eServer eHCA Infiniband device driver for Linux on POWER
+ *
+ *  mcast  functions
+ *
+ *  Authors: Khadija Souissi <souissik@de.ibm.com>
+ *           Waleri Fomin <fomin@de.ibm.com>
+ *           Reinhard Ernst <rernst@de.ibm.com>
+ *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
+ *           Heiko J Schick <schickhj@de.ibm.com>
+ *
+ *  Copyright (c) 2005 IBM Corporation
+ *
+ *  All rights reserved.
+ *
+ *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
+ *  BSD.
+ *
+ * OpenIB BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include "ehca_classes.h"
+#include "ehca_tools.h"
+#include "ehca_qes.h"
+#include "ehca_iverbs.h"
+#include "hcp_if.h"
+
+#define MAX_MC_LID 0xFFFE
+#define MIN_MC_LID 0xC000      /* Multicast limits */
+#define EHCA_VALID_MULTICAST_GID(gid)  ((gid)[0] == 0xFF)
+#define EHCA_VALID_MULTICAST_LID(lid) \
+       (((lid) >= MIN_MC_LID) && ((lid) <= MAX_MC_LID))
+
+int ehca_attach_mcast(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
+{
+       struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp);
+       struct ehca_shca *shca = container_of(ibqp->device, struct ehca_shca,
+                                             ib_device);
+       union ib_gid my_gid;
+       u64 subnet_prefix, interface_id, h_ret;
+
+       if (ibqp->qp_type != IB_QPT_UD) {
+               ehca_err(ibqp->device, "invalid qp_type=%x", ibqp->qp_type);
+               return -EINVAL;
+       }
+
+       if (!(EHCA_VALID_MULTICAST_GID(gid->raw))) {
+               ehca_err(ibqp->device, "invalid mulitcast gid");
+               return -EINVAL;
+       } else if ((lid < MIN_MC_LID) || (lid > MAX_MC_LID)) {
+               ehca_err(ibqp->device, "invalid mulitcast lid=%x", lid);
+               return -EINVAL;
+       }
+
+       memcpy(&my_gid, gid->raw, sizeof(union ib_gid));
+
+       subnet_prefix = be64_to_cpu(my_gid.global.subnet_prefix);
+       interface_id = be64_to_cpu(my_gid.global.interface_id);
+       h_ret = hipz_h_attach_mcqp(shca->ipz_hca_handle,
+                                  my_qp->ipz_qp_handle,
+                                  my_qp->galpas.kernel,
+                                  lid, subnet_prefix, interface_id);
+       if (h_ret != H_SUCCESS)
+               ehca_err(ibqp->device,
+                        "ehca_qp=%p qp_num=%x hipz_h_attach_mcqp() failed "
+                        "h_ret=%lli", my_qp, ibqp->qp_num, h_ret);
+
+       return ehca2ib_return_code(h_ret);
+}
+
+int ehca_detach_mcast(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
+{
+       struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp);
+       struct ehca_shca *shca = container_of(ibqp->pd->device,
+                                             struct ehca_shca, ib_device);
+       union ib_gid my_gid;
+       u64 subnet_prefix, interface_id, h_ret;
+
+       if (ibqp->qp_type != IB_QPT_UD) {
+               ehca_err(ibqp->device, "invalid qp_type %x", ibqp->qp_type);
+               return -EINVAL;
+       }
+
+       if (!(EHCA_VALID_MULTICAST_GID(gid->raw))) {
+               ehca_err(ibqp->device, "invalid mulitcast gid");
+               return -EINVAL;
+       } else if ((lid < MIN_MC_LID) || (lid > MAX_MC_LID)) {
+               ehca_err(ibqp->device, "invalid mulitcast lid=%x", lid);
+               return -EINVAL;
+       }
+
+       memcpy(&my_gid, gid->raw, sizeof(union ib_gid));
+
+       subnet_prefix = be64_to_cpu(my_gid.global.subnet_prefix);
+       interface_id = be64_to_cpu(my_gid.global.interface_id);
+       h_ret = hipz_h_detach_mcqp(shca->ipz_hca_handle,
+                                  my_qp->ipz_qp_handle,
+                                  my_qp->galpas.kernel,
+                                  lid, subnet_prefix, interface_id);
+       if (h_ret != H_SUCCESS)
+               ehca_err(ibqp->device,
+                        "ehca_qp=%p qp_num=%x hipz_h_detach_mcqp() failed "
+                        "h_ret=%lli", my_qp, ibqp->qp_num, h_ret);
+
+       return ehca2ib_return_code(h_ret);
+}
diff --git a/drivers/staging/rdma/ehca/ehca_mrmw.c b/drivers/staging/rdma/ehca/ehca_mrmw.c
new file mode 100644 (file)
index 0000000..f914b30
--- /dev/null
@@ -0,0 +1,2593 @@
+/*
+ *  IBM eServer eHCA Infiniband device driver for Linux on POWER
+ *
+ *  MR/MW functions
+ *
+ *  Authors: Dietmar Decker <ddecker@de.ibm.com>
+ *           Christoph Raisch <raisch@de.ibm.com>
+ *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
+ *
+ *  Copyright (c) 2005 IBM Corporation
+ *
+ *  All rights reserved.
+ *
+ *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
+ *  BSD.
+ *
+ * OpenIB BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/slab.h>
+#include <rdma/ib_umem.h>
+
+#include "ehca_iverbs.h"
+#include "ehca_mrmw.h"
+#include "hcp_if.h"
+#include "hipz_hw.h"
+
+#define NUM_CHUNKS(length, chunk_size) \
+       (((length) + (chunk_size - 1)) / (chunk_size))
+
+/* max number of rpages (per hcall register_rpages) */
+#define MAX_RPAGES 512
+
+/* DMEM toleration management */
+#define EHCA_SECTSHIFT        SECTION_SIZE_BITS
+#define EHCA_SECTSIZE          (1UL << EHCA_SECTSHIFT)
+#define EHCA_HUGEPAGESHIFT     34
+#define EHCA_HUGEPAGE_SIZE     (1UL << EHCA_HUGEPAGESHIFT)
+#define EHCA_HUGEPAGE_PFN_MASK ((EHCA_HUGEPAGE_SIZE - 1) >> PAGE_SHIFT)
+#define EHCA_INVAL_ADDR        0xFFFFFFFFFFFFFFFFULL
+#define EHCA_DIR_INDEX_SHIFT 13                   /* 8k Entries in 64k block */
+#define EHCA_TOP_INDEX_SHIFT (EHCA_DIR_INDEX_SHIFT * 2)
+#define EHCA_MAP_ENTRIES (1 << EHCA_DIR_INDEX_SHIFT)
+#define EHCA_TOP_MAP_SIZE (0x10000)               /* currently fixed map size */
+#define EHCA_DIR_MAP_SIZE (0x10000)
+#define EHCA_ENT_MAP_SIZE (0x10000)
+#define EHCA_INDEX_MASK (EHCA_MAP_ENTRIES - 1)
+
+static unsigned long ehca_mr_len;
+
+/*
+ * Memory map data structures
+ */
+struct ehca_dir_bmap {
+       u64 ent[EHCA_MAP_ENTRIES];
+};
+struct ehca_top_bmap {
+       struct ehca_dir_bmap *dir[EHCA_MAP_ENTRIES];
+};
+struct ehca_bmap {
+       struct ehca_top_bmap *top[EHCA_MAP_ENTRIES];
+};
+
+static struct ehca_bmap *ehca_bmap;
+
+static struct kmem_cache *mr_cache;
+static struct kmem_cache *mw_cache;
+
+enum ehca_mr_pgsize {
+       EHCA_MR_PGSIZE4K  = 0x1000L,
+       EHCA_MR_PGSIZE64K = 0x10000L,
+       EHCA_MR_PGSIZE1M  = 0x100000L,
+       EHCA_MR_PGSIZE16M = 0x1000000L
+};
+
+#define EHCA_MR_PGSHIFT4K  12
+#define EHCA_MR_PGSHIFT64K 16
+#define EHCA_MR_PGSHIFT1M  20
+#define EHCA_MR_PGSHIFT16M 24
+
+static u64 ehca_map_vaddr(void *caddr);
+
+static u32 ehca_encode_hwpage_size(u32 pgsize)
+{
+       int log = ilog2(pgsize);
+       WARN_ON(log < 12 || log > 24 || log & 3);
+       return (log - 12) / 4;
+}
+
+static u64 ehca_get_max_hwpage_size(struct ehca_shca *shca)
+{
+       return rounddown_pow_of_two(shca->hca_cap_mr_pgsize);
+}
+
+static struct ehca_mr *ehca_mr_new(void)
+{
+       struct ehca_mr *me;
+
+       me = kmem_cache_zalloc(mr_cache, GFP_KERNEL);
+       if (me)
+               spin_lock_init(&me->mrlock);
+       else
+               ehca_gen_err("alloc failed");
+
+       return me;
+}
+
+static void ehca_mr_delete(struct ehca_mr *me)
+{
+       kmem_cache_free(mr_cache, me);
+}
+
+static struct ehca_mw *ehca_mw_new(void)
+{
+       struct ehca_mw *me;
+
+       me = kmem_cache_zalloc(mw_cache, GFP_KERNEL);
+       if (me)
+               spin_lock_init(&me->mwlock);
+       else
+               ehca_gen_err("alloc failed");
+
+       return me;
+}
+
+static void ehca_mw_delete(struct ehca_mw *me)
+{
+       kmem_cache_free(mw_cache, me);
+}
+
+/*----------------------------------------------------------------------*/
+
+struct ib_mr *ehca_get_dma_mr(struct ib_pd *pd, int mr_access_flags)
+{
+       struct ib_mr *ib_mr;
+       int ret;
+       struct ehca_mr *e_maxmr;
+       struct ehca_pd *e_pd = container_of(pd, struct ehca_pd, ib_pd);
+       struct ehca_shca *shca =
+               container_of(pd->device, struct ehca_shca, ib_device);
+
+       if (shca->maxmr) {
+               e_maxmr = ehca_mr_new();
+               if (!e_maxmr) {
+                       ehca_err(&shca->ib_device, "out of memory");
+                       ib_mr = ERR_PTR(-ENOMEM);
+                       goto get_dma_mr_exit0;
+               }
+
+               ret = ehca_reg_maxmr(shca, e_maxmr,
+                                    (void *)ehca_map_vaddr((void *)(KERNELBASE + PHYSICAL_START)),
+                                    mr_access_flags, e_pd,
+                                    &e_maxmr->ib.ib_mr.lkey,
+                                    &e_maxmr->ib.ib_mr.rkey);
+               if (ret) {
+                       ehca_mr_delete(e_maxmr);
+                       ib_mr = ERR_PTR(ret);
+                       goto get_dma_mr_exit0;
+               }
+               ib_mr = &e_maxmr->ib.ib_mr;
+       } else {
+               ehca_err(&shca->ib_device, "no internal max-MR exist!");
+               ib_mr = ERR_PTR(-EINVAL);
+               goto get_dma_mr_exit0;
+       }
+
+get_dma_mr_exit0:
+       if (IS_ERR(ib_mr))
+               ehca_err(&shca->ib_device, "h_ret=%li pd=%p mr_access_flags=%x",
+                        PTR_ERR(ib_mr), pd, mr_access_flags);
+       return ib_mr;
+} /* end ehca_get_dma_mr() */
+
+/*----------------------------------------------------------------------*/
+
+struct ib_mr *ehca_reg_phys_mr(struct ib_pd *pd,
+                              struct ib_phys_buf *phys_buf_array,
+                              int num_phys_buf,
+                              int mr_access_flags,
+                              u64 *iova_start)
+{
+       struct ib_mr *ib_mr;
+       int ret;
+       struct ehca_mr *e_mr;
+       struct ehca_shca *shca =
+               container_of(pd->device, struct ehca_shca, ib_device);
+       struct ehca_pd *e_pd = container_of(pd, struct ehca_pd, ib_pd);
+
+       u64 size;
+
+       if ((num_phys_buf <= 0) || !phys_buf_array) {
+               ehca_err(pd->device, "bad input values: num_phys_buf=%x "
+                        "phys_buf_array=%p", num_phys_buf, phys_buf_array);
+               ib_mr = ERR_PTR(-EINVAL);
+               goto reg_phys_mr_exit0;
+       }
+       if (((mr_access_flags & IB_ACCESS_REMOTE_WRITE) &&
+            !(mr_access_flags & IB_ACCESS_LOCAL_WRITE)) ||
+           ((mr_access_flags & IB_ACCESS_REMOTE_ATOMIC) &&
+            !(mr_access_flags & IB_ACCESS_LOCAL_WRITE))) {
+               /*
+                * Remote Write Access requires Local Write Access
+                * Remote Atomic Access requires Local Write Access
+                */
+               ehca_err(pd->device, "bad input values: mr_access_flags=%x",
+                        mr_access_flags);
+               ib_mr = ERR_PTR(-EINVAL);
+               goto reg_phys_mr_exit0;
+       }
+
+       /* check physical buffer list and calculate size */
+       ret = ehca_mr_chk_buf_and_calc_size(phys_buf_array, num_phys_buf,
+                                           iova_start, &size);
+       if (ret) {
+               ib_mr = ERR_PTR(ret);
+               goto reg_phys_mr_exit0;
+       }
+       if ((size == 0) ||
+           (((u64)iova_start + size) < (u64)iova_start)) {
+               ehca_err(pd->device, "bad input values: size=%llx iova_start=%p",
+                        size, iova_start);
+               ib_mr = ERR_PTR(-EINVAL);
+               goto reg_phys_mr_exit0;
+       }
+
+       e_mr = ehca_mr_new();
+       if (!e_mr) {
+               ehca_err(pd->device, "out of memory");
+               ib_mr = ERR_PTR(-ENOMEM);
+               goto reg_phys_mr_exit0;
+       }
+
+       /* register MR on HCA */
+       if (ehca_mr_is_maxmr(size, iova_start)) {
+               e_mr->flags |= EHCA_MR_FLAG_MAXMR;
+               ret = ehca_reg_maxmr(shca, e_mr, iova_start, mr_access_flags,
+                                    e_pd, &e_mr->ib.ib_mr.lkey,
+                                    &e_mr->ib.ib_mr.rkey);
+               if (ret) {
+                       ib_mr = ERR_PTR(ret);
+                       goto reg_phys_mr_exit1;
+               }
+       } else {
+               struct ehca_mr_pginfo pginfo;
+               u32 num_kpages;
+               u32 num_hwpages;
+               u64 hw_pgsize;
+
+               num_kpages = NUM_CHUNKS(((u64)iova_start % PAGE_SIZE) + size,
+                                       PAGE_SIZE);
+               /* for kernel space we try most possible pgsize */
+               hw_pgsize = ehca_get_max_hwpage_size(shca);
+               num_hwpages = NUM_CHUNKS(((u64)iova_start % hw_pgsize) + size,
+                                        hw_pgsize);
+               memset(&pginfo, 0, sizeof(pginfo));
+               pginfo.type = EHCA_MR_PGI_PHYS;
+               pginfo.num_kpages = num_kpages;
+               pginfo.hwpage_size = hw_pgsize;
+               pginfo.num_hwpages = num_hwpages;
+               pginfo.u.phy.num_phys_buf = num_phys_buf;
+               pginfo.u.phy.phys_buf_array = phys_buf_array;
+               pginfo.next_hwpage =
+                       ((u64)iova_start & ~PAGE_MASK) / hw_pgsize;
+
+               ret = ehca_reg_mr(shca, e_mr, iova_start, size, mr_access_flags,
+                                 e_pd, &pginfo, &e_mr->ib.ib_mr.lkey,
+                                 &e_mr->ib.ib_mr.rkey, EHCA_REG_MR);
+               if (ret) {
+                       ib_mr = ERR_PTR(ret);
+                       goto reg_phys_mr_exit1;
+               }
+       }
+
+       /* successful registration of all pages */
+       return &e_mr->ib.ib_mr;
+
+reg_phys_mr_exit1:
+       ehca_mr_delete(e_mr);
+reg_phys_mr_exit0:
+       if (IS_ERR(ib_mr))
+               ehca_err(pd->device, "h_ret=%li pd=%p phys_buf_array=%p "
+                        "num_phys_buf=%x mr_access_flags=%x iova_start=%p",
+                        PTR_ERR(ib_mr), pd, phys_buf_array,
+                        num_phys_buf, mr_access_flags, iova_start);
+       return ib_mr;
+} /* end ehca_reg_phys_mr() */
+
+/*----------------------------------------------------------------------*/
+
+struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
+                              u64 virt, int mr_access_flags,
+                              struct ib_udata *udata)
+{
+       struct ib_mr *ib_mr;
+       struct ehca_mr *e_mr;
+       struct ehca_shca *shca =
+               container_of(pd->device, struct ehca_shca, ib_device);
+       struct ehca_pd *e_pd = container_of(pd, struct ehca_pd, ib_pd);
+       struct ehca_mr_pginfo pginfo;
+       int ret, page_shift;
+       u32 num_kpages;
+       u32 num_hwpages;
+       u64 hwpage_size;
+
+       if (!pd) {
+               ehca_gen_err("bad pd=%p", pd);
+               return ERR_PTR(-EFAULT);
+       }
+
+       if (((mr_access_flags & IB_ACCESS_REMOTE_WRITE) &&
+            !(mr_access_flags & IB_ACCESS_LOCAL_WRITE)) ||
+           ((mr_access_flags & IB_ACCESS_REMOTE_ATOMIC) &&
+            !(mr_access_flags & IB_ACCESS_LOCAL_WRITE))) {
+               /*
+                * Remote Write Access requires Local Write Access
+                * Remote Atomic Access requires Local Write Access
+                */
+               ehca_err(pd->device, "bad input values: mr_access_flags=%x",
+                        mr_access_flags);
+               ib_mr = ERR_PTR(-EINVAL);
+               goto reg_user_mr_exit0;
+       }
+
+       if (length == 0 || virt + length < virt) {
+               ehca_err(pd->device, "bad input values: length=%llx "
+                        "virt_base=%llx", length, virt);
+               ib_mr = ERR_PTR(-EINVAL);
+               goto reg_user_mr_exit0;
+       }
+
+       e_mr = ehca_mr_new();
+       if (!e_mr) {
+               ehca_err(pd->device, "out of memory");
+               ib_mr = ERR_PTR(-ENOMEM);
+               goto reg_user_mr_exit0;
+       }
+
+       e_mr->umem = ib_umem_get(pd->uobject->context, start, length,
+                                mr_access_flags, 0);
+       if (IS_ERR(e_mr->umem)) {
+               ib_mr = (void *)e_mr->umem;
+               goto reg_user_mr_exit1;
+       }
+
+       if (e_mr->umem->page_size != PAGE_SIZE) {
+               ehca_err(pd->device, "page size not supported, "
+                        "e_mr->umem->page_size=%x", e_mr->umem->page_size);
+               ib_mr = ERR_PTR(-EINVAL);
+               goto reg_user_mr_exit2;
+       }
+
+       /* determine number of MR pages */
+       num_kpages = NUM_CHUNKS((virt % PAGE_SIZE) + length, PAGE_SIZE);
+       /* select proper hw_pgsize */
+       page_shift = PAGE_SHIFT;
+       if (e_mr->umem->hugetlb) {
+               /* determine page_shift, clamp between 4K and 16M */
+               page_shift = (fls64(length - 1) + 3) & ~3;
+               page_shift = min(max(page_shift, EHCA_MR_PGSHIFT4K),
+                                EHCA_MR_PGSHIFT16M);
+       }
+       hwpage_size = 1UL << page_shift;
+
+       /* now that we have the desired page size, shift until it's
+        * supported, too. 4K is always supported, so this terminates.
+        */
+       while (!(hwpage_size & shca->hca_cap_mr_pgsize))
+               hwpage_size >>= 4;
+
+reg_user_mr_fallback:
+       num_hwpages = NUM_CHUNKS((virt % hwpage_size) + length, hwpage_size);
+       /* register MR on HCA */
+       memset(&pginfo, 0, sizeof(pginfo));
+       pginfo.type = EHCA_MR_PGI_USER;
+       pginfo.hwpage_size = hwpage_size;
+       pginfo.num_kpages = num_kpages;
+       pginfo.num_hwpages = num_hwpages;
+       pginfo.u.usr.region = e_mr->umem;
+       pginfo.next_hwpage = ib_umem_offset(e_mr->umem) / hwpage_size;
+       pginfo.u.usr.next_sg = pginfo.u.usr.region->sg_head.sgl;
+       ret = ehca_reg_mr(shca, e_mr, (u64 *)virt, length, mr_access_flags,
+                         e_pd, &pginfo, &e_mr->ib.ib_mr.lkey,
+                         &e_mr->ib.ib_mr.rkey, EHCA_REG_MR);
+       if (ret == -EINVAL && pginfo.hwpage_size > PAGE_SIZE) {
+               ehca_warn(pd->device, "failed to register mr "
+                         "with hwpage_size=%llx", hwpage_size);
+               ehca_info(pd->device, "try to register mr with "
+                         "kpage_size=%lx", PAGE_SIZE);
+               /*
+                * this means kpages are not contiguous for a hw page
+                * try kernel page size as fallback solution
+                */
+               hwpage_size = PAGE_SIZE;
+               goto reg_user_mr_fallback;
+       }
+       if (ret) {
+               ib_mr = ERR_PTR(ret);
+               goto reg_user_mr_exit2;
+       }
+
+       /* successful registration of all pages */
+       return &e_mr->ib.ib_mr;
+
+reg_user_mr_exit2:
+       ib_umem_release(e_mr->umem);
+reg_user_mr_exit1:
+       ehca_mr_delete(e_mr);
+reg_user_mr_exit0:
+       if (IS_ERR(ib_mr))
+               ehca_err(pd->device, "rc=%li pd=%p mr_access_flags=%x udata=%p",
+                        PTR_ERR(ib_mr), pd, mr_access_flags, udata);
+       return ib_mr;
+} /* end ehca_reg_user_mr() */
+
+/*----------------------------------------------------------------------*/
+
+int ehca_rereg_phys_mr(struct ib_mr *mr,
+                      int mr_rereg_mask,
+                      struct ib_pd *pd,
+                      struct ib_phys_buf *phys_buf_array,
+                      int num_phys_buf,
+                      int mr_access_flags,
+                      u64 *iova_start)
+{
+       int ret;
+
+       struct ehca_shca *shca =
+               container_of(mr->device, struct ehca_shca, ib_device);
+       struct ehca_mr *e_mr = container_of(mr, struct ehca_mr, ib.ib_mr);
+       u64 new_size;
+       u64 *new_start;
+       u32 new_acl;
+       struct ehca_pd *new_pd;
+       u32 tmp_lkey, tmp_rkey;
+       unsigned long sl_flags;
+       u32 num_kpages = 0;
+       u32 num_hwpages = 0;
+       struct ehca_mr_pginfo pginfo;
+
+       if (!(mr_rereg_mask & IB_MR_REREG_TRANS)) {
+               /* TODO not supported, because PHYP rereg hCall needs pages */
+               ehca_err(mr->device, "rereg without IB_MR_REREG_TRANS not "
+                        "supported yet, mr_rereg_mask=%x", mr_rereg_mask);
+               ret = -EINVAL;
+               goto rereg_phys_mr_exit0;
+       }
+
+       if (mr_rereg_mask & IB_MR_REREG_PD) {
+               if (!pd) {
+                       ehca_err(mr->device, "rereg with bad pd, pd=%p "
+                                "mr_rereg_mask=%x", pd, mr_rereg_mask);
+                       ret = -EINVAL;
+                       goto rereg_phys_mr_exit0;
+               }
+       }
+
+       if ((mr_rereg_mask &
+            ~(IB_MR_REREG_TRANS | IB_MR_REREG_PD | IB_MR_REREG_ACCESS)) ||
+           (mr_rereg_mask == 0)) {
+               ret = -EINVAL;
+               goto rereg_phys_mr_exit0;
+       }
+
+       /* check other parameters */
+       if (e_mr == shca->maxmr) {
+               /* should be impossible, however reject to be sure */
+               ehca_err(mr->device, "rereg internal max-MR impossible, mr=%p "
+                        "shca->maxmr=%p mr->lkey=%x",
+                        mr, shca->maxmr, mr->lkey);
+               ret = -EINVAL;
+               goto rereg_phys_mr_exit0;
+       }
+       if (mr_rereg_mask & IB_MR_REREG_TRANS) { /* transl., i.e. addr/size */
+               if (e_mr->flags & EHCA_MR_FLAG_FMR) {
+                       ehca_err(mr->device, "not supported for FMR, mr=%p "
+                                "flags=%x", mr, e_mr->flags);
+                       ret = -EINVAL;
+                       goto rereg_phys_mr_exit0;
+               }
+               if (!phys_buf_array || num_phys_buf <= 0) {
+                       ehca_err(mr->device, "bad input values mr_rereg_mask=%x"
+                                " phys_buf_array=%p num_phys_buf=%x",
+                                mr_rereg_mask, phys_buf_array, num_phys_buf);
+                       ret = -EINVAL;
+                       goto rereg_phys_mr_exit0;
+               }
+       }
+       if ((mr_rereg_mask & IB_MR_REREG_ACCESS) &&     /* change ACL */
+           (((mr_access_flags & IB_ACCESS_REMOTE_WRITE) &&
+             !(mr_access_flags & IB_ACCESS_LOCAL_WRITE)) ||
+            ((mr_access_flags & IB_ACCESS_REMOTE_ATOMIC) &&
+             !(mr_access_flags & IB_ACCESS_LOCAL_WRITE)))) {
+               /*
+                * Remote Write Access requires Local Write Access
+                * Remote Atomic Access requires Local Write Access
+                */
+               ehca_err(mr->device, "bad input values: mr_rereg_mask=%x "
+                        "mr_access_flags=%x", mr_rereg_mask, mr_access_flags);
+               ret = -EINVAL;
+               goto rereg_phys_mr_exit0;
+       }
+
+       /* set requested values dependent on rereg request */
+       spin_lock_irqsave(&e_mr->mrlock, sl_flags);
+       new_start = e_mr->start;
+       new_size = e_mr->size;
+       new_acl = e_mr->acl;
+       new_pd = container_of(mr->pd, struct ehca_pd, ib_pd);
+
+       if (mr_rereg_mask & IB_MR_REREG_TRANS) {
+               u64 hw_pgsize = ehca_get_max_hwpage_size(shca);
+
+               new_start = iova_start; /* change address */
+               /* check physical buffer list and calculate size */
+               ret = ehca_mr_chk_buf_and_calc_size(phys_buf_array,
+                                                   num_phys_buf, iova_start,
+                                                   &new_size);
+               if (ret)
+                       goto rereg_phys_mr_exit1;
+               if ((new_size == 0) ||
+                   (((u64)iova_start + new_size) < (u64)iova_start)) {
+                       ehca_err(mr->device, "bad input values: new_size=%llx "
+                                "iova_start=%p", new_size, iova_start);
+                       ret = -EINVAL;
+                       goto rereg_phys_mr_exit1;
+               }
+               num_kpages = NUM_CHUNKS(((u64)new_start % PAGE_SIZE) +
+                                       new_size, PAGE_SIZE);
+               num_hwpages = NUM_CHUNKS(((u64)new_start % hw_pgsize) +
+                                        new_size, hw_pgsize);
+               memset(&pginfo, 0, sizeof(pginfo));
+               pginfo.type = EHCA_MR_PGI_PHYS;
+               pginfo.num_kpages = num_kpages;
+               pginfo.hwpage_size = hw_pgsize;
+               pginfo.num_hwpages = num_hwpages;
+               pginfo.u.phy.num_phys_buf = num_phys_buf;
+               pginfo.u.phy.phys_buf_array = phys_buf_array;
+               pginfo.next_hwpage =
+                       ((u64)iova_start & ~PAGE_MASK) / hw_pgsize;
+       }
+       if (mr_rereg_mask & IB_MR_REREG_ACCESS)
+               new_acl = mr_access_flags;
+       if (mr_rereg_mask & IB_MR_REREG_PD)
+               new_pd = container_of(pd, struct ehca_pd, ib_pd);
+
+       ret = ehca_rereg_mr(shca, e_mr, new_start, new_size, new_acl,
+                           new_pd, &pginfo, &tmp_lkey, &tmp_rkey);
+       if (ret)
+               goto rereg_phys_mr_exit1;
+
+       /* successful reregistration */
+       if (mr_rereg_mask & IB_MR_REREG_PD)
+               mr->pd = pd;
+       mr->lkey = tmp_lkey;
+       mr->rkey = tmp_rkey;
+
+rereg_phys_mr_exit1:
+       spin_unlock_irqrestore(&e_mr->mrlock, sl_flags);
+rereg_phys_mr_exit0:
+       if (ret)
+               ehca_err(mr->device, "ret=%i mr=%p mr_rereg_mask=%x pd=%p "
+                        "phys_buf_array=%p num_phys_buf=%x mr_access_flags=%x "
+                        "iova_start=%p",
+                        ret, mr, mr_rereg_mask, pd, phys_buf_array,
+                        num_phys_buf, mr_access_flags, iova_start);
+       return ret;
+} /* end ehca_rereg_phys_mr() */
+
+/*----------------------------------------------------------------------*/
+
+int ehca_query_mr(struct ib_mr *mr, struct ib_mr_attr *mr_attr)
+{
+       int ret = 0;
+       u64 h_ret;
+       struct ehca_shca *shca =
+               container_of(mr->device, struct ehca_shca, ib_device);
+       struct ehca_mr *e_mr = container_of(mr, struct ehca_mr, ib.ib_mr);
+       unsigned long sl_flags;
+       struct ehca_mr_hipzout_parms hipzout;
+
+       if ((e_mr->flags & EHCA_MR_FLAG_FMR)) {
+               ehca_err(mr->device, "not supported for FMR, mr=%p e_mr=%p "
+                        "e_mr->flags=%x", mr, e_mr, e_mr->flags);
+               ret = -EINVAL;
+               goto query_mr_exit0;
+       }
+
+       memset(mr_attr, 0, sizeof(struct ib_mr_attr));
+       spin_lock_irqsave(&e_mr->mrlock, sl_flags);
+
+       h_ret = hipz_h_query_mr(shca->ipz_hca_handle, e_mr, &hipzout);
+       if (h_ret != H_SUCCESS) {
+               ehca_err(mr->device, "hipz_mr_query failed, h_ret=%lli mr=%p "
+                        "hca_hndl=%llx mr_hndl=%llx lkey=%x",
+                        h_ret, mr, shca->ipz_hca_handle.handle,
+                        e_mr->ipz_mr_handle.handle, mr->lkey);
+               ret = ehca2ib_return_code(h_ret);
+               goto query_mr_exit1;
+       }
+       mr_attr->pd = mr->pd;
+       mr_attr->device_virt_addr = hipzout.vaddr;
+       mr_attr->size = hipzout.len;
+       mr_attr->lkey = hipzout.lkey;
+       mr_attr->rkey = hipzout.rkey;
+       ehca_mrmw_reverse_map_acl(&hipzout.acl, &mr_attr->mr_access_flags);
+
+query_mr_exit1:
+       spin_unlock_irqrestore(&e_mr->mrlock, sl_flags);
+query_mr_exit0:
+       if (ret)
+               ehca_err(mr->device, "ret=%i mr=%p mr_attr=%p",
+                        ret, mr, mr_attr);
+       return ret;
+} /* end ehca_query_mr() */
+
+/*----------------------------------------------------------------------*/
+
+int ehca_dereg_mr(struct ib_mr *mr)
+{
+       int ret = 0;
+       u64 h_ret;
+       struct ehca_shca *shca =
+               container_of(mr->device, struct ehca_shca, ib_device);
+       struct ehca_mr *e_mr = container_of(mr, struct ehca_mr, ib.ib_mr);
+
+       if ((e_mr->flags & EHCA_MR_FLAG_FMR)) {
+               ehca_err(mr->device, "not supported for FMR, mr=%p e_mr=%p "
+                        "e_mr->flags=%x", mr, e_mr, e_mr->flags);
+               ret = -EINVAL;
+               goto dereg_mr_exit0;
+       } else if (e_mr == shca->maxmr) {
+               /* should be impossible, however reject to be sure */
+               ehca_err(mr->device, "dereg internal max-MR impossible, mr=%p "
+                        "shca->maxmr=%p mr->lkey=%x",
+                        mr, shca->maxmr, mr->lkey);
+               ret = -EINVAL;
+               goto dereg_mr_exit0;
+       }
+
+       /* TODO: BUSY: MR still has bound window(s) */
+       h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_mr);
+       if (h_ret != H_SUCCESS) {
+               ehca_err(mr->device, "hipz_free_mr failed, h_ret=%lli shca=%p "
+                        "e_mr=%p hca_hndl=%llx mr_hndl=%llx mr->lkey=%x",
+                        h_ret, shca, e_mr, shca->ipz_hca_handle.handle,
+                        e_mr->ipz_mr_handle.handle, mr->lkey);
+               ret = ehca2ib_return_code(h_ret);
+               goto dereg_mr_exit0;
+       }
+
+       if (e_mr->umem)
+               ib_umem_release(e_mr->umem);
+
+       /* successful deregistration */
+       ehca_mr_delete(e_mr);
+
+dereg_mr_exit0:
+       if (ret)
+               ehca_err(mr->device, "ret=%i mr=%p", ret, mr);
+       return ret;
+} /* end ehca_dereg_mr() */
+
+/*----------------------------------------------------------------------*/
+
+struct ib_mw *ehca_alloc_mw(struct ib_pd *pd, enum ib_mw_type type)
+{
+       struct ib_mw *ib_mw;
+       u64 h_ret;
+       struct ehca_mw *e_mw;
+       struct ehca_pd *e_pd = container_of(pd, struct ehca_pd, ib_pd);
+       struct ehca_shca *shca =
+               container_of(pd->device, struct ehca_shca, ib_device);
+       struct ehca_mw_hipzout_parms hipzout;
+
+       if (type != IB_MW_TYPE_1)
+               return ERR_PTR(-EINVAL);
+
+       e_mw = ehca_mw_new();
+       if (!e_mw) {
+               ib_mw = ERR_PTR(-ENOMEM);
+               goto alloc_mw_exit0;
+       }
+
+       h_ret = hipz_h_alloc_resource_mw(shca->ipz_hca_handle, e_mw,
+                                        e_pd->fw_pd, &hipzout);
+       if (h_ret != H_SUCCESS) {
+               ehca_err(pd->device, "hipz_mw_allocate failed, h_ret=%lli "
+                        "shca=%p hca_hndl=%llx mw=%p",
+                        h_ret, shca, shca->ipz_hca_handle.handle, e_mw);
+               ib_mw = ERR_PTR(ehca2ib_return_code(h_ret));
+               goto alloc_mw_exit1;
+       }
+       /* successful MW allocation */
+       e_mw->ipz_mw_handle = hipzout.handle;
+       e_mw->ib_mw.rkey    = hipzout.rkey;
+       return &e_mw->ib_mw;
+
+alloc_mw_exit1:
+       ehca_mw_delete(e_mw);
+alloc_mw_exit0:
+       if (IS_ERR(ib_mw))
+               ehca_err(pd->device, "h_ret=%li pd=%p", PTR_ERR(ib_mw), pd);
+       return ib_mw;
+} /* end ehca_alloc_mw() */
+
+/*----------------------------------------------------------------------*/
+
+int ehca_bind_mw(struct ib_qp *qp,
+                struct ib_mw *mw,
+                struct ib_mw_bind *mw_bind)
+{
+       /* TODO: not supported up to now */
+       ehca_gen_err("bind MW currently not supported by HCAD");
+
+       return -EPERM;
+} /* end ehca_bind_mw() */
+
+/*----------------------------------------------------------------------*/
+
+int ehca_dealloc_mw(struct ib_mw *mw)
+{
+       u64 h_ret;
+       struct ehca_shca *shca =
+               container_of(mw->device, struct ehca_shca, ib_device);
+       struct ehca_mw *e_mw = container_of(mw, struct ehca_mw, ib_mw);
+
+       h_ret = hipz_h_free_resource_mw(shca->ipz_hca_handle, e_mw);
+       if (h_ret != H_SUCCESS) {
+               ehca_err(mw->device, "hipz_free_mw failed, h_ret=%lli shca=%p "
+                        "mw=%p rkey=%x hca_hndl=%llx mw_hndl=%llx",
+                        h_ret, shca, mw, mw->rkey, shca->ipz_hca_handle.handle,
+                        e_mw->ipz_mw_handle.handle);
+               return ehca2ib_return_code(h_ret);
+       }
+       /* successful deallocation */
+       ehca_mw_delete(e_mw);
+       return 0;
+} /* end ehca_dealloc_mw() */
+
+/*----------------------------------------------------------------------*/
+
+struct ib_fmr *ehca_alloc_fmr(struct ib_pd *pd,
+                             int mr_access_flags,
+                             struct ib_fmr_attr *fmr_attr)
+{
+       struct ib_fmr *ib_fmr;
+       struct ehca_shca *shca =
+               container_of(pd->device, struct ehca_shca, ib_device);
+       struct ehca_pd *e_pd = container_of(pd, struct ehca_pd, ib_pd);
+       struct ehca_mr *e_fmr;
+       int ret;
+       u32 tmp_lkey, tmp_rkey;
+       struct ehca_mr_pginfo pginfo;
+       u64 hw_pgsize;
+
+       /* check other parameters */
+       if (((mr_access_flags & IB_ACCESS_REMOTE_WRITE) &&
+            !(mr_access_flags & IB_ACCESS_LOCAL_WRITE)) ||
+           ((mr_access_flags & IB_ACCESS_REMOTE_ATOMIC) &&
+            !(mr_access_flags & IB_ACCESS_LOCAL_WRITE))) {
+               /*
+                * Remote Write Access requires Local Write Access
+                * Remote Atomic Access requires Local Write Access
+                */
+               ehca_err(pd->device, "bad input values: mr_access_flags=%x",
+                        mr_access_flags);
+               ib_fmr = ERR_PTR(-EINVAL);
+               goto alloc_fmr_exit0;
+       }
+       if (mr_access_flags & IB_ACCESS_MW_BIND) {
+               ehca_err(pd->device, "bad input values: mr_access_flags=%x",
+                        mr_access_flags);
+               ib_fmr = ERR_PTR(-EINVAL);
+               goto alloc_fmr_exit0;
+       }
+       if ((fmr_attr->max_pages == 0) || (fmr_attr->max_maps == 0)) {
+               ehca_err(pd->device, "bad input values: fmr_attr->max_pages=%x "
+                        "fmr_attr->max_maps=%x fmr_attr->page_shift=%x",
+                        fmr_attr->max_pages, fmr_attr->max_maps,
+                        fmr_attr->page_shift);
+               ib_fmr = ERR_PTR(-EINVAL);
+               goto alloc_fmr_exit0;
+       }
+
+       hw_pgsize = 1 << fmr_attr->page_shift;
+       if (!(hw_pgsize & shca->hca_cap_mr_pgsize)) {
+               ehca_err(pd->device, "unsupported fmr_attr->page_shift=%x",
+                        fmr_attr->page_shift);
+               ib_fmr = ERR_PTR(-EINVAL);
+               goto alloc_fmr_exit0;
+       }
+
+       e_fmr = ehca_mr_new();
+       if (!e_fmr) {
+               ib_fmr = ERR_PTR(-ENOMEM);
+               goto alloc_fmr_exit0;
+       }
+       e_fmr->flags |= EHCA_MR_FLAG_FMR;
+
+       /* register MR on HCA */
+       memset(&pginfo, 0, sizeof(pginfo));
+       pginfo.hwpage_size = hw_pgsize;
+       /*
+        * pginfo.num_hwpages==0, ie register_rpages() will not be called
+        * but deferred to map_phys_fmr()
+        */
+       ret = ehca_reg_mr(shca, e_fmr, NULL,
+                         fmr_attr->max_pages * (1 << fmr_attr->page_shift),
+                         mr_access_flags, e_pd, &pginfo,
+                         &tmp_lkey, &tmp_rkey, EHCA_REG_MR);
+       if (ret) {
+               ib_fmr = ERR_PTR(ret);
+               goto alloc_fmr_exit1;
+       }
+
+       /* successful */
+       e_fmr->hwpage_size = hw_pgsize;
+       e_fmr->fmr_page_size = 1 << fmr_attr->page_shift;
+       e_fmr->fmr_max_pages = fmr_attr->max_pages;
+       e_fmr->fmr_max_maps = fmr_attr->max_maps;
+       e_fmr->fmr_map_cnt = 0;
+       return &e_fmr->ib.ib_fmr;
+
+alloc_fmr_exit1:
+       ehca_mr_delete(e_fmr);
+alloc_fmr_exit0:
+       return ib_fmr;
+} /* end ehca_alloc_fmr() */
+
+/*----------------------------------------------------------------------*/
+
+int ehca_map_phys_fmr(struct ib_fmr *fmr,
+                     u64 *page_list,
+                     int list_len,
+                     u64 iova)
+{
+       int ret;
+       struct ehca_shca *shca =
+               container_of(fmr->device, struct ehca_shca, ib_device);
+       struct ehca_mr *e_fmr = container_of(fmr, struct ehca_mr, ib.ib_fmr);
+       struct ehca_pd *e_pd = container_of(fmr->pd, struct ehca_pd, ib_pd);
+       struct ehca_mr_pginfo pginfo;
+       u32 tmp_lkey, tmp_rkey;
+
+       if (!(e_fmr->flags & EHCA_MR_FLAG_FMR)) {
+               ehca_err(fmr->device, "not a FMR, e_fmr=%p e_fmr->flags=%x",
+                        e_fmr, e_fmr->flags);
+               ret = -EINVAL;
+               goto map_phys_fmr_exit0;
+       }
+       ret = ehca_fmr_check_page_list(e_fmr, page_list, list_len);
+       if (ret)
+               goto map_phys_fmr_exit0;
+       if (iova % e_fmr->fmr_page_size) {
+               /* only whole-numbered pages */
+               ehca_err(fmr->device, "bad iova, iova=%llx fmr_page_size=%x",
+                        iova, e_fmr->fmr_page_size);
+               ret = -EINVAL;
+               goto map_phys_fmr_exit0;
+       }
+       if (e_fmr->fmr_map_cnt >= e_fmr->fmr_max_maps) {
+               /* HCAD does not limit the maps, however trace this anyway */
+               ehca_info(fmr->device, "map limit exceeded, fmr=%p "
+                         "e_fmr->fmr_map_cnt=%x e_fmr->fmr_max_maps=%x",
+                         fmr, e_fmr->fmr_map_cnt, e_fmr->fmr_max_maps);
+       }
+
+       memset(&pginfo, 0, sizeof(pginfo));
+       pginfo.type = EHCA_MR_PGI_FMR;
+       pginfo.num_kpages = list_len;
+       pginfo.hwpage_size = e_fmr->hwpage_size;
+       pginfo.num_hwpages =
+               list_len * e_fmr->fmr_page_size / pginfo.hwpage_size;
+       pginfo.u.fmr.page_list = page_list;
+       pginfo.next_hwpage =
+               (iova & (e_fmr->fmr_page_size-1)) / pginfo.hwpage_size;
+       pginfo.u.fmr.fmr_pgsize = e_fmr->fmr_page_size;
+
+       ret = ehca_rereg_mr(shca, e_fmr, (u64 *)iova,
+                           list_len * e_fmr->fmr_page_size,
+                           e_fmr->acl, e_pd, &pginfo, &tmp_lkey, &tmp_rkey);
+       if (ret)
+               goto map_phys_fmr_exit0;
+
+       /* successful reregistration */
+       e_fmr->fmr_map_cnt++;
+       e_fmr->ib.ib_fmr.lkey = tmp_lkey;
+       e_fmr->ib.ib_fmr.rkey = tmp_rkey;
+       return 0;
+
+map_phys_fmr_exit0:
+       if (ret)
+               ehca_err(fmr->device, "ret=%i fmr=%p page_list=%p list_len=%x "
+                        "iova=%llx", ret, fmr, page_list, list_len, iova);
+       return ret;
+} /* end ehca_map_phys_fmr() */
+
+/*----------------------------------------------------------------------*/
+
+int ehca_unmap_fmr(struct list_head *fmr_list)
+{
+       int ret = 0;
+       struct ib_fmr *ib_fmr;
+       struct ehca_shca *shca = NULL;
+       struct ehca_shca *prev_shca;
+       struct ehca_mr *e_fmr;
+       u32 num_fmr = 0;
+       u32 unmap_fmr_cnt = 0;
+
+       /* check all FMR belong to same SHCA, and check internal flag */
+       list_for_each_entry(ib_fmr, fmr_list, list) {
+               prev_shca = shca;
+               shca = container_of(ib_fmr->device, struct ehca_shca,
+                                   ib_device);
+               e_fmr = container_of(ib_fmr, struct ehca_mr, ib.ib_fmr);
+               if ((shca != prev_shca) && prev_shca) {
+                       ehca_err(&shca->ib_device, "SHCA mismatch, shca=%p "
+                                "prev_shca=%p e_fmr=%p",
+                                shca, prev_shca, e_fmr);
+                       ret = -EINVAL;
+                       goto unmap_fmr_exit0;
+               }
+               if (!(e_fmr->flags & EHCA_MR_FLAG_FMR)) {
+                       ehca_err(&shca->ib_device, "not a FMR, e_fmr=%p "
+                                "e_fmr->flags=%x", e_fmr, e_fmr->flags);
+                       ret = -EINVAL;
+                       goto unmap_fmr_exit0;
+               }
+               num_fmr++;
+       }
+
+       /* loop over all FMRs to unmap */
+       list_for_each_entry(ib_fmr, fmr_list, list) {
+               unmap_fmr_cnt++;
+               e_fmr = container_of(ib_fmr, struct ehca_mr, ib.ib_fmr);
+               shca = container_of(ib_fmr->device, struct ehca_shca,
+                                   ib_device);
+               ret = ehca_unmap_one_fmr(shca, e_fmr);
+               if (ret) {
+                       /* unmap failed, stop unmapping of rest of FMRs */
+                       ehca_err(&shca->ib_device, "unmap of one FMR failed, "
+                                "stop rest, e_fmr=%p num_fmr=%x "
+                                "unmap_fmr_cnt=%x lkey=%x", e_fmr, num_fmr,
+                                unmap_fmr_cnt, e_fmr->ib.ib_fmr.lkey);
+                       goto unmap_fmr_exit0;
+               }
+       }
+
+unmap_fmr_exit0:
+       if (ret)
+               ehca_gen_err("ret=%i fmr_list=%p num_fmr=%x unmap_fmr_cnt=%x",
+                            ret, fmr_list, num_fmr, unmap_fmr_cnt);
+       return ret;
+} /* end ehca_unmap_fmr() */
+
+/*----------------------------------------------------------------------*/
+
+int ehca_dealloc_fmr(struct ib_fmr *fmr)
+{
+       int ret;
+       u64 h_ret;
+       struct ehca_shca *shca =
+               container_of(fmr->device, struct ehca_shca, ib_device);
+       struct ehca_mr *e_fmr = container_of(fmr, struct ehca_mr, ib.ib_fmr);
+
+       if (!(e_fmr->flags & EHCA_MR_FLAG_FMR)) {
+               ehca_err(fmr->device, "not a FMR, e_fmr=%p e_fmr->flags=%x",
+                        e_fmr, e_fmr->flags);
+               ret = -EINVAL;
+               goto free_fmr_exit0;
+       }
+
+       h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_fmr);
+       if (h_ret != H_SUCCESS) {
+               ehca_err(fmr->device, "hipz_free_mr failed, h_ret=%lli e_fmr=%p "
+                        "hca_hndl=%llx fmr_hndl=%llx fmr->lkey=%x",
+                        h_ret, e_fmr, shca->ipz_hca_handle.handle,
+                        e_fmr->ipz_mr_handle.handle, fmr->lkey);
+               ret = ehca2ib_return_code(h_ret);
+               goto free_fmr_exit0;
+       }
+       /* successful deregistration */
+       ehca_mr_delete(e_fmr);
+       return 0;
+
+free_fmr_exit0:
+       if (ret)
+               ehca_err(&shca->ib_device, "ret=%i fmr=%p", ret, fmr);
+       return ret;
+} /* end ehca_dealloc_fmr() */
+
+/*----------------------------------------------------------------------*/
+
+static int ehca_reg_bmap_mr_rpages(struct ehca_shca *shca,
+                                  struct ehca_mr *e_mr,
+                                  struct ehca_mr_pginfo *pginfo);
+
+int ehca_reg_mr(struct ehca_shca *shca,
+               struct ehca_mr *e_mr,
+               u64 *iova_start,
+               u64 size,
+               int acl,
+               struct ehca_pd *e_pd,
+               struct ehca_mr_pginfo *pginfo,
+               u32 *lkey, /*OUT*/
+               u32 *rkey, /*OUT*/
+               enum ehca_reg_type reg_type)
+{
+       int ret;
+       u64 h_ret;
+       u32 hipz_acl;
+       struct ehca_mr_hipzout_parms hipzout;
+
+       ehca_mrmw_map_acl(acl, &hipz_acl);
+       ehca_mrmw_set_pgsize_hipz_acl(pginfo->hwpage_size, &hipz_acl);
+       if (ehca_use_hp_mr == 1)
+               hipz_acl |= 0x00000001;
+
+       h_ret = hipz_h_alloc_resource_mr(shca->ipz_hca_handle, e_mr,
+                                        (u64)iova_start, size, hipz_acl,
+                                        e_pd->fw_pd, &hipzout);
+       if (h_ret != H_SUCCESS) {
+               ehca_err(&shca->ib_device, "hipz_alloc_mr failed, h_ret=%lli "
+                        "hca_hndl=%llx", h_ret, shca->ipz_hca_handle.handle);
+               ret = ehca2ib_return_code(h_ret);
+               goto ehca_reg_mr_exit0;
+       }
+
+       e_mr->ipz_mr_handle = hipzout.handle;
+
+       if (reg_type == EHCA_REG_BUSMAP_MR)
+               ret = ehca_reg_bmap_mr_rpages(shca, e_mr, pginfo);
+       else if (reg_type == EHCA_REG_MR)
+               ret = ehca_reg_mr_rpages(shca, e_mr, pginfo);
+       else
+               ret = -EINVAL;
+
+       if (ret)
+               goto ehca_reg_mr_exit1;
+
+       /* successful registration */
+       e_mr->num_kpages = pginfo->num_kpages;
+       e_mr->num_hwpages = pginfo->num_hwpages;
+       e_mr->hwpage_size = pginfo->hwpage_size;
+       e_mr->start = iova_start;
+       e_mr->size = size;
+       e_mr->acl = acl;
+       *lkey = hipzout.lkey;
+       *rkey = hipzout.rkey;
+       return 0;
+
+ehca_reg_mr_exit1:
+       h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_mr);
+       if (h_ret != H_SUCCESS) {
+               ehca_err(&shca->ib_device, "h_ret=%lli shca=%p e_mr=%p "
+                        "iova_start=%p size=%llx acl=%x e_pd=%p lkey=%x "
+                        "pginfo=%p num_kpages=%llx num_hwpages=%llx ret=%i",
+                        h_ret, shca, e_mr, iova_start, size, acl, e_pd,
+                        hipzout.lkey, pginfo, pginfo->num_kpages,
+                        pginfo->num_hwpages, ret);
+               ehca_err(&shca->ib_device, "internal error in ehca_reg_mr, "
+                        "not recoverable");
+       }
+ehca_reg_mr_exit0:
+       if (ret)
+               ehca_err(&shca->ib_device, "ret=%i shca=%p e_mr=%p "
+                        "iova_start=%p size=%llx acl=%x e_pd=%p pginfo=%p "
+                        "num_kpages=%llx num_hwpages=%llx",
+                        ret, shca, e_mr, iova_start, size, acl, e_pd, pginfo,
+                        pginfo->num_kpages, pginfo->num_hwpages);
+       return ret;
+} /* end ehca_reg_mr() */
+
+/*----------------------------------------------------------------------*/
+
+int ehca_reg_mr_rpages(struct ehca_shca *shca,
+                      struct ehca_mr *e_mr,
+                      struct ehca_mr_pginfo *pginfo)
+{
+       int ret = 0;
+       u64 h_ret;
+       u32 rnum;
+       u64 rpage;
+       u32 i;
+       u64 *kpage;
+
+       if (!pginfo->num_hwpages) /* in case of fmr */
+               return 0;
+
+       kpage = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
+       if (!kpage) {
+               ehca_err(&shca->ib_device, "kpage alloc failed");
+               ret = -ENOMEM;
+               goto ehca_reg_mr_rpages_exit0;
+       }
+
+       /* max MAX_RPAGES ehca mr pages per register call */
+       for (i = 0; i < NUM_CHUNKS(pginfo->num_hwpages, MAX_RPAGES); i++) {
+
+               if (i == NUM_CHUNKS(pginfo->num_hwpages, MAX_RPAGES) - 1) {
+                       rnum = pginfo->num_hwpages % MAX_RPAGES; /* last shot */
+                       if (rnum == 0)
+                               rnum = MAX_RPAGES;      /* last shot is full */
+               } else
+                       rnum = MAX_RPAGES;
+
+               ret = ehca_set_pagebuf(pginfo, rnum, kpage);
+               if (ret) {
+                       ehca_err(&shca->ib_device, "ehca_set_pagebuf "
+                                "bad rc, ret=%i rnum=%x kpage=%p",
+                                ret, rnum, kpage);
+                       goto ehca_reg_mr_rpages_exit1;
+               }
+
+               if (rnum > 1) {
+                       rpage = __pa(kpage);
+                       if (!rpage) {
+                               ehca_err(&shca->ib_device, "kpage=%p i=%x",
+                                        kpage, i);
+                               ret = -EFAULT;
+                               goto ehca_reg_mr_rpages_exit1;
+                       }
+               } else
+                       rpage = *kpage;
+
+               h_ret = hipz_h_register_rpage_mr(
+                       shca->ipz_hca_handle, e_mr,
+                       ehca_encode_hwpage_size(pginfo->hwpage_size),
+                       0, rpage, rnum);
+
+               if (i == NUM_CHUNKS(pginfo->num_hwpages, MAX_RPAGES) - 1) {
+                       /*
+                        * check for 'registration complete'==H_SUCCESS
+                        * and for 'page registered'==H_PAGE_REGISTERED
+                        */
+                       if (h_ret != H_SUCCESS) {
+                               ehca_err(&shca->ib_device, "last "
+                                        "hipz_reg_rpage_mr failed, h_ret=%lli "
+                                        "e_mr=%p i=%x hca_hndl=%llx mr_hndl=%llx"
+                                        " lkey=%x", h_ret, e_mr, i,
+                                        shca->ipz_hca_handle.handle,
+                                        e_mr->ipz_mr_handle.handle,
+                                        e_mr->ib.ib_mr.lkey);
+                               ret = ehca2ib_return_code(h_ret);
+                               break;
+                       } else
+                               ret = 0;
+               } else if (h_ret != H_PAGE_REGISTERED) {
+                       ehca_err(&shca->ib_device, "hipz_reg_rpage_mr failed, "
+                                "h_ret=%lli e_mr=%p i=%x lkey=%x hca_hndl=%llx "
+                                "mr_hndl=%llx", h_ret, e_mr, i,
+                                e_mr->ib.ib_mr.lkey,
+                                shca->ipz_hca_handle.handle,
+                                e_mr->ipz_mr_handle.handle);
+                       ret = ehca2ib_return_code(h_ret);
+                       break;
+               } else
+                       ret = 0;
+       } /* end for(i) */
+
+
+ehca_reg_mr_rpages_exit1:
+       ehca_free_fw_ctrlblock(kpage);
+ehca_reg_mr_rpages_exit0:
+       if (ret)
+               ehca_err(&shca->ib_device, "ret=%i shca=%p e_mr=%p pginfo=%p "
+                        "num_kpages=%llx num_hwpages=%llx", ret, shca, e_mr,
+                        pginfo, pginfo->num_kpages, pginfo->num_hwpages);
+       return ret;
+} /* end ehca_reg_mr_rpages() */
+
+/*----------------------------------------------------------------------*/
+
+inline int ehca_rereg_mr_rereg1(struct ehca_shca *shca,
+                               struct ehca_mr *e_mr,
+                               u64 *iova_start,
+                               u64 size,
+                               u32 acl,
+                               struct ehca_pd *e_pd,
+                               struct ehca_mr_pginfo *pginfo,
+                               u32 *lkey, /*OUT*/
+                               u32 *rkey) /*OUT*/
+{
+       int ret;
+       u64 h_ret;
+       u32 hipz_acl;
+       u64 *kpage;
+       u64 rpage;
+       struct ehca_mr_pginfo pginfo_save;
+       struct ehca_mr_hipzout_parms hipzout;
+
+       ehca_mrmw_map_acl(acl, &hipz_acl);
+       ehca_mrmw_set_pgsize_hipz_acl(pginfo->hwpage_size, &hipz_acl);
+
+       kpage = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
+       if (!kpage) {
+               ehca_err(&shca->ib_device, "kpage alloc failed");
+               ret = -ENOMEM;
+               goto ehca_rereg_mr_rereg1_exit0;
+       }
+
+       pginfo_save = *pginfo;
+       ret = ehca_set_pagebuf(pginfo, pginfo->num_hwpages, kpage);
+       if (ret) {
+               ehca_err(&shca->ib_device, "set pagebuf failed, e_mr=%p "
+                        "pginfo=%p type=%x num_kpages=%llx num_hwpages=%llx "
+                        "kpage=%p", e_mr, pginfo, pginfo->type,
+                        pginfo->num_kpages, pginfo->num_hwpages, kpage);
+               goto ehca_rereg_mr_rereg1_exit1;
+       }
+       rpage = __pa(kpage);
+       if (!rpage) {
+               ehca_err(&shca->ib_device, "kpage=%p", kpage);
+               ret = -EFAULT;
+               goto ehca_rereg_mr_rereg1_exit1;
+       }
+       h_ret = hipz_h_reregister_pmr(shca->ipz_hca_handle, e_mr,
+                                     (u64)iova_start, size, hipz_acl,
+                                     e_pd->fw_pd, rpage, &hipzout);
+       if (h_ret != H_SUCCESS) {
+               /*
+                * reregistration unsuccessful, try it again with the 3 hCalls,
+                * e.g. this is required in case H_MR_CONDITION
+                * (MW bound or MR is shared)
+                */
+               ehca_warn(&shca->ib_device, "hipz_h_reregister_pmr failed "
+                         "(Rereg1), h_ret=%lli e_mr=%p", h_ret, e_mr);
+               *pginfo = pginfo_save;
+               ret = -EAGAIN;
+       } else if ((u64 *)hipzout.vaddr != iova_start) {
+               ehca_err(&shca->ib_device, "PHYP changed iova_start in "
+                        "rereg_pmr, iova_start=%p iova_start_out=%llx e_mr=%p "
+                        "mr_handle=%llx lkey=%x lkey_out=%x", iova_start,
+                        hipzout.vaddr, e_mr, e_mr->ipz_mr_handle.handle,
+                        e_mr->ib.ib_mr.lkey, hipzout.lkey);
+               ret = -EFAULT;
+       } else {
+               /*
+                * successful reregistration
+                * note: start and start_out are identical for eServer HCAs
+                */
+               e_mr->num_kpages = pginfo->num_kpages;
+               e_mr->num_hwpages = pginfo->num_hwpages;
+               e_mr->hwpage_size = pginfo->hwpage_size;
+               e_mr->start = iova_start;
+               e_mr->size = size;
+               e_mr->acl = acl;
+               *lkey = hipzout.lkey;
+               *rkey = hipzout.rkey;
+       }
+
+ehca_rereg_mr_rereg1_exit1:
+       ehca_free_fw_ctrlblock(kpage);
+ehca_rereg_mr_rereg1_exit0:
+       if ( ret && (ret != -EAGAIN) )
+               ehca_err(&shca->ib_device, "ret=%i lkey=%x rkey=%x "
+                        "pginfo=%p num_kpages=%llx num_hwpages=%llx",
+                        ret, *lkey, *rkey, pginfo, pginfo->num_kpages,
+                        pginfo->num_hwpages);
+       return ret;
+} /* end ehca_rereg_mr_rereg1() */
+
+/*----------------------------------------------------------------------*/
+
+int ehca_rereg_mr(struct ehca_shca *shca,
+                 struct ehca_mr *e_mr,
+                 u64 *iova_start,
+                 u64 size,
+                 int acl,
+                 struct ehca_pd *e_pd,
+                 struct ehca_mr_pginfo *pginfo,
+                 u32 *lkey,
+                 u32 *rkey)
+{
+       int ret = 0;
+       u64 h_ret;
+       int rereg_1_hcall = 1; /* 1: use hipz_h_reregister_pmr directly */
+       int rereg_3_hcall = 0; /* 1: use 3 hipz calls for reregistration */
+
+       /* first determine reregistration hCall(s) */
+       if ((pginfo->num_hwpages > MAX_RPAGES) ||
+           (e_mr->num_hwpages > MAX_RPAGES) ||
+           (pginfo->num_hwpages > e_mr->num_hwpages)) {
+               ehca_dbg(&shca->ib_device, "Rereg3 case, "
+                        "pginfo->num_hwpages=%llx e_mr->num_hwpages=%x",
+                        pginfo->num_hwpages, e_mr->num_hwpages);
+               rereg_1_hcall = 0;
+               rereg_3_hcall = 1;
+       }
+
+       if (e_mr->flags & EHCA_MR_FLAG_MAXMR) { /* check for max-MR */
+               rereg_1_hcall = 0;
+               rereg_3_hcall = 1;
+               e_mr->flags &= ~EHCA_MR_FLAG_MAXMR;
+               ehca_err(&shca->ib_device, "Rereg MR for max-MR! e_mr=%p",
+                        e_mr);
+       }
+
+       if (rereg_1_hcall) {
+               ret = ehca_rereg_mr_rereg1(shca, e_mr, iova_start, size,
+                                          acl, e_pd, pginfo, lkey, rkey);
+               if (ret) {
+                       if (ret == -EAGAIN)
+                               rereg_3_hcall = 1;
+                       else
+                               goto ehca_rereg_mr_exit0;
+               }
+       }
+
+       if (rereg_3_hcall) {
+               struct ehca_mr save_mr;
+
+               /* first deregister old MR */
+               h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_mr);
+               if (h_ret != H_SUCCESS) {
+                       ehca_err(&shca->ib_device, "hipz_free_mr failed, "
+                                "h_ret=%lli e_mr=%p hca_hndl=%llx mr_hndl=%llx "
+                                "mr->lkey=%x",
+                                h_ret, e_mr, shca->ipz_hca_handle.handle,
+                                e_mr->ipz_mr_handle.handle,
+                                e_mr->ib.ib_mr.lkey);
+                       ret = ehca2ib_return_code(h_ret);
+                       goto ehca_rereg_mr_exit0;
+               }
+               /* clean ehca_mr_t, without changing struct ib_mr and lock */
+               save_mr = *e_mr;
+               ehca_mr_deletenew(e_mr);
+
+               /* set some MR values */
+               e_mr->flags = save_mr.flags;
+               e_mr->hwpage_size = save_mr.hwpage_size;
+               e_mr->fmr_page_size = save_mr.fmr_page_size;
+               e_mr->fmr_max_pages = save_mr.fmr_max_pages;
+               e_mr->fmr_max_maps = save_mr.fmr_max_maps;
+               e_mr->fmr_map_cnt = save_mr.fmr_map_cnt;
+
+               ret = ehca_reg_mr(shca, e_mr, iova_start, size, acl,
+                                 e_pd, pginfo, lkey, rkey, EHCA_REG_MR);
+               if (ret) {
+                       u32 offset = (u64)(&e_mr->flags) - (u64)e_mr;
+                       memcpy(&e_mr->flags, &(save_mr.flags),
+                              sizeof(struct ehca_mr) - offset);
+                       goto ehca_rereg_mr_exit0;
+               }
+       }
+
+ehca_rereg_mr_exit0:
+       if (ret)
+               ehca_err(&shca->ib_device, "ret=%i shca=%p e_mr=%p "
+                        "iova_start=%p size=%llx acl=%x e_pd=%p pginfo=%p "
+                        "num_kpages=%llx lkey=%x rkey=%x rereg_1_hcall=%x "
+                        "rereg_3_hcall=%x", ret, shca, e_mr, iova_start, size,
+                        acl, e_pd, pginfo, pginfo->num_kpages, *lkey, *rkey,
+                        rereg_1_hcall, rereg_3_hcall);
+       return ret;
+} /* end ehca_rereg_mr() */
+
+/*----------------------------------------------------------------------*/
+
+int ehca_unmap_one_fmr(struct ehca_shca *shca,
+                      struct ehca_mr *e_fmr)
+{
+       int ret = 0;
+       u64 h_ret;
+       struct ehca_pd *e_pd =
+               container_of(e_fmr->ib.ib_fmr.pd, struct ehca_pd, ib_pd);
+       struct ehca_mr save_fmr;
+       u32 tmp_lkey, tmp_rkey;
+       struct ehca_mr_pginfo pginfo;
+       struct ehca_mr_hipzout_parms hipzout;
+       struct ehca_mr save_mr;
+
+       if (e_fmr->fmr_max_pages <= MAX_RPAGES) {
+               /*
+                * note: after using rereg hcall with len=0,
+                * rereg hcall must be used again for registering pages
+                */
+               h_ret = hipz_h_reregister_pmr(shca->ipz_hca_handle, e_fmr, 0,
+                                             0, 0, e_pd->fw_pd, 0, &hipzout);
+               if (h_ret == H_SUCCESS) {
+                       /* successful reregistration */
+                       e_fmr->start = NULL;
+                       e_fmr->size = 0;
+                       tmp_lkey = hipzout.lkey;
+                       tmp_rkey = hipzout.rkey;
+                       return 0;
+               }
+               /*
+                * should not happen, because length checked above,
+                * FMRs are not shared and no MW bound to FMRs
+                */
+               ehca_err(&shca->ib_device, "hipz_reregister_pmr failed "
+                        "(Rereg1), h_ret=%lli e_fmr=%p hca_hndl=%llx "
+                        "mr_hndl=%llx lkey=%x lkey_out=%x",
+                        h_ret, e_fmr, shca->ipz_hca_handle.handle,
+                        e_fmr->ipz_mr_handle.handle,
+                        e_fmr->ib.ib_fmr.lkey, hipzout.lkey);
+               /* try free and rereg */
+       }
+
+       /* first free old FMR */
+       h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_fmr);
+       if (h_ret != H_SUCCESS) {
+               ehca_err(&shca->ib_device, "hipz_free_mr failed, "
+                        "h_ret=%lli e_fmr=%p hca_hndl=%llx mr_hndl=%llx "
+                        "lkey=%x",
+                        h_ret, e_fmr, shca->ipz_hca_handle.handle,
+                        e_fmr->ipz_mr_handle.handle,
+                        e_fmr->ib.ib_fmr.lkey);
+               ret = ehca2ib_return_code(h_ret);
+               goto ehca_unmap_one_fmr_exit0;
+       }
+       /* clean ehca_mr_t, without changing lock */
+       save_fmr = *e_fmr;
+       ehca_mr_deletenew(e_fmr);
+
+       /* set some MR values */
+       e_fmr->flags = save_fmr.flags;
+       e_fmr->hwpage_size = save_fmr.hwpage_size;
+       e_fmr->fmr_page_size = save_fmr.fmr_page_size;
+       e_fmr->fmr_max_pages = save_fmr.fmr_max_pages;
+       e_fmr->fmr_max_maps = save_fmr.fmr_max_maps;
+       e_fmr->fmr_map_cnt = save_fmr.fmr_map_cnt;
+       e_fmr->acl = save_fmr.acl;
+
+       memset(&pginfo, 0, sizeof(pginfo));
+       pginfo.type = EHCA_MR_PGI_FMR;
+       ret = ehca_reg_mr(shca, e_fmr, NULL,
+                         (e_fmr->fmr_max_pages * e_fmr->fmr_page_size),
+                         e_fmr->acl, e_pd, &pginfo, &tmp_lkey,
+                         &tmp_rkey, EHCA_REG_MR);
+       if (ret) {
+               u32 offset = (u64)(&e_fmr->flags) - (u64)e_fmr;
+               memcpy(&e_fmr->flags, &(save_mr.flags),
+                      sizeof(struct ehca_mr) - offset);
+       }
+
+ehca_unmap_one_fmr_exit0:
+       if (ret)
+               ehca_err(&shca->ib_device, "ret=%i tmp_lkey=%x tmp_rkey=%x "
+                        "fmr_max_pages=%x",
+                        ret, tmp_lkey, tmp_rkey, e_fmr->fmr_max_pages);
+       return ret;
+} /* end ehca_unmap_one_fmr() */
+
+/*----------------------------------------------------------------------*/
+
+int ehca_reg_smr(struct ehca_shca *shca,
+                struct ehca_mr *e_origmr,
+                struct ehca_mr *e_newmr,
+                u64 *iova_start,
+                int acl,
+                struct ehca_pd *e_pd,
+                u32 *lkey, /*OUT*/
+                u32 *rkey) /*OUT*/
+{
+       int ret = 0;
+       u64 h_ret;
+       u32 hipz_acl;
+       struct ehca_mr_hipzout_parms hipzout;
+
+       ehca_mrmw_map_acl(acl, &hipz_acl);
+       ehca_mrmw_set_pgsize_hipz_acl(e_origmr->hwpage_size, &hipz_acl);
+
+       h_ret = hipz_h_register_smr(shca->ipz_hca_handle, e_newmr, e_origmr,
+                                   (u64)iova_start, hipz_acl, e_pd->fw_pd,
+                                   &hipzout);
+       if (h_ret != H_SUCCESS) {
+               ehca_err(&shca->ib_device, "hipz_reg_smr failed, h_ret=%lli "
+                        "shca=%p e_origmr=%p e_newmr=%p iova_start=%p acl=%x "
+                        "e_pd=%p hca_hndl=%llx mr_hndl=%llx lkey=%x",
+                        h_ret, shca, e_origmr, e_newmr, iova_start, acl, e_pd,
+                        shca->ipz_hca_handle.handle,
+                        e_origmr->ipz_mr_handle.handle,
+                        e_origmr->ib.ib_mr.lkey);
+               ret = ehca2ib_return_code(h_ret);
+               goto ehca_reg_smr_exit0;
+       }
+       /* successful registration */
+       e_newmr->num_kpages = e_origmr->num_kpages;
+       e_newmr->num_hwpages = e_origmr->num_hwpages;
+       e_newmr->hwpage_size   = e_origmr->hwpage_size;
+       e_newmr->start = iova_start;
+       e_newmr->size = e_origmr->size;
+       e_newmr->acl = acl;
+       e_newmr->ipz_mr_handle = hipzout.handle;
+       *lkey = hipzout.lkey;
+       *rkey = hipzout.rkey;
+       return 0;
+
+ehca_reg_smr_exit0:
+       if (ret)
+               ehca_err(&shca->ib_device, "ret=%i shca=%p e_origmr=%p "
+                        "e_newmr=%p iova_start=%p acl=%x e_pd=%p",
+                        ret, shca, e_origmr, e_newmr, iova_start, acl, e_pd);
+       return ret;
+} /* end ehca_reg_smr() */
+
+/*----------------------------------------------------------------------*/
+static inline void *ehca_calc_sectbase(int top, int dir, int idx)
+{
+       unsigned long ret = idx;
+       ret |= dir << EHCA_DIR_INDEX_SHIFT;
+       ret |= top << EHCA_TOP_INDEX_SHIFT;
+       return __va(ret << SECTION_SIZE_BITS);
+}
+
+#define ehca_bmap_valid(entry) \
+       ((u64)entry != (u64)EHCA_INVAL_ADDR)
+
+static u64 ehca_reg_mr_section(int top, int dir, int idx, u64 *kpage,
+                              struct ehca_shca *shca, struct ehca_mr *mr,
+                              struct ehca_mr_pginfo *pginfo)
+{
+       u64 h_ret = 0;
+       unsigned long page = 0;
+       u64 rpage = __pa(kpage);
+       int page_count;
+
+       void *sectbase = ehca_calc_sectbase(top, dir, idx);
+       if ((unsigned long)sectbase & (pginfo->hwpage_size - 1)) {
+               ehca_err(&shca->ib_device, "reg_mr_section will probably fail:"
+                                          "hwpage_size does not fit to "
+                                          "section start address");
+       }
+       page_count = EHCA_SECTSIZE / pginfo->hwpage_size;
+
+       while (page < page_count) {
+               u64 rnum;
+               for (rnum = 0; (rnum < MAX_RPAGES) && (page < page_count);
+                    rnum++) {
+                       void *pg = sectbase + ((page++) * pginfo->hwpage_size);
+                       kpage[rnum] = __pa(pg);
+               }
+
+               h_ret = hipz_h_register_rpage_mr(shca->ipz_hca_handle, mr,
+                       ehca_encode_hwpage_size(pginfo->hwpage_size),
+                       0, rpage, rnum);
+
+               if ((h_ret != H_SUCCESS) && (h_ret != H_PAGE_REGISTERED)) {
+                       ehca_err(&shca->ib_device, "register_rpage_mr failed");
+                       return h_ret;
+               }
+       }
+       return h_ret;
+}
+
+static u64 ehca_reg_mr_sections(int top, int dir, u64 *kpage,
+                               struct ehca_shca *shca, struct ehca_mr *mr,
+                               struct ehca_mr_pginfo *pginfo)
+{
+       u64 hret = H_SUCCESS;
+       int idx;
+
+       for (idx = 0; idx < EHCA_MAP_ENTRIES; idx++) {
+               if (!ehca_bmap_valid(ehca_bmap->top[top]->dir[dir]->ent[idx]))
+                       continue;
+
+               hret = ehca_reg_mr_section(top, dir, idx, kpage, shca, mr,
+                                          pginfo);
+               if ((hret != H_SUCCESS) && (hret != H_PAGE_REGISTERED))
+                               return hret;
+       }
+       return hret;
+}
+
+static u64 ehca_reg_mr_dir_sections(int top, u64 *kpage, struct ehca_shca *shca,
+                                   struct ehca_mr *mr,
+                                   struct ehca_mr_pginfo *pginfo)
+{
+       u64 hret = H_SUCCESS;
+       int dir;
+
+       for (dir = 0; dir < EHCA_MAP_ENTRIES; dir++) {
+               if (!ehca_bmap_valid(ehca_bmap->top[top]->dir[dir]))
+                       continue;
+
+               hret = ehca_reg_mr_sections(top, dir, kpage, shca, mr, pginfo);
+               if ((hret != H_SUCCESS) && (hret != H_PAGE_REGISTERED))
+                               return hret;
+       }
+       return hret;
+}
+
+/* register internal max-MR to internal SHCA */
+int ehca_reg_internal_maxmr(
+       struct ehca_shca *shca,
+       struct ehca_pd *e_pd,
+       struct ehca_mr **e_maxmr)  /*OUT*/
+{
+       int ret;
+       struct ehca_mr *e_mr;
+       u64 *iova_start;
+       u64 size_maxmr;
+       struct ehca_mr_pginfo pginfo;
+       struct ib_phys_buf ib_pbuf;
+       u32 num_kpages;
+       u32 num_hwpages;
+       u64 hw_pgsize;
+
+       if (!ehca_bmap) {
+               ret = -EFAULT;
+               goto ehca_reg_internal_maxmr_exit0;
+       }
+
+       e_mr = ehca_mr_new();
+       if (!e_mr) {
+               ehca_err(&shca->ib_device, "out of memory");
+               ret = -ENOMEM;
+               goto ehca_reg_internal_maxmr_exit0;
+       }
+       e_mr->flags |= EHCA_MR_FLAG_MAXMR;
+
+       /* register internal max-MR on HCA */
+       size_maxmr = ehca_mr_len;
+       iova_start = (u64 *)ehca_map_vaddr((void *)(KERNELBASE + PHYSICAL_START));
+       ib_pbuf.addr = 0;
+       ib_pbuf.size = size_maxmr;
+       num_kpages = NUM_CHUNKS(((u64)iova_start % PAGE_SIZE) + size_maxmr,
+                               PAGE_SIZE);
+       hw_pgsize = ehca_get_max_hwpage_size(shca);
+       num_hwpages = NUM_CHUNKS(((u64)iova_start % hw_pgsize) + size_maxmr,
+                                hw_pgsize);
+
+       memset(&pginfo, 0, sizeof(pginfo));
+       pginfo.type = EHCA_MR_PGI_PHYS;
+       pginfo.num_kpages = num_kpages;
+       pginfo.num_hwpages = num_hwpages;
+       pginfo.hwpage_size = hw_pgsize;
+       pginfo.u.phy.num_phys_buf = 1;
+       pginfo.u.phy.phys_buf_array = &ib_pbuf;
+
+       ret = ehca_reg_mr(shca, e_mr, iova_start, size_maxmr, 0, e_pd,
+                         &pginfo, &e_mr->ib.ib_mr.lkey,
+                         &e_mr->ib.ib_mr.rkey, EHCA_REG_BUSMAP_MR);
+       if (ret) {
+               ehca_err(&shca->ib_device, "reg of internal max MR failed, "
+                        "e_mr=%p iova_start=%p size_maxmr=%llx num_kpages=%x "
+                        "num_hwpages=%x", e_mr, iova_start, size_maxmr,
+                        num_kpages, num_hwpages);
+               goto ehca_reg_internal_maxmr_exit1;
+       }
+
+       /* successful registration of all pages */
+       e_mr->ib.ib_mr.device = e_pd->ib_pd.device;
+       e_mr->ib.ib_mr.pd = &e_pd->ib_pd;
+       e_mr->ib.ib_mr.uobject = NULL;
+       atomic_inc(&(e_pd->ib_pd.usecnt));
+       atomic_set(&(e_mr->ib.ib_mr.usecnt), 0);
+       *e_maxmr = e_mr;
+       return 0;
+
+ehca_reg_internal_maxmr_exit1:
+       ehca_mr_delete(e_mr);
+ehca_reg_internal_maxmr_exit0:
+       if (ret)
+               ehca_err(&shca->ib_device, "ret=%i shca=%p e_pd=%p e_maxmr=%p",
+                        ret, shca, e_pd, e_maxmr);
+       return ret;
+} /* end ehca_reg_internal_maxmr() */
+
+/*----------------------------------------------------------------------*/
+
+int ehca_reg_maxmr(struct ehca_shca *shca,
+                  struct ehca_mr *e_newmr,
+                  u64 *iova_start,
+                  int acl,
+                  struct ehca_pd *e_pd,
+                  u32 *lkey,
+                  u32 *rkey)
+{
+       u64 h_ret;
+       struct ehca_mr *e_origmr = shca->maxmr;
+       u32 hipz_acl;
+       struct ehca_mr_hipzout_parms hipzout;
+
+       ehca_mrmw_map_acl(acl, &hipz_acl);
+       ehca_mrmw_set_pgsize_hipz_acl(e_origmr->hwpage_size, &hipz_acl);
+
+       h_ret = hipz_h_register_smr(shca->ipz_hca_handle, e_newmr, e_origmr,
+                                   (u64)iova_start, hipz_acl, e_pd->fw_pd,
+                                   &hipzout);
+       if (h_ret != H_SUCCESS) {
+               ehca_err(&shca->ib_device, "hipz_reg_smr failed, h_ret=%lli "
+                        "e_origmr=%p hca_hndl=%llx mr_hndl=%llx lkey=%x",
+                        h_ret, e_origmr, shca->ipz_hca_handle.handle,
+                        e_origmr->ipz_mr_handle.handle,
+                        e_origmr->ib.ib_mr.lkey);
+               return ehca2ib_return_code(h_ret);
+       }
+       /* successful registration */
+       e_newmr->num_kpages = e_origmr->num_kpages;
+       e_newmr->num_hwpages = e_origmr->num_hwpages;
+       e_newmr->hwpage_size = e_origmr->hwpage_size;
+       e_newmr->start = iova_start;
+       e_newmr->size = e_origmr->size;
+       e_newmr->acl = acl;
+       e_newmr->ipz_mr_handle = hipzout.handle;
+       *lkey = hipzout.lkey;
+       *rkey = hipzout.rkey;
+       return 0;
+} /* end ehca_reg_maxmr() */
+
+/*----------------------------------------------------------------------*/
+
+int ehca_dereg_internal_maxmr(struct ehca_shca *shca)
+{
+       int ret;
+       struct ehca_mr *e_maxmr;
+       struct ib_pd *ib_pd;
+
+       if (!shca->maxmr) {
+               ehca_err(&shca->ib_device, "bad call, shca=%p", shca);
+               ret = -EINVAL;
+               goto ehca_dereg_internal_maxmr_exit0;
+       }
+
+       e_maxmr = shca->maxmr;
+       ib_pd = e_maxmr->ib.ib_mr.pd;
+       shca->maxmr = NULL; /* remove internal max-MR indication from SHCA */
+
+       ret = ehca_dereg_mr(&e_maxmr->ib.ib_mr);
+       if (ret) {
+               ehca_err(&shca->ib_device, "dereg internal max-MR failed, "
+                        "ret=%i e_maxmr=%p shca=%p lkey=%x",
+                        ret, e_maxmr, shca, e_maxmr->ib.ib_mr.lkey);
+               shca->maxmr = e_maxmr;
+               goto ehca_dereg_internal_maxmr_exit0;
+       }
+
+       atomic_dec(&ib_pd->usecnt);
+
+ehca_dereg_internal_maxmr_exit0:
+       if (ret)
+               ehca_err(&shca->ib_device, "ret=%i shca=%p shca->maxmr=%p",
+                        ret, shca, shca->maxmr);
+       return ret;
+} /* end ehca_dereg_internal_maxmr() */
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * check physical buffer array of MR verbs for validness and
+ * calculates MR size
+ */
+int ehca_mr_chk_buf_and_calc_size(struct ib_phys_buf *phys_buf_array,
+                                 int num_phys_buf,
+                                 u64 *iova_start,
+                                 u64 *size)
+{
+       struct ib_phys_buf *pbuf = phys_buf_array;
+       u64 size_count = 0;
+       u32 i;
+
+       if (num_phys_buf == 0) {
+               ehca_gen_err("bad phys buf array len, num_phys_buf=0");
+               return -EINVAL;
+       }
+       /* check first buffer */
+       if (((u64)iova_start & ~PAGE_MASK) != (pbuf->addr & ~PAGE_MASK)) {
+               ehca_gen_err("iova_start/addr mismatch, iova_start=%p "
+                            "pbuf->addr=%llx pbuf->size=%llx",
+                            iova_start, pbuf->addr, pbuf->size);
+               return -EINVAL;
+       }
+       if (((pbuf->addr + pbuf->size) % PAGE_SIZE) &&
+           (num_phys_buf > 1)) {
+               ehca_gen_err("addr/size mismatch in 1st buf, pbuf->addr=%llx "
+                            "pbuf->size=%llx", pbuf->addr, pbuf->size);
+               return -EINVAL;
+       }
+
+       for (i = 0; i < num_phys_buf; i++) {
+               if ((i > 0) && (pbuf->addr % PAGE_SIZE)) {
+                       ehca_gen_err("bad address, i=%x pbuf->addr=%llx "
+                                    "pbuf->size=%llx",
+                                    i, pbuf->addr, pbuf->size);
+                       return -EINVAL;
+               }
+               if (((i > 0) && /* not 1st */
+                    (i < (num_phys_buf - 1)) &&        /* not last */
+                    (pbuf->size % PAGE_SIZE)) || (pbuf->size == 0)) {
+                       ehca_gen_err("bad size, i=%x pbuf->size=%llx",
+                                    i, pbuf->size);
+                       return -EINVAL;
+               }
+               size_count += pbuf->size;
+               pbuf++;
+       }
+
+       *size = size_count;
+       return 0;
+} /* end ehca_mr_chk_buf_and_calc_size() */
+
+/*----------------------------------------------------------------------*/
+
+/* check page list of map FMR verb for validness */
+int ehca_fmr_check_page_list(struct ehca_mr *e_fmr,
+                            u64 *page_list,
+                            int list_len)
+{
+       u32 i;
+       u64 *page;
+
+       if ((list_len == 0) || (list_len > e_fmr->fmr_max_pages)) {
+               ehca_gen_err("bad list_len, list_len=%x "
+                            "e_fmr->fmr_max_pages=%x fmr=%p",
+                            list_len, e_fmr->fmr_max_pages, e_fmr);
+               return -EINVAL;
+       }
+
+       /* each page must be aligned */
+       page = page_list;
+       for (i = 0; i < list_len; i++) {
+               if (*page % e_fmr->fmr_page_size) {
+                       ehca_gen_err("bad page, i=%x *page=%llx page=%p fmr=%p "
+                                    "fmr_page_size=%x", i, *page, page, e_fmr,
+                                    e_fmr->fmr_page_size);
+                       return -EINVAL;
+               }
+               page++;
+       }
+
+       return 0;
+} /* end ehca_fmr_check_page_list() */
+
+/*----------------------------------------------------------------------*/
+
+/* PAGE_SIZE >= pginfo->hwpage_size */
+static int ehca_set_pagebuf_user1(struct ehca_mr_pginfo *pginfo,
+                                 u32 number,
+                                 u64 *kpage)
+{
+       int ret = 0;
+       u64 pgaddr;
+       u32 j = 0;
+       int hwpages_per_kpage = PAGE_SIZE / pginfo->hwpage_size;
+       struct scatterlist **sg = &pginfo->u.usr.next_sg;
+
+       while (*sg != NULL) {
+               pgaddr = page_to_pfn(sg_page(*sg))
+                       << PAGE_SHIFT;
+               *kpage = pgaddr + (pginfo->next_hwpage *
+                                  pginfo->hwpage_size);
+               if (!(*kpage)) {
+                       ehca_gen_err("pgaddr=%llx "
+                                    "sg_dma_address=%llx "
+                                    "entry=%llx next_hwpage=%llx",
+                                    pgaddr, (u64)sg_dma_address(*sg),
+                                    pginfo->u.usr.next_nmap,
+                                    pginfo->next_hwpage);
+                       return -EFAULT;
+               }
+               (pginfo->hwpage_cnt)++;
+               (pginfo->next_hwpage)++;
+               kpage++;
+               if (pginfo->next_hwpage % hwpages_per_kpage == 0) {
+                       (pginfo->kpage_cnt)++;
+                       (pginfo->u.usr.next_nmap)++;
+                       pginfo->next_hwpage = 0;
+                       *sg = sg_next(*sg);
+               }
+               j++;
+               if (j >= number)
+                       break;
+       }
+
+       return ret;
+}
+
+/*
+ * check given pages for contiguous layout
+ * last page addr is returned in prev_pgaddr for further check
+ */
+static int ehca_check_kpages_per_ate(struct scatterlist **sg,
+                                    int num_pages,
+                                    u64 *prev_pgaddr)
+{
+       for (; *sg && num_pages > 0; *sg = sg_next(*sg), num_pages--) {
+               u64 pgaddr = page_to_pfn(sg_page(*sg)) << PAGE_SHIFT;
+               if (ehca_debug_level >= 3)
+                       ehca_gen_dbg("chunk_page=%llx value=%016llx", pgaddr,
+                                    *(u64 *)__va(pgaddr));
+               if (pgaddr - PAGE_SIZE != *prev_pgaddr) {
+                       ehca_gen_err("uncontiguous page found pgaddr=%llx "
+                                    "prev_pgaddr=%llx entries_left_in_hwpage=%x",
+                                    pgaddr, *prev_pgaddr, num_pages);
+                       return -EINVAL;
+               }
+               *prev_pgaddr = pgaddr;
+       }
+       return 0;
+}
+
+/* PAGE_SIZE < pginfo->hwpage_size */
+static int ehca_set_pagebuf_user2(struct ehca_mr_pginfo *pginfo,
+                                 u32 number,
+                                 u64 *kpage)
+{
+       int ret = 0;
+       u64 pgaddr, prev_pgaddr;
+       u32 j = 0;
+       int kpages_per_hwpage = pginfo->hwpage_size / PAGE_SIZE;
+       int nr_kpages = kpages_per_hwpage;
+       struct scatterlist **sg = &pginfo->u.usr.next_sg;
+
+       while (*sg != NULL) {
+
+               if (nr_kpages == kpages_per_hwpage) {
+                       pgaddr = (page_to_pfn(sg_page(*sg))
+                                  << PAGE_SHIFT);
+                       *kpage = pgaddr;
+                       if (!(*kpage)) {
+                               ehca_gen_err("pgaddr=%llx entry=%llx",
+                                            pgaddr, pginfo->u.usr.next_nmap);
+                               ret = -EFAULT;
+                               return ret;
+                       }
+                       /*
+                        * The first page in a hwpage must be aligned;
+                        * the first MR page is exempt from this rule.
+                        */
+                       if (pgaddr & (pginfo->hwpage_size - 1)) {
+                               if (pginfo->hwpage_cnt) {
+                                       ehca_gen_err(
+                                               "invalid alignment "
+                                               "pgaddr=%llx entry=%llx "
+                                               "mr_pgsize=%llx",
+                                               pgaddr, pginfo->u.usr.next_nmap,
+                                               pginfo->hwpage_size);
+                                       ret = -EFAULT;
+                                       return ret;
+                               }
+                               /* first MR page */
+                               pginfo->kpage_cnt =
+                                       (pgaddr &
+                                        (pginfo->hwpage_size - 1)) >>
+                                       PAGE_SHIFT;
+                               nr_kpages -= pginfo->kpage_cnt;
+                               *kpage = pgaddr &
+                                        ~(pginfo->hwpage_size - 1);
+                       }
+                       if (ehca_debug_level >= 3) {
+                               u64 val = *(u64 *)__va(pgaddr);
+                               ehca_gen_dbg("kpage=%llx page=%llx "
+                                            "value=%016llx",
+                                            *kpage, pgaddr, val);
+                       }
+                       prev_pgaddr = pgaddr;
+                       *sg = sg_next(*sg);
+                       pginfo->kpage_cnt++;
+                       pginfo->u.usr.next_nmap++;
+                       nr_kpages--;
+                       if (!nr_kpages)
+                               goto next_kpage;
+                       continue;
+               }
+
+               ret = ehca_check_kpages_per_ate(sg, nr_kpages,
+                                               &prev_pgaddr);
+               if (ret)
+                       return ret;
+               pginfo->kpage_cnt += nr_kpages;
+               pginfo->u.usr.next_nmap += nr_kpages;
+
+next_kpage:
+               nr_kpages = kpages_per_hwpage;
+               (pginfo->hwpage_cnt)++;
+               kpage++;
+               j++;
+               if (j >= number)
+                       break;
+       }
+
+       return ret;
+}
+
+static int ehca_set_pagebuf_phys(struct ehca_mr_pginfo *pginfo,
+                                u32 number, u64 *kpage)
+{
+       int ret = 0;
+       struct ib_phys_buf *pbuf;
+       u64 num_hw, offs_hw;
+       u32 i = 0;
+
+       /* loop over desired phys_buf_array entries */
+       while (i < number) {
+               pbuf   = pginfo->u.phy.phys_buf_array + pginfo->u.phy.next_buf;
+               num_hw  = NUM_CHUNKS((pbuf->addr % pginfo->hwpage_size) +
+                                    pbuf->size, pginfo->hwpage_size);
+               offs_hw = (pbuf->addr & ~(pginfo->hwpage_size - 1)) /
+                       pginfo->hwpage_size;
+               while (pginfo->next_hwpage < offs_hw + num_hw) {
+                       /* sanity check */
+                       if ((pginfo->kpage_cnt >= pginfo->num_kpages) ||
+                           (pginfo->hwpage_cnt >= pginfo->num_hwpages)) {
+                               ehca_gen_err("kpage_cnt >= num_kpages, "
+                                            "kpage_cnt=%llx num_kpages=%llx "
+                                            "hwpage_cnt=%llx "
+                                            "num_hwpages=%llx i=%x",
+                                            pginfo->kpage_cnt,
+                                            pginfo->num_kpages,
+                                            pginfo->hwpage_cnt,
+                                            pginfo->num_hwpages, i);
+                               return -EFAULT;
+                       }
+                       *kpage = (pbuf->addr & ~(pginfo->hwpage_size - 1)) +
+                                (pginfo->next_hwpage * pginfo->hwpage_size);
+                       if ( !(*kpage) && pbuf->addr ) {
+                               ehca_gen_err("pbuf->addr=%llx pbuf->size=%llx "
+                                            "next_hwpage=%llx", pbuf->addr,
+                                            pbuf->size, pginfo->next_hwpage);
+                               return -EFAULT;
+                       }
+                       (pginfo->hwpage_cnt)++;
+                       (pginfo->next_hwpage)++;
+                       if (PAGE_SIZE >= pginfo->hwpage_size) {
+                               if (pginfo->next_hwpage %
+                                   (PAGE_SIZE / pginfo->hwpage_size) == 0)
+                                       (pginfo->kpage_cnt)++;
+                       } else
+                               pginfo->kpage_cnt += pginfo->hwpage_size /
+                                       PAGE_SIZE;
+                       kpage++;
+                       i++;
+                       if (i >= number) break;
+               }
+               if (pginfo->next_hwpage >= offs_hw + num_hw) {
+                       (pginfo->u.phy.next_buf)++;
+                       pginfo->next_hwpage = 0;
+               }
+       }
+       return ret;
+}
+
+static int ehca_set_pagebuf_fmr(struct ehca_mr_pginfo *pginfo,
+                               u32 number, u64 *kpage)
+{
+       int ret = 0;
+       u64 *fmrlist;
+       u32 i;
+
+       /* loop over desired page_list entries */
+       fmrlist = pginfo->u.fmr.page_list + pginfo->u.fmr.next_listelem;
+       for (i = 0; i < number; i++) {
+               *kpage = (*fmrlist & ~(pginfo->hwpage_size - 1)) +
+                          pginfo->next_hwpage * pginfo->hwpage_size;
+               if ( !(*kpage) ) {
+                       ehca_gen_err("*fmrlist=%llx fmrlist=%p "
+                                    "next_listelem=%llx next_hwpage=%llx",
+                                    *fmrlist, fmrlist,
+                                    pginfo->u.fmr.next_listelem,
+                                    pginfo->next_hwpage);
+                       return -EFAULT;
+               }
+               (pginfo->hwpage_cnt)++;
+               if (pginfo->u.fmr.fmr_pgsize >= pginfo->hwpage_size) {
+                       if (pginfo->next_hwpage %
+                           (pginfo->u.fmr.fmr_pgsize /
+                            pginfo->hwpage_size) == 0) {
+                               (pginfo->kpage_cnt)++;
+                               (pginfo->u.fmr.next_listelem)++;
+                               fmrlist++;
+                               pginfo->next_hwpage = 0;
+                       } else
+                               (pginfo->next_hwpage)++;
+               } else {
+                       unsigned int cnt_per_hwpage = pginfo->hwpage_size /
+                               pginfo->u.fmr.fmr_pgsize;
+                       unsigned int j;
+                       u64 prev = *kpage;
+                       /* check if adrs are contiguous */
+                       for (j = 1; j < cnt_per_hwpage; j++) {
+                               u64 p = fmrlist[j] & ~(pginfo->hwpage_size - 1);
+                               if (prev + pginfo->u.fmr.fmr_pgsize != p) {
+                                       ehca_gen_err("uncontiguous fmr pages "
+                                                    "found prev=%llx p=%llx "
+                                                    "idx=%x", prev, p, i + j);
+                                       return -EINVAL;
+                               }
+                               prev = p;
+                       }
+                       pginfo->kpage_cnt += cnt_per_hwpage;
+                       pginfo->u.fmr.next_listelem += cnt_per_hwpage;
+                       fmrlist += cnt_per_hwpage;
+               }
+               kpage++;
+       }
+       return ret;
+}
+
+/* setup page buffer from page info */
+int ehca_set_pagebuf(struct ehca_mr_pginfo *pginfo,
+                    u32 number,
+                    u64 *kpage)
+{
+       int ret;
+
+       switch (pginfo->type) {
+       case EHCA_MR_PGI_PHYS:
+               ret = ehca_set_pagebuf_phys(pginfo, number, kpage);
+               break;
+       case EHCA_MR_PGI_USER:
+               ret = PAGE_SIZE >= pginfo->hwpage_size ?
+                       ehca_set_pagebuf_user1(pginfo, number, kpage) :
+                       ehca_set_pagebuf_user2(pginfo, number, kpage);
+               break;
+       case EHCA_MR_PGI_FMR:
+               ret = ehca_set_pagebuf_fmr(pginfo, number, kpage);
+               break;
+       default:
+               ehca_gen_err("bad pginfo->type=%x", pginfo->type);
+               ret = -EFAULT;
+               break;
+       }
+       return ret;
+} /* end ehca_set_pagebuf() */
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * check MR if it is a max-MR, i.e. uses whole memory
+ * in case it's a max-MR 1 is returned, else 0
+ */
+int ehca_mr_is_maxmr(u64 size,
+                    u64 *iova_start)
+{
+       /* a MR is treated as max-MR only if it fits following: */
+       if ((size == ehca_mr_len) &&
+           (iova_start == (void *)ehca_map_vaddr((void *)(KERNELBASE + PHYSICAL_START)))) {
+               ehca_gen_dbg("this is a max-MR");
+               return 1;
+       } else
+               return 0;
+} /* end ehca_mr_is_maxmr() */
+
+/*----------------------------------------------------------------------*/
+
+/* map access control for MR/MW. This routine is used for MR and MW. */
+void ehca_mrmw_map_acl(int ib_acl,
+                      u32 *hipz_acl)
+{
+       *hipz_acl = 0;
+       if (ib_acl & IB_ACCESS_REMOTE_READ)
+               *hipz_acl |= HIPZ_ACCESSCTRL_R_READ;
+       if (ib_acl & IB_ACCESS_REMOTE_WRITE)
+               *hipz_acl |= HIPZ_ACCESSCTRL_R_WRITE;
+       if (ib_acl & IB_ACCESS_REMOTE_ATOMIC)
+               *hipz_acl |= HIPZ_ACCESSCTRL_R_ATOMIC;
+       if (ib_acl & IB_ACCESS_LOCAL_WRITE)
+               *hipz_acl |= HIPZ_ACCESSCTRL_L_WRITE;
+       if (ib_acl & IB_ACCESS_MW_BIND)
+               *hipz_acl |= HIPZ_ACCESSCTRL_MW_BIND;
+} /* end ehca_mrmw_map_acl() */
+
+/*----------------------------------------------------------------------*/
+
+/* sets page size in hipz access control for MR/MW. */
+void ehca_mrmw_set_pgsize_hipz_acl(u32 pgsize, u32 *hipz_acl) /*INOUT*/
+{
+       *hipz_acl |= (ehca_encode_hwpage_size(pgsize) << 24);
+} /* end ehca_mrmw_set_pgsize_hipz_acl() */
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * reverse map access control for MR/MW.
+ * This routine is used for MR and MW.
+ */
+void ehca_mrmw_reverse_map_acl(const u32 *hipz_acl,
+                              int *ib_acl) /*OUT*/
+{
+       *ib_acl = 0;
+       if (*hipz_acl & HIPZ_ACCESSCTRL_R_READ)
+               *ib_acl |= IB_ACCESS_REMOTE_READ;
+       if (*hipz_acl & HIPZ_ACCESSCTRL_R_WRITE)
+               *ib_acl |= IB_ACCESS_REMOTE_WRITE;
+       if (*hipz_acl & HIPZ_ACCESSCTRL_R_ATOMIC)
+               *ib_acl |= IB_ACCESS_REMOTE_ATOMIC;
+       if (*hipz_acl & HIPZ_ACCESSCTRL_L_WRITE)
+               *ib_acl |= IB_ACCESS_LOCAL_WRITE;
+       if (*hipz_acl & HIPZ_ACCESSCTRL_MW_BIND)
+               *ib_acl |= IB_ACCESS_MW_BIND;
+} /* end ehca_mrmw_reverse_map_acl() */
+
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * MR destructor and constructor
+ * used in Reregister MR verb, sets all fields in ehca_mr_t to 0,
+ * except struct ib_mr and spinlock
+ */
+void ehca_mr_deletenew(struct ehca_mr *mr)
+{
+       mr->flags = 0;
+       mr->num_kpages = 0;
+       mr->num_hwpages = 0;
+       mr->acl = 0;
+       mr->start = NULL;
+       mr->fmr_page_size = 0;
+       mr->fmr_max_pages = 0;
+       mr->fmr_max_maps = 0;
+       mr->fmr_map_cnt = 0;
+       memset(&mr->ipz_mr_handle, 0, sizeof(mr->ipz_mr_handle));
+       memset(&mr->galpas, 0, sizeof(mr->galpas));
+} /* end ehca_mr_deletenew() */
+
+int ehca_init_mrmw_cache(void)
+{
+       mr_cache = kmem_cache_create("ehca_cache_mr",
+                                    sizeof(struct ehca_mr), 0,
+                                    SLAB_HWCACHE_ALIGN,
+                                    NULL);
+       if (!mr_cache)
+               return -ENOMEM;
+       mw_cache = kmem_cache_create("ehca_cache_mw",
+                                    sizeof(struct ehca_mw), 0,
+                                    SLAB_HWCACHE_ALIGN,
+                                    NULL);
+       if (!mw_cache) {
+               kmem_cache_destroy(mr_cache);
+               mr_cache = NULL;
+               return -ENOMEM;
+       }
+       return 0;
+}
+
+void ehca_cleanup_mrmw_cache(void)
+{
+       if (mr_cache)
+               kmem_cache_destroy(mr_cache);
+       if (mw_cache)
+               kmem_cache_destroy(mw_cache);
+}
+
+static inline int ehca_init_top_bmap(struct ehca_top_bmap *ehca_top_bmap,
+                                    int dir)
+{
+       if (!ehca_bmap_valid(ehca_top_bmap->dir[dir])) {
+               ehca_top_bmap->dir[dir] =
+                       kmalloc(sizeof(struct ehca_dir_bmap), GFP_KERNEL);
+               if (!ehca_top_bmap->dir[dir])
+                       return -ENOMEM;
+               /* Set map block to 0xFF according to EHCA_INVAL_ADDR */
+               memset(ehca_top_bmap->dir[dir], 0xFF, EHCA_ENT_MAP_SIZE);
+       }
+       return 0;
+}
+
+static inline int ehca_init_bmap(struct ehca_bmap *ehca_bmap, int top, int dir)
+{
+       if (!ehca_bmap_valid(ehca_bmap->top[top])) {
+               ehca_bmap->top[top] =
+                       kmalloc(sizeof(struct ehca_top_bmap), GFP_KERNEL);
+               if (!ehca_bmap->top[top])
+                       return -ENOMEM;
+               /* Set map block to 0xFF according to EHCA_INVAL_ADDR */
+               memset(ehca_bmap->top[top], 0xFF, EHCA_DIR_MAP_SIZE);
+       }
+       return ehca_init_top_bmap(ehca_bmap->top[top], dir);
+}
+
+static inline int ehca_calc_index(unsigned long i, unsigned long s)
+{
+       return (i >> s) & EHCA_INDEX_MASK;
+}
+
+void ehca_destroy_busmap(void)
+{
+       int top, dir;
+
+       if (!ehca_bmap)
+               return;
+
+       for (top = 0; top < EHCA_MAP_ENTRIES; top++) {
+               if (!ehca_bmap_valid(ehca_bmap->top[top]))
+                       continue;
+               for (dir = 0; dir < EHCA_MAP_ENTRIES; dir++) {
+                       if (!ehca_bmap_valid(ehca_bmap->top[top]->dir[dir]))
+                               continue;
+
+                       kfree(ehca_bmap->top[top]->dir[dir]);
+               }
+
+               kfree(ehca_bmap->top[top]);
+       }
+
+       kfree(ehca_bmap);
+       ehca_bmap = NULL;
+}
+
+static int ehca_update_busmap(unsigned long pfn, unsigned long nr_pages)
+{
+       unsigned long i, start_section, end_section;
+       int top, dir, idx;
+
+       if (!nr_pages)
+               return 0;
+
+       if (!ehca_bmap) {
+               ehca_bmap = kmalloc(sizeof(struct ehca_bmap), GFP_KERNEL);
+               if (!ehca_bmap)
+                       return -ENOMEM;
+               /* Set map block to 0xFF according to EHCA_INVAL_ADDR */
+               memset(ehca_bmap, 0xFF, EHCA_TOP_MAP_SIZE);
+       }
+
+       start_section = (pfn * PAGE_SIZE) / EHCA_SECTSIZE;
+       end_section = ((pfn + nr_pages) * PAGE_SIZE) / EHCA_SECTSIZE;
+       for (i = start_section; i < end_section; i++) {
+               int ret;
+               top = ehca_calc_index(i, EHCA_TOP_INDEX_SHIFT);
+               dir = ehca_calc_index(i, EHCA_DIR_INDEX_SHIFT);
+               idx = i & EHCA_INDEX_MASK;
+
+               ret = ehca_init_bmap(ehca_bmap, top, dir);
+               if (ret) {
+                       ehca_destroy_busmap();
+                       return ret;
+               }
+               ehca_bmap->top[top]->dir[dir]->ent[idx] = ehca_mr_len;
+               ehca_mr_len += EHCA_SECTSIZE;
+       }
+       return 0;
+}
+
+static int ehca_is_hugepage(unsigned long pfn)
+{
+       int page_order;
+
+       if (pfn & EHCA_HUGEPAGE_PFN_MASK)
+               return 0;
+
+       page_order = compound_order(pfn_to_page(pfn));
+       if (page_order + PAGE_SHIFT != EHCA_HUGEPAGESHIFT)
+               return 0;
+
+       return 1;
+}
+
+static int ehca_create_busmap_callback(unsigned long initial_pfn,
+                                      unsigned long total_nr_pages, void *arg)
+{
+       int ret;
+       unsigned long pfn, start_pfn, end_pfn, nr_pages;
+
+       if ((total_nr_pages * PAGE_SIZE) < EHCA_HUGEPAGE_SIZE)
+               return ehca_update_busmap(initial_pfn, total_nr_pages);
+
+       /* Given chunk is >= 16GB -> check for hugepages */
+       start_pfn = initial_pfn;
+       end_pfn = initial_pfn + total_nr_pages;
+       pfn = start_pfn;
+
+       while (pfn < end_pfn) {
+               if (ehca_is_hugepage(pfn)) {
+                       /* Add mem found in front of the hugepage */
+                       nr_pages = pfn - start_pfn;
+                       ret = ehca_update_busmap(start_pfn, nr_pages);
+                       if (ret)
+                               return ret;
+                       /* Skip the hugepage */
+                       pfn += (EHCA_HUGEPAGE_SIZE / PAGE_SIZE);
+                       start_pfn = pfn;
+               } else
+                       pfn += (EHCA_SECTSIZE / PAGE_SIZE);
+       }
+
+       /* Add mem found behind the hugepage(s)  */
+       nr_pages = pfn - start_pfn;
+       return ehca_update_busmap(start_pfn, nr_pages);
+}
+
+int ehca_create_busmap(void)
+{
+       int ret;
+
+       ehca_mr_len = 0;
+       ret = walk_system_ram_range(0, 1ULL << MAX_PHYSMEM_BITS, NULL,
+                                  ehca_create_busmap_callback);
+       return ret;
+}
+
+static int ehca_reg_bmap_mr_rpages(struct ehca_shca *shca,
+                                  struct ehca_mr *e_mr,
+                                  struct ehca_mr_pginfo *pginfo)
+{
+       int top;
+       u64 hret, *kpage;
+
+       kpage = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
+       if (!kpage) {
+               ehca_err(&shca->ib_device, "kpage alloc failed");
+               return -ENOMEM;
+       }
+       for (top = 0; top < EHCA_MAP_ENTRIES; top++) {
+               if (!ehca_bmap_valid(ehca_bmap->top[top]))
+                       continue;
+               hret = ehca_reg_mr_dir_sections(top, kpage, shca, e_mr, pginfo);
+               if ((hret != H_PAGE_REGISTERED) && (hret != H_SUCCESS))
+                       break;
+       }
+
+       ehca_free_fw_ctrlblock(kpage);
+
+       if (hret == H_SUCCESS)
+               return 0; /* Everything is fine */
+       else {
+               ehca_err(&shca->ib_device, "ehca_reg_bmap_mr_rpages failed, "
+                                "h_ret=%lli e_mr=%p top=%x lkey=%x "
+                                "hca_hndl=%llx mr_hndl=%llx", hret, e_mr, top,
+                                e_mr->ib.ib_mr.lkey,
+                                shca->ipz_hca_handle.handle,
+                                e_mr->ipz_mr_handle.handle);
+               return ehca2ib_return_code(hret);
+       }
+}
+
+static u64 ehca_map_vaddr(void *caddr)
+{
+       int top, dir, idx;
+       unsigned long abs_addr, offset;
+       u64 entry;
+
+       if (!ehca_bmap)
+               return EHCA_INVAL_ADDR;
+
+       abs_addr = __pa(caddr);
+       top = ehca_calc_index(abs_addr, EHCA_TOP_INDEX_SHIFT + EHCA_SECTSHIFT);
+       if (!ehca_bmap_valid(ehca_bmap->top[top]))
+               return EHCA_INVAL_ADDR;
+
+       dir = ehca_calc_index(abs_addr, EHCA_DIR_INDEX_SHIFT + EHCA_SECTSHIFT);
+       if (!ehca_bmap_valid(ehca_bmap->top[top]->dir[dir]))
+               return EHCA_INVAL_ADDR;
+
+       idx = ehca_calc_index(abs_addr, EHCA_SECTSHIFT);
+
+       entry = ehca_bmap->top[top]->dir[dir]->ent[idx];
+       if (ehca_bmap_valid(entry)) {
+               offset = (unsigned long)caddr & (EHCA_SECTSIZE - 1);
+               return entry | offset;
+       } else
+               return EHCA_INVAL_ADDR;
+}
+
+static int ehca_dma_mapping_error(struct ib_device *dev, u64 dma_addr)
+{
+       return dma_addr == EHCA_INVAL_ADDR;
+}
+
+static u64 ehca_dma_map_single(struct ib_device *dev, void *cpu_addr,
+                              size_t size, enum dma_data_direction direction)
+{
+       if (cpu_addr)
+               return ehca_map_vaddr(cpu_addr);
+       else
+               return EHCA_INVAL_ADDR;
+}
+
+static void ehca_dma_unmap_single(struct ib_device *dev, u64 addr, size_t size,
+                                 enum dma_data_direction direction)
+{
+       /* This is only a stub; nothing to be done here */
+}
+
+static u64 ehca_dma_map_page(struct ib_device *dev, struct page *page,
+                            unsigned long offset, size_t size,
+                            enum dma_data_direction direction)
+{
+       u64 addr;
+
+       if (offset + size > PAGE_SIZE)
+               return EHCA_INVAL_ADDR;
+
+       addr = ehca_map_vaddr(page_address(page));
+       if (!ehca_dma_mapping_error(dev, addr))
+               addr += offset;
+
+       return addr;
+}
+
+static void ehca_dma_unmap_page(struct ib_device *dev, u64 addr, size_t size,
+                               enum dma_data_direction direction)
+{
+       /* This is only a stub; nothing to be done here */
+}
+
+static int ehca_dma_map_sg(struct ib_device *dev, struct scatterlist *sgl,
+                          int nents, enum dma_data_direction direction)
+{
+       struct scatterlist *sg;
+       int i;
+
+       for_each_sg(sgl, sg, nents, i) {
+               u64 addr;
+               addr = ehca_map_vaddr(sg_virt(sg));
+               if (ehca_dma_mapping_error(dev, addr))
+                       return 0;
+
+               sg->dma_address = addr;
+               sg->dma_length = sg->length;
+       }
+       return nents;
+}
+
+static void ehca_dma_unmap_sg(struct ib_device *dev, struct scatterlist *sg,
+                             int nents, enum dma_data_direction direction)
+{
+       /* This is only a stub; nothing to be done here */
+}
+
+static void ehca_dma_sync_single_for_cpu(struct ib_device *dev, u64 addr,
+                                        size_t size,
+                                        enum dma_data_direction dir)
+{
+       dma_sync_single_for_cpu(dev->dma_device, addr, size, dir);
+}
+
+static void ehca_dma_sync_single_for_device(struct ib_device *dev, u64 addr,
+                                           size_t size,
+                                           enum dma_data_direction dir)
+{
+       dma_sync_single_for_device(dev->dma_device, addr, size, dir);
+}
+
+static void *ehca_dma_alloc_coherent(struct ib_device *dev, size_t size,
+                                    u64 *dma_handle, gfp_t flag)
+{
+       struct page *p;
+       void *addr = NULL;
+       u64 dma_addr;
+
+       p = alloc_pages(flag, get_order(size));
+       if (p) {
+               addr = page_address(p);
+               dma_addr = ehca_map_vaddr(addr);
+               if (ehca_dma_mapping_error(dev, dma_addr)) {
+                       free_pages((unsigned long)addr, get_order(size));
+                       return NULL;
+               }
+               if (dma_handle)
+                       *dma_handle = dma_addr;
+               return addr;
+       }
+       return NULL;
+}
+
+static void ehca_dma_free_coherent(struct ib_device *dev, size_t size,
+                                  void *cpu_addr, u64 dma_handle)
+{
+       if (cpu_addr && size)
+               free_pages((unsigned long)cpu_addr, get_order(size));
+}
+
+
+struct ib_dma_mapping_ops ehca_dma_mapping_ops = {
+       .mapping_error          = ehca_dma_mapping_error,
+       .map_single             = ehca_dma_map_single,
+       .unmap_single           = ehca_dma_unmap_single,
+       .map_page               = ehca_dma_map_page,
+       .unmap_page             = ehca_dma_unmap_page,
+       .map_sg                 = ehca_dma_map_sg,
+       .unmap_sg               = ehca_dma_unmap_sg,
+       .sync_single_for_cpu    = ehca_dma_sync_single_for_cpu,
+       .sync_single_for_device = ehca_dma_sync_single_for_device,
+       .alloc_coherent         = ehca_dma_alloc_coherent,
+       .free_coherent          = ehca_dma_free_coherent,
+};
diff --git a/drivers/staging/rdma/ehca/ehca_mrmw.h b/drivers/staging/rdma/ehca/ehca_mrmw.h
new file mode 100644 (file)
index 0000000..50d8b51
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ *  IBM eServer eHCA Infiniband device driver for Linux on POWER
+ *
+ *  MR/MW declarations and inline functions
+ *
+ *  Authors: Dietmar Decker <ddecker@de.ibm.com>
+ *           Christoph Raisch <raisch@de.ibm.com>
+ *
+ *  Copyright (c) 2005 IBM Corporation
+ *
+ *  All rights reserved.
+ *
+ *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
+ *  BSD.
+ *
+ * OpenIB BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _EHCA_MRMW_H_
+#define _EHCA_MRMW_H_
+
+enum ehca_reg_type {
+       EHCA_REG_MR,
+       EHCA_REG_BUSMAP_MR
+};
+
+int ehca_reg_mr(struct ehca_shca *shca,
+               struct ehca_mr *e_mr,
+               u64 *iova_start,
+               u64 size,
+               int acl,
+               struct ehca_pd *e_pd,
+               struct ehca_mr_pginfo *pginfo,
+               u32 *lkey,
+               u32 *rkey,
+               enum ehca_reg_type reg_type);
+
+int ehca_reg_mr_rpages(struct ehca_shca *shca,
+                      struct ehca_mr *e_mr,
+                      struct ehca_mr_pginfo *pginfo);
+
+int ehca_rereg_mr(struct ehca_shca *shca,
+                 struct ehca_mr *e_mr,
+                 u64 *iova_start,
+                 u64 size,
+                 int mr_access_flags,
+                 struct ehca_pd *e_pd,
+                 struct ehca_mr_pginfo *pginfo,
+                 u32 *lkey,
+                 u32 *rkey);
+
+int ehca_unmap_one_fmr(struct ehca_shca *shca,
+                      struct ehca_mr *e_fmr);
+
+int ehca_reg_smr(struct ehca_shca *shca,
+                struct ehca_mr *e_origmr,
+                struct ehca_mr *e_newmr,
+                u64 *iova_start,
+                int acl,
+                struct ehca_pd *e_pd,
+                u32 *lkey,
+                u32 *rkey);
+
+int ehca_reg_internal_maxmr(struct ehca_shca *shca,
+                           struct ehca_pd *e_pd,
+                           struct ehca_mr **maxmr);
+
+int ehca_reg_maxmr(struct ehca_shca *shca,
+                  struct ehca_mr *e_newmr,
+                  u64 *iova_start,
+                  int acl,
+                  struct ehca_pd *e_pd,
+                  u32 *lkey,
+                  u32 *rkey);
+
+int ehca_dereg_internal_maxmr(struct ehca_shca *shca);
+
+int ehca_mr_chk_buf_and_calc_size(struct ib_phys_buf *phys_buf_array,
+                                 int num_phys_buf,
+                                 u64 *iova_start,
+                                 u64 *size);
+
+int ehca_fmr_check_page_list(struct ehca_mr *e_fmr,
+                            u64 *page_list,
+                            int list_len);
+
+int ehca_set_pagebuf(struct ehca_mr_pginfo *pginfo,
+                    u32 number,
+                    u64 *kpage);
+
+int ehca_mr_is_maxmr(u64 size,
+                    u64 *iova_start);
+
+void ehca_mrmw_map_acl(int ib_acl,
+                      u32 *hipz_acl);
+
+void ehca_mrmw_set_pgsize_hipz_acl(u32 pgsize, u32 *hipz_acl);
+
+void ehca_mrmw_reverse_map_acl(const u32 *hipz_acl,
+                              int *ib_acl);
+
+void ehca_mr_deletenew(struct ehca_mr *mr);
+
+int ehca_create_busmap(void);
+
+void ehca_destroy_busmap(void);
+
+extern struct ib_dma_mapping_ops ehca_dma_mapping_ops;
+#endif  /*_EHCA_MRMW_H_*/
diff --git a/drivers/staging/rdma/ehca/ehca_pd.c b/drivers/staging/rdma/ehca/ehca_pd.c
new file mode 100644 (file)
index 0000000..351577a
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ *  IBM eServer eHCA Infiniband device driver for Linux on POWER
+ *
+ *  PD functions
+ *
+ *  Authors: Christoph Raisch <raisch@de.ibm.com>
+ *
+ *  Copyright (c) 2005 IBM Corporation
+ *
+ *  All rights reserved.
+ *
+ *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
+ *  BSD.
+ *
+ * OpenIB BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/slab.h>
+
+#include "ehca_tools.h"
+#include "ehca_iverbs.h"
+
+static struct kmem_cache *pd_cache;
+
+struct ib_pd *ehca_alloc_pd(struct ib_device *device,
+                           struct ib_ucontext *context, struct ib_udata *udata)
+{
+       struct ehca_pd *pd;
+       int i;
+
+       pd = kmem_cache_zalloc(pd_cache, GFP_KERNEL);
+       if (!pd) {
+               ehca_err(device, "device=%p context=%p out of memory",
+                        device, context);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       for (i = 0; i < 2; i++) {
+               INIT_LIST_HEAD(&pd->free[i]);
+               INIT_LIST_HEAD(&pd->full[i]);
+       }
+       mutex_init(&pd->lock);
+
+       /*
+        * Kernel PD: when device = -1, 0
+        * User   PD: when context != -1
+        */
+       if (!context) {
+               /*
+                * Kernel PDs after init reuses always
+                * the one created in ehca_shca_reopen()
+                */
+               struct ehca_shca *shca = container_of(device, struct ehca_shca,
+                                                     ib_device);
+               pd->fw_pd.value = shca->pd->fw_pd.value;
+       } else
+               pd->fw_pd.value = (u64)pd;
+
+       return &pd->ib_pd;
+}
+
+int ehca_dealloc_pd(struct ib_pd *pd)
+{
+       struct ehca_pd *my_pd = container_of(pd, struct ehca_pd, ib_pd);
+       int i, leftovers = 0;
+       struct ipz_small_queue_page *page, *tmp;
+
+       for (i = 0; i < 2; i++) {
+               list_splice(&my_pd->full[i], &my_pd->free[i]);
+               list_for_each_entry_safe(page, tmp, &my_pd->free[i], list) {
+                       leftovers = 1;
+                       free_page(page->page);
+                       kmem_cache_free(small_qp_cache, page);
+               }
+       }
+
+       if (leftovers)
+               ehca_warn(pd->device,
+                         "Some small queue pages were not freed");
+
+       kmem_cache_free(pd_cache, my_pd);
+
+       return 0;
+}
+
+int ehca_init_pd_cache(void)
+{
+       pd_cache = kmem_cache_create("ehca_cache_pd",
+                                    sizeof(struct ehca_pd), 0,
+                                    SLAB_HWCACHE_ALIGN,
+                                    NULL);
+       if (!pd_cache)
+               return -ENOMEM;
+       return 0;
+}
+
+void ehca_cleanup_pd_cache(void)
+{
+       if (pd_cache)
+               kmem_cache_destroy(pd_cache);
+}
diff --git a/drivers/staging/rdma/ehca/ehca_qes.h b/drivers/staging/rdma/ehca/ehca_qes.h
new file mode 100644 (file)
index 0000000..90c4efa
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ *  IBM eServer eHCA Infiniband device driver for Linux on POWER
+ *
+ *  Hardware request structures
+ *
+ *  Authors: Waleri Fomin <fomin@de.ibm.com>
+ *           Reinhard Ernst <rernst@de.ibm.com>
+ *           Christoph Raisch <raisch@de.ibm.com>
+ *
+ *  Copyright (c) 2005 IBM Corporation
+ *
+ *  All rights reserved.
+ *
+ *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
+ *  BSD.
+ *
+ * OpenIB BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef _EHCA_QES_H_
+#define _EHCA_QES_H_
+
+#include "ehca_tools.h"
+
+/* virtual scatter gather entry to specify remote addresses with length */
+struct ehca_vsgentry {
+       u64 vaddr;
+       u32 lkey;
+       u32 length;
+};
+
+#define GRH_FLAG_MASK        EHCA_BMASK_IBM( 7,  7)
+#define GRH_IPVERSION_MASK   EHCA_BMASK_IBM( 0,  3)
+#define GRH_TCLASS_MASK      EHCA_BMASK_IBM( 4, 12)
+#define GRH_FLOWLABEL_MASK   EHCA_BMASK_IBM(13, 31)
+#define GRH_PAYLEN_MASK      EHCA_BMASK_IBM(32, 47)
+#define GRH_NEXTHEADER_MASK  EHCA_BMASK_IBM(48, 55)
+#define GRH_HOPLIMIT_MASK    EHCA_BMASK_IBM(56, 63)
+
+/*
+ * Unreliable Datagram Address Vector Format
+ * see IBTA Vol1 chapter 8.3 Global Routing Header
+ */
+struct ehca_ud_av {
+       u8 sl;
+       u8 lnh;
+       u16 dlid;
+       u8 reserved1;
+       u8 reserved2;
+       u8 reserved3;
+       u8 slid_path_bits;
+       u8 reserved4;
+       u8 ipd;
+       u8 reserved5;
+       u8 pmtu;
+       u32 reserved6;
+       u64 reserved7;
+       union {
+               struct {
+                       u64 word_0; /* always set to 6  */
+                       /*should be 0x1B for IB transport */
+                       u64 word_1;
+                       u64 word_2;
+                       u64 word_3;
+                       u64 word_4;
+               } grh;
+               struct {
+                       u32 wd_0;
+                       u32 wd_1;
+                       /* DWord_1 --> SGID */
+
+                       u32 sgid_wd3;
+                       u32 sgid_wd2;
+
+                       u32 sgid_wd1;
+                       u32 sgid_wd0;
+                       /* DWord_3 --> DGID */
+
+                       u32 dgid_wd3;
+                       u32 dgid_wd2;
+
+                       u32 dgid_wd1;
+                       u32 dgid_wd0;
+               } grh_l;
+       };
+};
+
+/* maximum number of sg entries allowed in a WQE */
+#define MAX_WQE_SG_ENTRIES 252
+
+#define WQE_OPTYPE_SEND             0x80
+#define WQE_OPTYPE_RDMAREAD         0x40
+#define WQE_OPTYPE_RDMAWRITE        0x20
+#define WQE_OPTYPE_CMPSWAP          0x10
+#define WQE_OPTYPE_FETCHADD         0x08
+#define WQE_OPTYPE_BIND             0x04
+
+#define WQE_WRFLAG_REQ_SIGNAL_COM   0x80
+#define WQE_WRFLAG_FENCE            0x40
+#define WQE_WRFLAG_IMM_DATA_PRESENT 0x20
+#define WQE_WRFLAG_SOLIC_EVENT      0x10
+
+#define WQEF_CACHE_HINT             0x80
+#define WQEF_CACHE_HINT_RD_WR       0x40
+#define WQEF_TIMED_WQE              0x20
+#define WQEF_PURGE                  0x08
+#define WQEF_HIGH_NIBBLE            0xF0
+
+#define MW_BIND_ACCESSCTRL_R_WRITE   0x40
+#define MW_BIND_ACCESSCTRL_R_READ    0x20
+#define MW_BIND_ACCESSCTRL_R_ATOMIC  0x10
+
+struct ehca_wqe {
+       u64 work_request_id;
+       u8 optype;
+       u8 wr_flag;
+       u16 pkeyi;
+       u8 wqef;
+       u8 nr_of_data_seg;
+       u16 wqe_provided_slid;
+       u32 destination_qp_number;
+       u32 resync_psn_sqp;
+       u32 local_ee_context_qkey;
+       u32 immediate_data;
+       union {
+               struct {
+                       u64 remote_virtual_address;
+                       u32 rkey;
+                       u32 reserved;
+                       u64 atomic_1st_op_dma_len;
+                       u64 atomic_2nd_op;
+                       struct ehca_vsgentry sg_list[MAX_WQE_SG_ENTRIES];
+
+               } nud;
+               struct {
+                       u64 ehca_ud_av_ptr;
+                       u64 reserved1;
+                       u64 reserved2;
+                       u64 reserved3;
+                       struct ehca_vsgentry sg_list[MAX_WQE_SG_ENTRIES];
+               } ud_avp;
+               struct {
+                       struct ehca_ud_av ud_av;
+                       struct ehca_vsgentry sg_list[MAX_WQE_SG_ENTRIES -
+                                                    2];
+               } ud_av;
+               struct {
+                       u64 reserved0;
+                       u64 reserved1;
+                       u64 reserved2;
+                       u64 reserved3;
+                       struct ehca_vsgentry sg_list[MAX_WQE_SG_ENTRIES];
+               } all_rcv;
+
+               struct {
+                       u64 reserved;
+                       u32 rkey;
+                       u32 old_rkey;
+                       u64 reserved1;
+                       u64 reserved2;
+                       u64 virtual_address;
+                       u32 reserved3;
+                       u32 length;
+                       u32 reserved4;
+                       u16 reserved5;
+                       u8 reserved6;
+                       u8 lr_ctl;
+                       u32 lkey;
+                       u32 reserved7;
+                       u64 reserved8;
+                       u64 reserved9;
+                       u64 reserved10;
+                       u64 reserved11;
+               } bind;
+               struct {
+                       u64 reserved12;
+                       u64 reserved13;
+                       u32 size;
+                       u32 start;
+               } inline_data;
+       } u;
+
+};
+
+#define WC_SEND_RECEIVE EHCA_BMASK_IBM(0, 0)
+#define WC_IMM_DATA     EHCA_BMASK_IBM(1, 1)
+#define WC_GRH_PRESENT  EHCA_BMASK_IBM(2, 2)
+#define WC_SE_BIT       EHCA_BMASK_IBM(3, 3)
+#define WC_STATUS_ERROR_BIT 0x80000000
+#define WC_STATUS_REMOTE_ERROR_FLAGS 0x0000F800
+#define WC_STATUS_PURGE_BIT 0x10
+#define WC_SEND_RECEIVE_BIT 0x80
+
+struct ehca_cqe {
+       u64 work_request_id;
+       u8 optype;
+       u8 w_completion_flags;
+       u16 reserved1;
+       u32 nr_bytes_transferred;
+       u32 immediate_data;
+       u32 local_qp_number;
+       u8 freed_resource_count;
+       u8 service_level;
+       u16 wqe_count;
+       u32 qp_token;
+       u32 qkey_ee_token;
+       u32 remote_qp_number;
+       u16 dlid;
+       u16 rlid;
+       u16 reserved2;
+       u16 pkey_index;
+       u32 cqe_timestamp;
+       u32 wqe_timestamp;
+       u8 wqe_timestamp_valid;
+       u8 reserved3;
+       u8 reserved4;
+       u8 cqe_flags;
+       u32 status;
+};
+
+struct ehca_eqe {
+       u64 entry;
+};
+
+struct ehca_mrte {
+       u64 starting_va;
+       u64 length; /* length of memory region in bytes*/
+       u32 pd;
+       u8 key_instance;
+       u8 pagesize;
+       u8 mr_control;
+       u8 local_remote_access_ctrl;
+       u8 reserved[0x20 - 0x18];
+       u64 at_pointer[4];
+};
+#endif /*_EHCA_QES_H_*/
diff --git a/drivers/staging/rdma/ehca/ehca_qp.c b/drivers/staging/rdma/ehca/ehca_qp.c
new file mode 100644 (file)
index 0000000..2e89356
--- /dev/null
@@ -0,0 +1,2257 @@
+/*
+ *  IBM eServer eHCA Infiniband device driver for Linux on POWER
+ *
+ *  QP functions
+ *
+ *  Authors: Joachim Fenkes <fenkes@de.ibm.com>
+ *           Stefan Roscher <stefan.roscher@de.ibm.com>
+ *           Waleri Fomin <fomin@de.ibm.com>
+ *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
+ *           Reinhard Ernst <rernst@de.ibm.com>
+ *           Heiko J Schick <schickhj@de.ibm.com>
+ *
+ *  Copyright (c) 2005 IBM Corporation
+ *
+ *  All rights reserved.
+ *
+ *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
+ *  BSD.
+ *
+ * OpenIB BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/slab.h>
+
+#include "ehca_classes.h"
+#include "ehca_tools.h"
+#include "ehca_qes.h"
+#include "ehca_iverbs.h"
+#include "hcp_if.h"
+#include "hipz_fns.h"
+
+static struct kmem_cache *qp_cache;
+
+/*
+ * attributes not supported by query qp
+ */
+#define QP_ATTR_QUERY_NOT_SUPPORTED (IB_QP_ACCESS_FLAGS       | \
+                                    IB_QP_EN_SQD_ASYNC_NOTIFY)
+
+/*
+ * ehca (internal) qp state values
+ */
+enum ehca_qp_state {
+       EHCA_QPS_RESET = 1,
+       EHCA_QPS_INIT = 2,
+       EHCA_QPS_RTR = 3,
+       EHCA_QPS_RTS = 5,
+       EHCA_QPS_SQD = 6,
+       EHCA_QPS_SQE = 8,
+       EHCA_QPS_ERR = 128
+};
+
+/*
+ * qp state transitions as defined by IB Arch Rel 1.1 page 431
+ */
+enum ib_qp_statetrans {
+       IB_QPST_ANY2RESET,
+       IB_QPST_ANY2ERR,
+       IB_QPST_RESET2INIT,
+       IB_QPST_INIT2RTR,
+       IB_QPST_INIT2INIT,
+       IB_QPST_RTR2RTS,
+       IB_QPST_RTS2SQD,
+       IB_QPST_RTS2RTS,
+       IB_QPST_SQD2RTS,
+       IB_QPST_SQE2RTS,
+       IB_QPST_SQD2SQD,
+       IB_QPST_MAX     /* nr of transitions, this must be last!!! */
+};
+
+/*
+ * ib2ehca_qp_state maps IB to ehca qp_state
+ * returns ehca qp state corresponding to given ib qp state
+ */
+static inline enum ehca_qp_state ib2ehca_qp_state(enum ib_qp_state ib_qp_state)
+{
+       switch (ib_qp_state) {
+       case IB_QPS_RESET:
+               return EHCA_QPS_RESET;
+       case IB_QPS_INIT:
+               return EHCA_QPS_INIT;
+       case IB_QPS_RTR:
+               return EHCA_QPS_RTR;
+       case IB_QPS_RTS:
+               return EHCA_QPS_RTS;
+       case IB_QPS_SQD:
+               return EHCA_QPS_SQD;
+       case IB_QPS_SQE:
+               return EHCA_QPS_SQE;
+       case IB_QPS_ERR:
+               return EHCA_QPS_ERR;
+       default:
+               ehca_gen_err("invalid ib_qp_state=%x", ib_qp_state);
+               return -EINVAL;
+       }
+}
+
+/*
+ * ehca2ib_qp_state maps ehca to IB qp_state
+ * returns ib qp state corresponding to given ehca qp state
+ */
+static inline enum ib_qp_state ehca2ib_qp_state(enum ehca_qp_state
+                                               ehca_qp_state)
+{
+       switch (ehca_qp_state) {
+       case EHCA_QPS_RESET:
+               return IB_QPS_RESET;
+       case EHCA_QPS_INIT:
+               return IB_QPS_INIT;
+       case EHCA_QPS_RTR:
+               return IB_QPS_RTR;
+       case EHCA_QPS_RTS:
+               return IB_QPS_RTS;
+       case EHCA_QPS_SQD:
+               return IB_QPS_SQD;
+       case EHCA_QPS_SQE:
+               return IB_QPS_SQE;
+       case EHCA_QPS_ERR:
+               return IB_QPS_ERR;
+       default:
+               ehca_gen_err("invalid ehca_qp_state=%x", ehca_qp_state);
+               return -EINVAL;
+       }
+}
+
+/*
+ * ehca_qp_type used as index for req_attr and opt_attr of
+ * struct ehca_modqp_statetrans
+ */
+enum ehca_qp_type {
+       QPT_RC = 0,
+       QPT_UC = 1,
+       QPT_UD = 2,
+       QPT_SQP = 3,
+       QPT_MAX
+};
+
+/*
+ * ib2ehcaqptype maps Ib to ehca qp_type
+ * returns ehca qp type corresponding to ib qp type
+ */
+static inline enum ehca_qp_type ib2ehcaqptype(enum ib_qp_type ibqptype)
+{
+       switch (ibqptype) {
+       case IB_QPT_SMI:
+       case IB_QPT_GSI:
+               return QPT_SQP;
+       case IB_QPT_RC:
+               return QPT_RC;
+       case IB_QPT_UC:
+               return QPT_UC;
+       case IB_QPT_UD:
+               return QPT_UD;
+       default:
+               ehca_gen_err("Invalid ibqptype=%x", ibqptype);
+               return -EINVAL;
+       }
+}
+
+static inline enum ib_qp_statetrans get_modqp_statetrans(int ib_fromstate,
+                                                        int ib_tostate)
+{
+       int index = -EINVAL;
+       switch (ib_tostate) {
+       case IB_QPS_RESET:
+               index = IB_QPST_ANY2RESET;
+               break;
+       case IB_QPS_INIT:
+               switch (ib_fromstate) {
+               case IB_QPS_RESET:
+                       index = IB_QPST_RESET2INIT;
+                       break;
+               case IB_QPS_INIT:
+                       index = IB_QPST_INIT2INIT;
+                       break;
+               }
+               break;
+       case IB_QPS_RTR:
+               if (ib_fromstate == IB_QPS_INIT)
+                       index = IB_QPST_INIT2RTR;
+               break;
+       case IB_QPS_RTS:
+               switch (ib_fromstate) {
+               case IB_QPS_RTR:
+                       index = IB_QPST_RTR2RTS;
+                       break;
+               case IB_QPS_RTS:
+                       index = IB_QPST_RTS2RTS;
+                       break;
+               case IB_QPS_SQD:
+                       index = IB_QPST_SQD2RTS;
+                       break;
+               case IB_QPS_SQE:
+                       index = IB_QPST_SQE2RTS;
+                       break;
+               }
+               break;
+       case IB_QPS_SQD:
+               if (ib_fromstate == IB_QPS_RTS)
+                       index = IB_QPST_RTS2SQD;
+               break;
+       case IB_QPS_SQE:
+               break;
+       case IB_QPS_ERR:
+               index = IB_QPST_ANY2ERR;
+               break;
+       default:
+               break;
+       }
+       return index;
+}
+
+/*
+ * ibqptype2servicetype returns hcp service type corresponding to given
+ * ib qp type used by create_qp()
+ */
+static inline int ibqptype2servicetype(enum ib_qp_type ibqptype)
+{
+       switch (ibqptype) {
+       case IB_QPT_SMI:
+       case IB_QPT_GSI:
+               return ST_UD;
+       case IB_QPT_RC:
+               return ST_RC;
+       case IB_QPT_UC:
+               return ST_UC;
+       case IB_QPT_UD:
+               return ST_UD;
+       case IB_QPT_RAW_IPV6:
+               return -EINVAL;
+       case IB_QPT_RAW_ETHERTYPE:
+               return -EINVAL;
+       default:
+               ehca_gen_err("Invalid ibqptype=%x", ibqptype);
+               return -EINVAL;
+       }
+}
+
+/*
+ * init userspace queue info from ipz_queue data
+ */
+static inline void queue2resp(struct ipzu_queue_resp *resp,
+                             struct ipz_queue *queue)
+{
+       resp->qe_size = queue->qe_size;
+       resp->act_nr_of_sg = queue->act_nr_of_sg;
+       resp->queue_length = queue->queue_length;
+       resp->pagesize = queue->pagesize;
+       resp->toggle_state = queue->toggle_state;
+       resp->offset = queue->offset;
+}
+
+/*
+ * init_qp_queue initializes/constructs r/squeue and registers queue pages.
+ */
+static inline int init_qp_queue(struct ehca_shca *shca,
+                               struct ehca_pd *pd,
+                               struct ehca_qp *my_qp,
+                               struct ipz_queue *queue,
+                               int q_type,
+                               u64 expected_hret,
+                               struct ehca_alloc_queue_parms *parms,
+                               int wqe_size)
+{
+       int ret, cnt, ipz_rc, nr_q_pages;
+       void *vpage;
+       u64 rpage, h_ret;
+       struct ib_device *ib_dev = &shca->ib_device;
+       struct ipz_adapter_handle ipz_hca_handle = shca->ipz_hca_handle;
+
+       if (!parms->queue_size)
+               return 0;
+
+       if (parms->is_small) {
+               nr_q_pages = 1;
+               ipz_rc = ipz_queue_ctor(pd, queue, nr_q_pages,
+                                       128 << parms->page_size,
+                                       wqe_size, parms->act_nr_sges, 1);
+       } else {
+               nr_q_pages = parms->queue_size;
+               ipz_rc = ipz_queue_ctor(pd, queue, nr_q_pages,
+                                       EHCA_PAGESIZE, wqe_size,
+                                       parms->act_nr_sges, 0);
+       }
+
+       if (!ipz_rc) {
+               ehca_err(ib_dev, "Cannot allocate page for queue. ipz_rc=%i",
+                        ipz_rc);
+               return -EBUSY;
+       }
+
+       /* register queue pages */
+       for (cnt = 0; cnt < nr_q_pages; cnt++) {
+               vpage = ipz_qpageit_get_inc(queue);
+               if (!vpage) {
+                       ehca_err(ib_dev, "ipz_qpageit_get_inc() "
+                                "failed p_vpage= %p", vpage);
+                       ret = -EINVAL;
+                       goto init_qp_queue1;
+               }
+               rpage = __pa(vpage);
+
+               h_ret = hipz_h_register_rpage_qp(ipz_hca_handle,
+                                                my_qp->ipz_qp_handle,
+                                                NULL, 0, q_type,
+                                                rpage, parms->is_small ? 0 : 1,
+                                                my_qp->galpas.kernel);
+               if (cnt == (nr_q_pages - 1)) {  /* last page! */
+                       if (h_ret != expected_hret) {
+                               ehca_err(ib_dev, "hipz_qp_register_rpage() "
+                                        "h_ret=%lli", h_ret);
+                               ret = ehca2ib_return_code(h_ret);
+                               goto init_qp_queue1;
+                       }
+                       vpage = ipz_qpageit_get_inc(&my_qp->ipz_rqueue);
+                       if (vpage) {
+                               ehca_err(ib_dev, "ipz_qpageit_get_inc() "
+                                        "should not succeed vpage=%p", vpage);
+                               ret = -EINVAL;
+                               goto init_qp_queue1;
+                       }
+               } else {
+                       if (h_ret != H_PAGE_REGISTERED) {
+                               ehca_err(ib_dev, "hipz_qp_register_rpage() "
+                                        "h_ret=%lli", h_ret);
+                               ret = ehca2ib_return_code(h_ret);
+                               goto init_qp_queue1;
+                       }
+               }
+       }
+
+       ipz_qeit_reset(queue);
+
+       return 0;
+
+init_qp_queue1:
+       ipz_queue_dtor(pd, queue);
+       return ret;
+}
+
+static inline int ehca_calc_wqe_size(int act_nr_sge, int is_llqp)
+{
+       if (is_llqp)
+               return 128 << act_nr_sge;
+       else
+               return offsetof(struct ehca_wqe,
+                               u.nud.sg_list[act_nr_sge]);
+}
+
+static void ehca_determine_small_queue(struct ehca_alloc_queue_parms *queue,
+                                      int req_nr_sge, int is_llqp)
+{
+       u32 wqe_size, q_size;
+       int act_nr_sge = req_nr_sge;
+
+       if (!is_llqp)
+               /* round up #SGEs so WQE size is a power of 2 */
+               for (act_nr_sge = 4; act_nr_sge <= 252;
+                    act_nr_sge = 4 + 2 * act_nr_sge)
+                       if (act_nr_sge >= req_nr_sge)
+                               break;
+
+       wqe_size = ehca_calc_wqe_size(act_nr_sge, is_llqp);
+       q_size = wqe_size * (queue->max_wr + 1);
+
+       if (q_size <= 512)
+               queue->page_size = 2;
+       else if (q_size <= 1024)
+               queue->page_size = 3;
+       else
+               queue->page_size = 0;
+
+       queue->is_small = (queue->page_size != 0);
+}
+
+/* needs to be called with cq->spinlock held */
+void ehca_add_to_err_list(struct ehca_qp *qp, int on_sq)
+{
+       struct list_head *list, *node;
+
+       /* TODO: support low latency QPs */
+       if (qp->ext_type == EQPT_LLQP)
+               return;
+
+       if (on_sq) {
+               list = &qp->send_cq->sqp_err_list;
+               node = &qp->sq_err_node;
+       } else {
+               list = &qp->recv_cq->rqp_err_list;
+               node = &qp->rq_err_node;
+       }
+
+       if (list_empty(node))
+               list_add_tail(node, list);
+
+       return;
+}
+
+static void del_from_err_list(struct ehca_cq *cq, struct list_head *node)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&cq->spinlock, flags);
+
+       if (!list_empty(node))
+               list_del_init(node);
+
+       spin_unlock_irqrestore(&cq->spinlock, flags);
+}
+
+static void reset_queue_map(struct ehca_queue_map *qmap)
+{
+       int i;
+
+       qmap->tail = qmap->entries - 1;
+       qmap->left_to_poll = 0;
+       qmap->next_wqe_idx = 0;
+       for (i = 0; i < qmap->entries; i++) {
+               qmap->map[i].reported = 1;
+               qmap->map[i].cqe_req = 0;
+       }
+}
+
+/*
+ * Create an ib_qp struct that is either a QP or an SRQ, depending on
+ * the value of the is_srq parameter. If init_attr and srq_init_attr share
+ * fields, the field out of init_attr is used.
+ */
+static struct ehca_qp *internal_create_qp(
+       struct ib_pd *pd,
+       struct ib_qp_init_attr *init_attr,
+       struct ib_srq_init_attr *srq_init_attr,
+       struct ib_udata *udata, int is_srq)
+{
+       struct ehca_qp *my_qp, *my_srq = NULL;
+       struct ehca_pd *my_pd = container_of(pd, struct ehca_pd, ib_pd);
+       struct ehca_shca *shca = container_of(pd->device, struct ehca_shca,
+                                             ib_device);
+       struct ib_ucontext *context = NULL;
+       u64 h_ret;
+       int is_llqp = 0, has_srq = 0, is_user = 0;
+       int qp_type, max_send_sge, max_recv_sge, ret;
+
+       /* h_call's out parameters */
+       struct ehca_alloc_qp_parms parms;
+       u32 swqe_size = 0, rwqe_size = 0, ib_qp_num;
+       unsigned long flags;
+
+       if (!atomic_add_unless(&shca->num_qps, 1, shca->max_num_qps)) {
+               ehca_err(pd->device, "Unable to create QP, max number of %i "
+                        "QPs reached.", shca->max_num_qps);
+               ehca_err(pd->device, "To increase the maximum number of QPs "
+                        "use the number_of_qps module parameter.\n");
+               return ERR_PTR(-ENOSPC);
+       }
+
+       if (init_attr->create_flags) {
+               atomic_dec(&shca->num_qps);
+               return ERR_PTR(-EINVAL);
+       }
+
+       memset(&parms, 0, sizeof(parms));
+       qp_type = init_attr->qp_type;
+
+       if (init_attr->sq_sig_type != IB_SIGNAL_REQ_WR &&
+               init_attr->sq_sig_type != IB_SIGNAL_ALL_WR) {
+               ehca_err(pd->device, "init_attr->sg_sig_type=%x not allowed",
+                        init_attr->sq_sig_type);
+               atomic_dec(&shca->num_qps);
+               return ERR_PTR(-EINVAL);
+       }
+
+       /* save LLQP info */
+       if (qp_type & 0x80) {
+               is_llqp = 1;
+               parms.ext_type = EQPT_LLQP;
+               parms.ll_comp_flags = qp_type & LLQP_COMP_MASK;
+       }
+       qp_type &= 0x1F;
+       init_attr->qp_type &= 0x1F;
+
+       /* handle SRQ base QPs */
+       if (init_attr->srq) {
+               my_srq = container_of(init_attr->srq, struct ehca_qp, ib_srq);
+
+               if (qp_type == IB_QPT_UC) {
+                       ehca_err(pd->device, "UC with SRQ not supported");
+                       atomic_dec(&shca->num_qps);
+                       return ERR_PTR(-EINVAL);
+               }
+
+               has_srq = 1;
+               parms.ext_type = EQPT_SRQBASE;
+               parms.srq_qpn = my_srq->real_qp_num;
+       }
+
+       if (is_llqp && has_srq) {
+               ehca_err(pd->device, "LLQPs can't have an SRQ");
+               atomic_dec(&shca->num_qps);
+               return ERR_PTR(-EINVAL);
+       }
+
+       /* handle SRQs */
+       if (is_srq) {
+               parms.ext_type = EQPT_SRQ;
+               parms.srq_limit = srq_init_attr->attr.srq_limit;
+               if (init_attr->cap.max_recv_sge > 3) {
+                       ehca_err(pd->device, "no more than three SGEs "
+                                "supported for SRQ  pd=%p  max_sge=%x",
+                                pd, init_attr->cap.max_recv_sge);
+                       atomic_dec(&shca->num_qps);
+                       return ERR_PTR(-EINVAL);
+               }
+       }
+
+       /* check QP type */
+       if (qp_type != IB_QPT_UD &&
+           qp_type != IB_QPT_UC &&
+           qp_type != IB_QPT_RC &&
+           qp_type != IB_QPT_SMI &&
+           qp_type != IB_QPT_GSI) {
+               ehca_err(pd->device, "wrong QP Type=%x", qp_type);
+               atomic_dec(&shca->num_qps);
+               return ERR_PTR(-EINVAL);
+       }
+
+       if (is_llqp) {
+               switch (qp_type) {
+               case IB_QPT_RC:
+                       if ((init_attr->cap.max_send_wr > 255) ||
+                           (init_attr->cap.max_recv_wr > 255)) {
+                               ehca_err(pd->device,
+                                        "Invalid Number of max_sq_wr=%x "
+                                        "or max_rq_wr=%x for RC LLQP",
+                                        init_attr->cap.max_send_wr,
+                                        init_attr->cap.max_recv_wr);
+                               atomic_dec(&shca->num_qps);
+                               return ERR_PTR(-EINVAL);
+                       }
+                       break;
+               case IB_QPT_UD:
+                       if (!EHCA_BMASK_GET(HCA_CAP_UD_LL_QP, shca->hca_cap)) {
+                               ehca_err(pd->device, "UD LLQP not supported "
+                                        "by this adapter");
+                               atomic_dec(&shca->num_qps);
+                               return ERR_PTR(-ENOSYS);
+                       }
+                       if (!(init_attr->cap.max_send_sge <= 5
+                           && init_attr->cap.max_send_sge >= 1
+                           && init_attr->cap.max_recv_sge <= 5
+                           && init_attr->cap.max_recv_sge >= 1)) {
+                               ehca_err(pd->device,
+                                        "Invalid Number of max_send_sge=%x "
+                                        "or max_recv_sge=%x for UD LLQP",
+                                        init_attr->cap.max_send_sge,
+                                        init_attr->cap.max_recv_sge);
+                               atomic_dec(&shca->num_qps);
+                               return ERR_PTR(-EINVAL);
+                       } else if (init_attr->cap.max_send_wr > 255) {
+                               ehca_err(pd->device,
+                                        "Invalid Number of "
+                                        "max_send_wr=%x for UD QP_TYPE=%x",
+                                        init_attr->cap.max_send_wr, qp_type);
+                               atomic_dec(&shca->num_qps);
+                               return ERR_PTR(-EINVAL);
+                       }
+                       break;
+               default:
+                       ehca_err(pd->device, "unsupported LL QP Type=%x",
+                                qp_type);
+                       atomic_dec(&shca->num_qps);
+                       return ERR_PTR(-EINVAL);
+               }
+       } else {
+               int max_sge = (qp_type == IB_QPT_UD || qp_type == IB_QPT_SMI
+                              || qp_type == IB_QPT_GSI) ? 250 : 252;
+
+               if (init_attr->cap.max_send_sge > max_sge
+                   || init_attr->cap.max_recv_sge > max_sge) {
+                       ehca_err(pd->device, "Invalid number of SGEs requested "
+                                "send_sge=%x recv_sge=%x max_sge=%x",
+                                init_attr->cap.max_send_sge,
+                                init_attr->cap.max_recv_sge, max_sge);
+                       atomic_dec(&shca->num_qps);
+                       return ERR_PTR(-EINVAL);
+               }
+       }
+
+       my_qp = kmem_cache_zalloc(qp_cache, GFP_KERNEL);
+       if (!my_qp) {
+               ehca_err(pd->device, "pd=%p not enough memory to alloc qp", pd);
+               atomic_dec(&shca->num_qps);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       if (pd->uobject && udata) {
+               is_user = 1;
+               context = pd->uobject->context;
+       }
+
+       atomic_set(&my_qp->nr_events, 0);
+       init_waitqueue_head(&my_qp->wait_completion);
+       spin_lock_init(&my_qp->spinlock_s);
+       spin_lock_init(&my_qp->spinlock_r);
+       my_qp->qp_type = qp_type;
+       my_qp->ext_type = parms.ext_type;
+       my_qp->state = IB_QPS_RESET;
+
+       if (init_attr->recv_cq)
+               my_qp->recv_cq =
+                       container_of(init_attr->recv_cq, struct ehca_cq, ib_cq);
+       if (init_attr->send_cq)
+               my_qp->send_cq =
+                       container_of(init_attr->send_cq, struct ehca_cq, ib_cq);
+
+       idr_preload(GFP_KERNEL);
+       write_lock_irqsave(&ehca_qp_idr_lock, flags);
+
+       ret = idr_alloc(&ehca_qp_idr, my_qp, 0, 0x2000000, GFP_NOWAIT);
+       if (ret >= 0)
+               my_qp->token = ret;
+
+       write_unlock_irqrestore(&ehca_qp_idr_lock, flags);
+       idr_preload_end();
+       if (ret < 0) {
+               if (ret == -ENOSPC) {
+                       ret = -EINVAL;
+                       ehca_err(pd->device, "Invalid number of qp");
+               } else {
+                       ret = -ENOMEM;
+                       ehca_err(pd->device, "Can't allocate new idr entry.");
+               }
+               goto create_qp_exit0;
+       }
+
+       if (has_srq)
+               parms.srq_token = my_qp->token;
+
+       parms.servicetype = ibqptype2servicetype(qp_type);
+       if (parms.servicetype < 0) {
+               ret = -EINVAL;
+               ehca_err(pd->device, "Invalid qp_type=%x", qp_type);
+               goto create_qp_exit1;
+       }
+
+       /* Always signal by WQE so we can hide circ. WQEs */
+       parms.sigtype = HCALL_SIGT_BY_WQE;
+
+       /* UD_AV CIRCUMVENTION */
+       max_send_sge = init_attr->cap.max_send_sge;
+       max_recv_sge = init_attr->cap.max_recv_sge;
+       if (parms.servicetype == ST_UD && !is_llqp) {
+               max_send_sge += 2;
+               max_recv_sge += 2;
+       }
+
+       parms.token = my_qp->token;
+       parms.eq_handle = shca->eq.ipz_eq_handle;
+       parms.pd = my_pd->fw_pd;
+       if (my_qp->send_cq)
+               parms.send_cq_handle = my_qp->send_cq->ipz_cq_handle;
+       if (my_qp->recv_cq)
+               parms.recv_cq_handle = my_qp->recv_cq->ipz_cq_handle;
+
+       parms.squeue.max_wr = init_attr->cap.max_send_wr;
+       parms.rqueue.max_wr = init_attr->cap.max_recv_wr;
+       parms.squeue.max_sge = max_send_sge;
+       parms.rqueue.max_sge = max_recv_sge;
+
+       /* RC QPs need one more SWQE for unsolicited ack circumvention */
+       if (qp_type == IB_QPT_RC)
+               parms.squeue.max_wr++;
+
+       if (EHCA_BMASK_GET(HCA_CAP_MINI_QP, shca->hca_cap)) {
+               if (HAS_SQ(my_qp))
+                       ehca_determine_small_queue(
+                               &parms.squeue, max_send_sge, is_llqp);
+               if (HAS_RQ(my_qp))
+                       ehca_determine_small_queue(
+                               &parms.rqueue, max_recv_sge, is_llqp);
+               parms.qp_storage =
+                       (parms.squeue.is_small || parms.rqueue.is_small);
+       }
+
+       h_ret = hipz_h_alloc_resource_qp(shca->ipz_hca_handle, &parms, is_user);
+       if (h_ret != H_SUCCESS) {
+               ehca_err(pd->device, "h_alloc_resource_qp() failed h_ret=%lli",
+                        h_ret);
+               ret = ehca2ib_return_code(h_ret);
+               goto create_qp_exit1;
+       }
+
+       ib_qp_num = my_qp->real_qp_num = parms.real_qp_num;
+       my_qp->ipz_qp_handle = parms.qp_handle;
+       my_qp->galpas = parms.galpas;
+
+       swqe_size = ehca_calc_wqe_size(parms.squeue.act_nr_sges, is_llqp);
+       rwqe_size = ehca_calc_wqe_size(parms.rqueue.act_nr_sges, is_llqp);
+
+       switch (qp_type) {
+       case IB_QPT_RC:
+               if (is_llqp) {
+                       parms.squeue.act_nr_sges = 1;
+                       parms.rqueue.act_nr_sges = 1;
+               }
+               /* hide the extra WQE */
+               parms.squeue.act_nr_wqes--;
+               break;
+       case IB_QPT_UD:
+       case IB_QPT_GSI:
+       case IB_QPT_SMI:
+               /* UD circumvention */
+               if (is_llqp) {
+                       parms.squeue.act_nr_sges = 1;
+                       parms.rqueue.act_nr_sges = 1;
+               } else {
+                       parms.squeue.act_nr_sges -= 2;
+                       parms.rqueue.act_nr_sges -= 2;
+               }
+
+               if (IB_QPT_GSI == qp_type || IB_QPT_SMI == qp_type) {
+                       parms.squeue.act_nr_wqes = init_attr->cap.max_send_wr;
+                       parms.rqueue.act_nr_wqes = init_attr->cap.max_recv_wr;
+                       parms.squeue.act_nr_sges = init_attr->cap.max_send_sge;
+                       parms.rqueue.act_nr_sges = init_attr->cap.max_recv_sge;
+                       ib_qp_num = (qp_type == IB_QPT_SMI) ? 0 : 1;
+               }
+
+               break;
+
+       default:
+               break;
+       }
+
+       /* initialize r/squeue and register queue pages */
+       if (HAS_SQ(my_qp)) {
+               ret = init_qp_queue(
+                       shca, my_pd, my_qp, &my_qp->ipz_squeue, 0,
+                       HAS_RQ(my_qp) ? H_PAGE_REGISTERED : H_SUCCESS,
+                       &parms.squeue, swqe_size);
+               if (ret) {
+                       ehca_err(pd->device, "Couldn't initialize squeue "
+                                "and pages ret=%i", ret);
+                       goto create_qp_exit2;
+               }
+
+               if (!is_user) {
+                       my_qp->sq_map.entries = my_qp->ipz_squeue.queue_length /
+                               my_qp->ipz_squeue.qe_size;
+                       my_qp->sq_map.map = vmalloc(my_qp->sq_map.entries *
+                                                   sizeof(struct ehca_qmap_entry));
+                       if (!my_qp->sq_map.map) {
+                               ehca_err(pd->device, "Couldn't allocate squeue "
+                                        "map ret=%i", ret);
+                               goto create_qp_exit3;
+                       }
+                       INIT_LIST_HEAD(&my_qp->sq_err_node);
+                       /* to avoid the generation of bogus flush CQEs */
+                       reset_queue_map(&my_qp->sq_map);
+               }
+       }
+
+       if (HAS_RQ(my_qp)) {
+               ret = init_qp_queue(
+                       shca, my_pd, my_qp, &my_qp->ipz_rqueue, 1,
+                       H_SUCCESS, &parms.rqueue, rwqe_size);
+               if (ret) {
+                       ehca_err(pd->device, "Couldn't initialize rqueue "
+                                "and pages ret=%i", ret);
+                       goto create_qp_exit4;
+               }
+               if (!is_user) {
+                       my_qp->rq_map.entries = my_qp->ipz_rqueue.queue_length /
+                               my_qp->ipz_rqueue.qe_size;
+                       my_qp->rq_map.map = vmalloc(my_qp->rq_map.entries *
+                                                   sizeof(struct ehca_qmap_entry));
+                       if (!my_qp->rq_map.map) {
+                               ehca_err(pd->device, "Couldn't allocate squeue "
+                                        "map ret=%i", ret);
+                               goto create_qp_exit5;
+                       }
+                       INIT_LIST_HEAD(&my_qp->rq_err_node);
+                       /* to avoid the generation of bogus flush CQEs */
+                       reset_queue_map(&my_qp->rq_map);
+               }
+       } else if (init_attr->srq && !is_user) {
+               /* this is a base QP, use the queue map of the SRQ */
+               my_qp->rq_map = my_srq->rq_map;
+               INIT_LIST_HEAD(&my_qp->rq_err_node);
+
+               my_qp->ipz_rqueue = my_srq->ipz_rqueue;
+       }
+
+       if (is_srq) {
+               my_qp->ib_srq.pd = &my_pd->ib_pd;
+               my_qp->ib_srq.device = my_pd->ib_pd.device;
+
+               my_qp->ib_srq.srq_context = init_attr->qp_context;
+               my_qp->ib_srq.event_handler = init_attr->event_handler;
+       } else {
+               my_qp->ib_qp.qp_num = ib_qp_num;
+               my_qp->ib_qp.pd = &my_pd->ib_pd;
+               my_qp->ib_qp.device = my_pd->ib_pd.device;
+
+               my_qp->ib_qp.recv_cq = init_attr->recv_cq;
+               my_qp->ib_qp.send_cq = init_attr->send_cq;
+
+               my_qp->ib_qp.qp_type = qp_type;
+               my_qp->ib_qp.srq = init_attr->srq;
+
+               my_qp->ib_qp.qp_context = init_attr->qp_context;
+               my_qp->ib_qp.event_handler = init_attr->event_handler;
+       }
+
+       init_attr->cap.max_inline_data = 0; /* not supported yet */
+       init_attr->cap.max_recv_sge = parms.rqueue.act_nr_sges;
+       init_attr->cap.max_recv_wr = parms.rqueue.act_nr_wqes;
+       init_attr->cap.max_send_sge = parms.squeue.act_nr_sges;
+       init_attr->cap.max_send_wr = parms.squeue.act_nr_wqes;
+       my_qp->init_attr = *init_attr;
+
+       if (qp_type == IB_QPT_SMI || qp_type == IB_QPT_GSI) {
+               shca->sport[init_attr->port_num - 1].ibqp_sqp[qp_type] =
+                       &my_qp->ib_qp;
+               if (ehca_nr_ports < 0) {
+                       /* alloc array to cache subsequent modify qp parms
+                        * for autodetect mode
+                        */
+                       my_qp->mod_qp_parm =
+                               kzalloc(EHCA_MOD_QP_PARM_MAX *
+                                       sizeof(*my_qp->mod_qp_parm),
+                                       GFP_KERNEL);
+                       if (!my_qp->mod_qp_parm) {
+                               ehca_err(pd->device,
+                                        "Could not alloc mod_qp_parm");
+                               goto create_qp_exit5;
+                       }
+               }
+       }
+
+       /* NOTE: define_apq0() not supported yet */
+       if (qp_type == IB_QPT_GSI) {
+               h_ret = ehca_define_sqp(shca, my_qp, init_attr);
+               if (h_ret != H_SUCCESS) {
+                       kfree(my_qp->mod_qp_parm);
+                       my_qp->mod_qp_parm = NULL;
+                       /* the QP pointer is no longer valid */
+                       shca->sport[init_attr->port_num - 1].ibqp_sqp[qp_type] =
+                               NULL;
+                       ret = ehca2ib_return_code(h_ret);
+                       goto create_qp_exit6;
+               }
+       }
+
+       if (my_qp->send_cq) {
+               ret = ehca_cq_assign_qp(my_qp->send_cq, my_qp);
+               if (ret) {
+                       ehca_err(pd->device,
+                                "Couldn't assign qp to send_cq ret=%i", ret);
+                       goto create_qp_exit7;
+               }
+       }
+
+       /* copy queues, galpa data to user space */
+       if (context && udata) {
+               struct ehca_create_qp_resp resp;
+               memset(&resp, 0, sizeof(resp));
+
+               resp.qp_num = my_qp->real_qp_num;
+               resp.token = my_qp->token;
+               resp.qp_type = my_qp->qp_type;
+               resp.ext_type = my_qp->ext_type;
+               resp.qkey = my_qp->qkey;
+               resp.real_qp_num = my_qp->real_qp_num;
+
+               if (HAS_SQ(my_qp))
+                       queue2resp(&resp.ipz_squeue, &my_qp->ipz_squeue);
+               if (HAS_RQ(my_qp))
+                       queue2resp(&resp.ipz_rqueue, &my_qp->ipz_rqueue);
+               resp.fw_handle_ofs = (u32)
+                       (my_qp->galpas.user.fw_handle & (PAGE_SIZE - 1));
+
+               if (ib_copy_to_udata(udata, &resp, sizeof resp)) {
+                       ehca_err(pd->device, "Copy to udata failed");
+                       ret = -EINVAL;
+                       goto create_qp_exit8;
+               }
+       }
+
+       return my_qp;
+
+create_qp_exit8:
+       ehca_cq_unassign_qp(my_qp->send_cq, my_qp->real_qp_num);
+
+create_qp_exit7:
+       kfree(my_qp->mod_qp_parm);
+
+create_qp_exit6:
+       if (HAS_RQ(my_qp) && !is_user)
+               vfree(my_qp->rq_map.map);
+
+create_qp_exit5:
+       if (HAS_RQ(my_qp))
+               ipz_queue_dtor(my_pd, &my_qp->ipz_rqueue);
+
+create_qp_exit4:
+       if (HAS_SQ(my_qp) && !is_user)
+               vfree(my_qp->sq_map.map);
+
+create_qp_exit3:
+       if (HAS_SQ(my_qp))
+               ipz_queue_dtor(my_pd, &my_qp->ipz_squeue);
+
+create_qp_exit2:
+       hipz_h_destroy_qp(shca->ipz_hca_handle, my_qp);
+
+create_qp_exit1:
+       write_lock_irqsave(&ehca_qp_idr_lock, flags);
+       idr_remove(&ehca_qp_idr, my_qp->token);
+       write_unlock_irqrestore(&ehca_qp_idr_lock, flags);
+
+create_qp_exit0:
+       kmem_cache_free(qp_cache, my_qp);
+       atomic_dec(&shca->num_qps);
+       return ERR_PTR(ret);
+}
+
+struct ib_qp *ehca_create_qp(struct ib_pd *pd,
+                            struct ib_qp_init_attr *qp_init_attr,
+                            struct ib_udata *udata)
+{
+       struct ehca_qp *ret;
+
+       ret = internal_create_qp(pd, qp_init_attr, NULL, udata, 0);
+       return IS_ERR(ret) ? (struct ib_qp *)ret : &ret->ib_qp;
+}
+
+static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
+                              struct ib_uobject *uobject);
+
+struct ib_srq *ehca_create_srq(struct ib_pd *pd,
+                              struct ib_srq_init_attr *srq_init_attr,
+                              struct ib_udata *udata)
+{
+       struct ib_qp_init_attr qp_init_attr;
+       struct ehca_qp *my_qp;
+       struct ib_srq *ret;
+       struct ehca_shca *shca = container_of(pd->device, struct ehca_shca,
+                                             ib_device);
+       struct hcp_modify_qp_control_block *mqpcb;
+       u64 hret, update_mask;
+
+       if (srq_init_attr->srq_type != IB_SRQT_BASIC)
+               return ERR_PTR(-ENOSYS);
+
+       /* For common attributes, internal_create_qp() takes its info
+        * out of qp_init_attr, so copy all common attrs there.
+        */
+       memset(&qp_init_attr, 0, sizeof(qp_init_attr));
+       qp_init_attr.event_handler = srq_init_attr->event_handler;
+       qp_init_attr.qp_context = srq_init_attr->srq_context;
+       qp_init_attr.sq_sig_type = IB_SIGNAL_ALL_WR;
+       qp_init_attr.qp_type = IB_QPT_RC;
+       qp_init_attr.cap.max_recv_wr = srq_init_attr->attr.max_wr;
+       qp_init_attr.cap.max_recv_sge = srq_init_attr->attr.max_sge;
+
+       my_qp = internal_create_qp(pd, &qp_init_attr, srq_init_attr, udata, 1);
+       if (IS_ERR(my_qp))
+               return (struct ib_srq *)my_qp;
+
+       /* copy back return values */
+       srq_init_attr->attr.max_wr = qp_init_attr.cap.max_recv_wr;
+       srq_init_attr->attr.max_sge = 3;
+
+       /* drive SRQ into RTR state */
+       mqpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
+       if (!mqpcb) {
+               ehca_err(pd->device, "Could not get zeroed page for mqpcb "
+                        "ehca_qp=%p qp_num=%x ", my_qp, my_qp->real_qp_num);
+               ret = ERR_PTR(-ENOMEM);
+               goto create_srq1;
+       }
+
+       mqpcb->qp_state = EHCA_QPS_INIT;
+       mqpcb->prim_phys_port = 1;
+       update_mask = EHCA_BMASK_SET(MQPCB_MASK_QP_STATE, 1);
+       hret = hipz_h_modify_qp(shca->ipz_hca_handle,
+                               my_qp->ipz_qp_handle,
+                               &my_qp->pf,
+                               update_mask,
+                               mqpcb, my_qp->galpas.kernel);
+       if (hret != H_SUCCESS) {
+               ehca_err(pd->device, "Could not modify SRQ to INIT "
+                        "ehca_qp=%p qp_num=%x h_ret=%lli",
+                        my_qp, my_qp->real_qp_num, hret);
+               goto create_srq2;
+       }
+
+       mqpcb->qp_enable = 1;
+       update_mask = EHCA_BMASK_SET(MQPCB_MASK_QP_ENABLE, 1);
+       hret = hipz_h_modify_qp(shca->ipz_hca_handle,
+                               my_qp->ipz_qp_handle,
+                               &my_qp->pf,
+                               update_mask,
+                               mqpcb, my_qp->galpas.kernel);
+       if (hret != H_SUCCESS) {
+               ehca_err(pd->device, "Could not enable SRQ "
+                        "ehca_qp=%p qp_num=%x h_ret=%lli",
+                        my_qp, my_qp->real_qp_num, hret);
+               goto create_srq2;
+       }
+
+       mqpcb->qp_state  = EHCA_QPS_RTR;
+       update_mask = EHCA_BMASK_SET(MQPCB_MASK_QP_STATE, 1);
+       hret = hipz_h_modify_qp(shca->ipz_hca_handle,
+                               my_qp->ipz_qp_handle,
+                               &my_qp->pf,
+                               update_mask,
+                               mqpcb, my_qp->galpas.kernel);
+       if (hret != H_SUCCESS) {
+               ehca_err(pd->device, "Could not modify SRQ to RTR "
+                        "ehca_qp=%p qp_num=%x h_ret=%lli",
+                        my_qp, my_qp->real_qp_num, hret);
+               goto create_srq2;
+       }
+
+       ehca_free_fw_ctrlblock(mqpcb);
+
+       return &my_qp->ib_srq;
+
+create_srq2:
+       ret = ERR_PTR(ehca2ib_return_code(hret));
+       ehca_free_fw_ctrlblock(mqpcb);
+
+create_srq1:
+       internal_destroy_qp(pd->device, my_qp, my_qp->ib_srq.uobject);
+
+       return ret;
+}
+
+/*
+ * prepare_sqe_rts called by internal_modify_qp() at trans sqe -> rts
+ * set purge bit of bad wqe and subsequent wqes to avoid reentering sqe
+ * returns total number of bad wqes in bad_wqe_cnt
+ */
+static int prepare_sqe_rts(struct ehca_qp *my_qp, struct ehca_shca *shca,
+                          int *bad_wqe_cnt)
+{
+       u64 h_ret;
+       struct ipz_queue *squeue;
+       void *bad_send_wqe_p, *bad_send_wqe_v;
+       u64 q_ofs;
+       struct ehca_wqe *wqe;
+       int qp_num = my_qp->ib_qp.qp_num;
+
+       /* get send wqe pointer */
+       h_ret = hipz_h_disable_and_get_wqe(shca->ipz_hca_handle,
+                                          my_qp->ipz_qp_handle, &my_qp->pf,
+                                          &bad_send_wqe_p, NULL, 2);
+       if (h_ret != H_SUCCESS) {
+               ehca_err(&shca->ib_device, "hipz_h_disable_and_get_wqe() failed"
+                        " ehca_qp=%p qp_num=%x h_ret=%lli",
+                        my_qp, qp_num, h_ret);
+               return ehca2ib_return_code(h_ret);
+       }
+       bad_send_wqe_p = (void *)((u64)bad_send_wqe_p & (~(1L << 63)));
+       ehca_dbg(&shca->ib_device, "qp_num=%x bad_send_wqe_p=%p",
+                qp_num, bad_send_wqe_p);
+       /* convert wqe pointer to vadr */
+       bad_send_wqe_v = __va((u64)bad_send_wqe_p);
+       if (ehca_debug_level >= 2)
+               ehca_dmp(bad_send_wqe_v, 32, "qp_num=%x bad_wqe", qp_num);
+       squeue = &my_qp->ipz_squeue;
+       if (ipz_queue_abs_to_offset(squeue, (u64)bad_send_wqe_p, &q_ofs)) {
+               ehca_err(&shca->ib_device, "failed to get wqe offset qp_num=%x"
+                        " bad_send_wqe_p=%p", qp_num, bad_send_wqe_p);
+               return -EFAULT;
+       }
+
+       /* loop sets wqe's purge bit */
+       wqe = (struct ehca_wqe *)ipz_qeit_calc(squeue, q_ofs);
+       *bad_wqe_cnt = 0;
+       while (wqe->optype != 0xff && wqe->wqef != 0xff) {
+               if (ehca_debug_level >= 2)
+                       ehca_dmp(wqe, 32, "qp_num=%x wqe", qp_num);
+               wqe->nr_of_data_seg = 0; /* suppress data access */
+               wqe->wqef = WQEF_PURGE; /* WQE to be purged */
+               q_ofs = ipz_queue_advance_offset(squeue, q_ofs);
+               wqe = (struct ehca_wqe *)ipz_qeit_calc(squeue, q_ofs);
+               *bad_wqe_cnt = (*bad_wqe_cnt)+1;
+       }
+       /*
+        * bad wqe will be reprocessed and ignored when pol_cq() is called,
+        *  i.e. nr of wqes with flush error status is one less
+        */
+       ehca_dbg(&shca->ib_device, "qp_num=%x flusherr_wqe_cnt=%x",
+                qp_num, (*bad_wqe_cnt)-1);
+       wqe->wqef = 0;
+
+       return 0;
+}
+
+static int calc_left_cqes(u64 wqe_p, struct ipz_queue *ipz_queue,
+                         struct ehca_queue_map *qmap)
+{
+       void *wqe_v;
+       u64 q_ofs;
+       u32 wqe_idx;
+       unsigned int tail_idx;
+
+       /* convert real to abs address */
+       wqe_p = wqe_p & (~(1UL << 63));
+
+       wqe_v = __va(wqe_p);
+
+       if (ipz_queue_abs_to_offset(ipz_queue, wqe_p, &q_ofs)) {
+               ehca_gen_err("Invalid offset for calculating left cqes "
+                               "wqe_p=%#llx wqe_v=%p\n", wqe_p, wqe_v);
+               return -EFAULT;
+       }
+
+       tail_idx = next_index(qmap->tail, qmap->entries);
+       wqe_idx = q_ofs / ipz_queue->qe_size;
+
+       /* check all processed wqes, whether a cqe is requested or not */
+       while (tail_idx != wqe_idx) {
+               if (qmap->map[tail_idx].cqe_req)
+                       qmap->left_to_poll++;
+               tail_idx = next_index(tail_idx, qmap->entries);
+       }
+       /* save index in queue, where we have to start flushing */
+       qmap->next_wqe_idx = wqe_idx;
+       return 0;
+}
+
+static int check_for_left_cqes(struct ehca_qp *my_qp, struct ehca_shca *shca)
+{
+       u64 h_ret;
+       void *send_wqe_p, *recv_wqe_p;
+       int ret;
+       unsigned long flags;
+       int qp_num = my_qp->ib_qp.qp_num;
+
+       /* this hcall is not supported on base QPs */
+       if (my_qp->ext_type != EQPT_SRQBASE) {
+               /* get send and receive wqe pointer */
+               h_ret = hipz_h_disable_and_get_wqe(shca->ipz_hca_handle,
+                               my_qp->ipz_qp_handle, &my_qp->pf,
+                               &send_wqe_p, &recv_wqe_p, 4);
+               if (h_ret != H_SUCCESS) {
+                       ehca_err(&shca->ib_device, "disable_and_get_wqe() "
+                                "failed ehca_qp=%p qp_num=%x h_ret=%lli",
+                                my_qp, qp_num, h_ret);
+                       return ehca2ib_return_code(h_ret);
+               }
+
+               /*
+                * acquire lock to ensure that nobody is polling the cq which
+                * could mean that the qmap->tail pointer is in an
+                * inconsistent state.
+                */
+               spin_lock_irqsave(&my_qp->send_cq->spinlock, flags);
+               ret = calc_left_cqes((u64)send_wqe_p, &my_qp->ipz_squeue,
+                               &my_qp->sq_map);
+               spin_unlock_irqrestore(&my_qp->send_cq->spinlock, flags);
+               if (ret)
+                       return ret;
+
+
+               spin_lock_irqsave(&my_qp->recv_cq->spinlock, flags);
+               ret = calc_left_cqes((u64)recv_wqe_p, &my_qp->ipz_rqueue,
+                               &my_qp->rq_map);
+               spin_unlock_irqrestore(&my_qp->recv_cq->spinlock, flags);
+               if (ret)
+                       return ret;
+       } else {
+               spin_lock_irqsave(&my_qp->send_cq->spinlock, flags);
+               my_qp->sq_map.left_to_poll = 0;
+               my_qp->sq_map.next_wqe_idx = next_index(my_qp->sq_map.tail,
+                                                       my_qp->sq_map.entries);
+               spin_unlock_irqrestore(&my_qp->send_cq->spinlock, flags);
+
+               spin_lock_irqsave(&my_qp->recv_cq->spinlock, flags);
+               my_qp->rq_map.left_to_poll = 0;
+               my_qp->rq_map.next_wqe_idx = next_index(my_qp->rq_map.tail,
+                                                       my_qp->rq_map.entries);
+               spin_unlock_irqrestore(&my_qp->recv_cq->spinlock, flags);
+       }
+
+       /* this assures flush cqes being generated only for pending wqes */
+       if ((my_qp->sq_map.left_to_poll == 0) &&
+                               (my_qp->rq_map.left_to_poll == 0)) {
+               spin_lock_irqsave(&my_qp->send_cq->spinlock, flags);
+               ehca_add_to_err_list(my_qp, 1);
+               spin_unlock_irqrestore(&my_qp->send_cq->spinlock, flags);
+
+               if (HAS_RQ(my_qp)) {
+                       spin_lock_irqsave(&my_qp->recv_cq->spinlock, flags);
+                       ehca_add_to_err_list(my_qp, 0);
+                       spin_unlock_irqrestore(&my_qp->recv_cq->spinlock,
+                                       flags);
+               }
+       }
+
+       return 0;
+}
+
+/*
+ * internal_modify_qp with circumvention to handle aqp0 properly
+ * smi_reset2init indicates if this is an internal reset-to-init-call for
+ * smi. This flag must always be zero if called from ehca_modify_qp()!
+ * This internal func was intorduced to avoid recursion of ehca_modify_qp()!
+ */
+static int internal_modify_qp(struct ib_qp *ibqp,
+                             struct ib_qp_attr *attr,
+                             int attr_mask, int smi_reset2init)
+{
+       enum ib_qp_state qp_cur_state, qp_new_state;
+       int cnt, qp_attr_idx, ret = 0;
+       enum ib_qp_statetrans statetrans;
+       struct hcp_modify_qp_control_block *mqpcb;
+       struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp);
+       struct ehca_shca *shca =
+               container_of(ibqp->pd->device, struct ehca_shca, ib_device);
+       u64 update_mask;
+       u64 h_ret;
+       int bad_wqe_cnt = 0;
+       int is_user = 0;
+       int squeue_locked = 0;
+       unsigned long flags = 0;
+
+       /* do query_qp to obtain current attr values */
+       mqpcb = ehca_alloc_fw_ctrlblock(GFP_ATOMIC);
+       if (!mqpcb) {
+               ehca_err(ibqp->device, "Could not get zeroed page for mqpcb "
+                        "ehca_qp=%p qp_num=%x ", my_qp, ibqp->qp_num);
+               return -ENOMEM;
+       }
+
+       h_ret = hipz_h_query_qp(shca->ipz_hca_handle,
+                               my_qp->ipz_qp_handle,
+                               &my_qp->pf,
+                               mqpcb, my_qp->galpas.kernel);
+       if (h_ret != H_SUCCESS) {
+               ehca_err(ibqp->device, "hipz_h_query_qp() failed "
+                        "ehca_qp=%p qp_num=%x h_ret=%lli",
+                        my_qp, ibqp->qp_num, h_ret);
+               ret = ehca2ib_return_code(h_ret);
+               goto modify_qp_exit1;
+       }
+       if (ibqp->uobject)
+               is_user = 1;
+
+       qp_cur_state = ehca2ib_qp_state(mqpcb->qp_state);
+
+       if (qp_cur_state == -EINVAL) {  /* invalid qp state */
+               ret = -EINVAL;
+               ehca_err(ibqp->device, "Invalid current ehca_qp_state=%x "
+                        "ehca_qp=%p qp_num=%x",
+                        mqpcb->qp_state, my_qp, ibqp->qp_num);
+               goto modify_qp_exit1;
+       }
+       /*
+        * circumvention to set aqp0 initial state to init
+        * as expected by IB spec
+        */
+       if (smi_reset2init == 0 &&
+           ibqp->qp_type == IB_QPT_SMI &&
+           qp_cur_state == IB_QPS_RESET &&
+           (attr_mask & IB_QP_STATE) &&
+           attr->qp_state == IB_QPS_INIT) { /* RESET -> INIT */
+               struct ib_qp_attr smiqp_attr = {
+                       .qp_state = IB_QPS_INIT,
+                       .port_num = my_qp->init_attr.port_num,
+                       .pkey_index = 0,
+                       .qkey = 0
+               };
+               int smiqp_attr_mask = IB_QP_STATE | IB_QP_PORT |
+                       IB_QP_PKEY_INDEX | IB_QP_QKEY;
+               int smirc = internal_modify_qp(
+                       ibqp, &smiqp_attr, smiqp_attr_mask, 1);
+               if (smirc) {
+                       ehca_err(ibqp->device, "SMI RESET -> INIT failed. "
+                                "ehca_modify_qp() rc=%i", smirc);
+                       ret = H_PARAMETER;
+                       goto modify_qp_exit1;
+               }
+               qp_cur_state = IB_QPS_INIT;
+               ehca_dbg(ibqp->device, "SMI RESET -> INIT succeeded");
+       }
+       /* is transmitted current state  equal to "real" current state */
+       if ((attr_mask & IB_QP_CUR_STATE) &&
+           qp_cur_state != attr->cur_qp_state) {
+               ret = -EINVAL;
+               ehca_err(ibqp->device,
+                        "Invalid IB_QP_CUR_STATE attr->curr_qp_state=%x <>"
+                        " actual cur_qp_state=%x. ehca_qp=%p qp_num=%x",
+                        attr->cur_qp_state, qp_cur_state, my_qp, ibqp->qp_num);
+               goto modify_qp_exit1;
+       }
+
+       ehca_dbg(ibqp->device, "ehca_qp=%p qp_num=%x current qp_state=%x "
+                "new qp_state=%x attribute_mask=%x",
+                my_qp, ibqp->qp_num, qp_cur_state, attr->qp_state, attr_mask);
+
+       qp_new_state = attr_mask & IB_QP_STATE ? attr->qp_state : qp_cur_state;
+       if (!smi_reset2init &&
+           !ib_modify_qp_is_ok(qp_cur_state, qp_new_state, ibqp->qp_type,
+                               attr_mask, IB_LINK_LAYER_UNSPECIFIED)) {
+               ret = -EINVAL;
+               ehca_err(ibqp->device,
+                        "Invalid qp transition new_state=%x cur_state=%x "
+                        "ehca_qp=%p qp_num=%x attr_mask=%x", qp_new_state,
+                        qp_cur_state, my_qp, ibqp->qp_num, attr_mask);
+               goto modify_qp_exit1;
+       }
+
+       mqpcb->qp_state = ib2ehca_qp_state(qp_new_state);
+       if (mqpcb->qp_state)
+               update_mask = EHCA_BMASK_SET(MQPCB_MASK_QP_STATE, 1);
+       else {
+               ret = -EINVAL;
+               ehca_err(ibqp->device, "Invalid new qp state=%x "
+                        "ehca_qp=%p qp_num=%x",
+                        qp_new_state, my_qp, ibqp->qp_num);
+               goto modify_qp_exit1;
+       }
+
+       /* retrieve state transition struct to get req and opt attrs */
+       statetrans = get_modqp_statetrans(qp_cur_state, qp_new_state);
+       if (statetrans < 0) {
+               ret = -EINVAL;
+               ehca_err(ibqp->device, "<INVALID STATE CHANGE> qp_cur_state=%x "
+                        "new_qp_state=%x State_xsition=%x ehca_qp=%p "
+                        "qp_num=%x", qp_cur_state, qp_new_state,
+                        statetrans, my_qp, ibqp->qp_num);
+               goto modify_qp_exit1;
+       }
+
+       qp_attr_idx = ib2ehcaqptype(ibqp->qp_type);
+
+       if (qp_attr_idx < 0) {
+               ret = qp_attr_idx;
+               ehca_err(ibqp->device,
+                        "Invalid QP type=%x ehca_qp=%p qp_num=%x",
+                        ibqp->qp_type, my_qp, ibqp->qp_num);
+               goto modify_qp_exit1;
+       }
+
+       ehca_dbg(ibqp->device,
+                "ehca_qp=%p qp_num=%x <VALID STATE CHANGE> qp_state_xsit=%x",
+                my_qp, ibqp->qp_num, statetrans);
+
+       /* eHCA2 rev2 and higher require the SEND_GRH_FLAG to be set
+        * in non-LL UD QPs.
+        */
+       if ((my_qp->qp_type == IB_QPT_UD) &&
+           (my_qp->ext_type != EQPT_LLQP) &&
+           (statetrans == IB_QPST_INIT2RTR) &&
+           (shca->hw_level >= 0x22)) {
+               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SEND_GRH_FLAG, 1);
+               mqpcb->send_grh_flag = 1;
+       }
+
+       /* sqe -> rts: set purge bit of bad wqe before actual trans */
+       if ((my_qp->qp_type == IB_QPT_UD ||
+            my_qp->qp_type == IB_QPT_GSI ||
+            my_qp->qp_type == IB_QPT_SMI) &&
+           statetrans == IB_QPST_SQE2RTS) {
+               /* mark next free wqe if kernel */
+               if (!ibqp->uobject) {
+                       struct ehca_wqe *wqe;
+                       /* lock send queue */
+                       spin_lock_irqsave(&my_qp->spinlock_s, flags);
+                       squeue_locked = 1;
+                       /* mark next free wqe */
+                       wqe = (struct ehca_wqe *)
+                               ipz_qeit_get(&my_qp->ipz_squeue);
+                       wqe->optype = wqe->wqef = 0xff;
+                       ehca_dbg(ibqp->device, "qp_num=%x next_free_wqe=%p",
+                                ibqp->qp_num, wqe);
+               }
+               ret = prepare_sqe_rts(my_qp, shca, &bad_wqe_cnt);
+               if (ret) {
+                       ehca_err(ibqp->device, "prepare_sqe_rts() failed "
+                                "ehca_qp=%p qp_num=%x ret=%i",
+                                my_qp, ibqp->qp_num, ret);
+                       goto modify_qp_exit2;
+               }
+       }
+
+       /*
+        * enable RDMA_Atomic_Control if reset->init und reliable con
+        * this is necessary since gen2 does not provide that flag,
+        * but pHyp requires it
+        */
+       if (statetrans == IB_QPST_RESET2INIT &&
+           (ibqp->qp_type == IB_QPT_RC || ibqp->qp_type == IB_QPT_UC)) {
+               mqpcb->rdma_atomic_ctrl = 3;
+               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_RDMA_ATOMIC_CTRL, 1);
+       }
+       /* circ. pHyp requires #RDMA/Atomic Resp Res for UC INIT -> RTR */
+       if (statetrans == IB_QPST_INIT2RTR &&
+           (ibqp->qp_type == IB_QPT_UC) &&
+           !(attr_mask & IB_QP_MAX_DEST_RD_ATOMIC)) {
+               mqpcb->rdma_nr_atomic_resp_res = 1; /* default to 1 */
+               update_mask |=
+                       EHCA_BMASK_SET(MQPCB_MASK_RDMA_NR_ATOMIC_RESP_RES, 1);
+       }
+
+       if (attr_mask & IB_QP_PKEY_INDEX) {
+               if (attr->pkey_index >= 16) {
+                       ret = -EINVAL;
+                       ehca_err(ibqp->device, "Invalid pkey_index=%x. "
+                                "ehca_qp=%p qp_num=%x max_pkey_index=f",
+                                attr->pkey_index, my_qp, ibqp->qp_num);
+                       goto modify_qp_exit2;
+               }
+               mqpcb->prim_p_key_idx = attr->pkey_index;
+               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_PRIM_P_KEY_IDX, 1);
+       }
+       if (attr_mask & IB_QP_PORT) {
+               struct ehca_sport *sport;
+               struct ehca_qp *aqp1;
+               if (attr->port_num < 1 || attr->port_num > shca->num_ports) {
+                       ret = -EINVAL;
+                       ehca_err(ibqp->device, "Invalid port=%x. "
+                                "ehca_qp=%p qp_num=%x num_ports=%x",
+                                attr->port_num, my_qp, ibqp->qp_num,
+                                shca->num_ports);
+                       goto modify_qp_exit2;
+               }
+               sport = &shca->sport[attr->port_num - 1];
+               if (!sport->ibqp_sqp[IB_QPT_GSI]) {
+                       /* should not occur */
+                       ret = -EFAULT;
+                       ehca_err(ibqp->device, "AQP1 was not created for "
+                                "port=%x", attr->port_num);
+                       goto modify_qp_exit2;
+               }
+               aqp1 = container_of(sport->ibqp_sqp[IB_QPT_GSI],
+                                   struct ehca_qp, ib_qp);
+               if (ibqp->qp_type != IB_QPT_GSI &&
+                   ibqp->qp_type != IB_QPT_SMI &&
+                   aqp1->mod_qp_parm) {
+                       /*
+                        * firmware will reject this modify_qp() because
+                        * port is not activated/initialized fully
+                        */
+                       ret = -EFAULT;
+                       ehca_warn(ibqp->device, "Couldn't modify qp port=%x: "
+                                 "either port is being activated (try again) "
+                                 "or cabling issue", attr->port_num);
+                       goto modify_qp_exit2;
+               }
+               mqpcb->prim_phys_port = attr->port_num;
+               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_PRIM_PHYS_PORT, 1);
+       }
+       if (attr_mask & IB_QP_QKEY) {
+               mqpcb->qkey = attr->qkey;
+               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_QKEY, 1);
+       }
+       if (attr_mask & IB_QP_AV) {
+               mqpcb->dlid = attr->ah_attr.dlid;
+               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_DLID, 1);
+               mqpcb->source_path_bits = attr->ah_attr.src_path_bits;
+               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SOURCE_PATH_BITS, 1);
+               mqpcb->service_level = attr->ah_attr.sl;
+               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SERVICE_LEVEL, 1);
+
+               if (ehca_calc_ipd(shca, mqpcb->prim_phys_port,
+                                 attr->ah_attr.static_rate,
+                                 &mqpcb->max_static_rate)) {
+                       ret = -EINVAL;
+                       goto modify_qp_exit2;
+               }
+               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_MAX_STATIC_RATE, 1);
+
+               /*
+                * Always supply the GRH flag, even if it's zero, to give the
+                * hypervisor a clear "yes" or "no" instead of a "perhaps"
+                */
+               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SEND_GRH_FLAG, 1);
+
+               /*
+                * only if GRH is TRUE we might consider SOURCE_GID_IDX
+                * and DEST_GID otherwise phype will return H_ATTR_PARM!!!
+                */
+               if (attr->ah_attr.ah_flags == IB_AH_GRH) {
+                       mqpcb->send_grh_flag = 1;
+
+                       mqpcb->source_gid_idx = attr->ah_attr.grh.sgid_index;
+                       update_mask |=
+                               EHCA_BMASK_SET(MQPCB_MASK_SOURCE_GID_IDX, 1);
+
+                       for (cnt = 0; cnt < 16; cnt++)
+                               mqpcb->dest_gid.byte[cnt] =
+                                       attr->ah_attr.grh.dgid.raw[cnt];
+
+                       update_mask |= EHCA_BMASK_SET(MQPCB_MASK_DEST_GID, 1);
+                       mqpcb->flow_label = attr->ah_attr.grh.flow_label;
+                       update_mask |= EHCA_BMASK_SET(MQPCB_MASK_FLOW_LABEL, 1);
+                       mqpcb->hop_limit = attr->ah_attr.grh.hop_limit;
+                       update_mask |= EHCA_BMASK_SET(MQPCB_MASK_HOP_LIMIT, 1);
+                       mqpcb->traffic_class = attr->ah_attr.grh.traffic_class;
+                       update_mask |=
+                               EHCA_BMASK_SET(MQPCB_MASK_TRAFFIC_CLASS, 1);
+               }
+       }
+
+       if (attr_mask & IB_QP_PATH_MTU) {
+               /* store ld(MTU) */
+               my_qp->mtu_shift = attr->path_mtu + 7;
+               mqpcb->path_mtu = attr->path_mtu;
+               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_PATH_MTU, 1);
+       }
+       if (attr_mask & IB_QP_TIMEOUT) {
+               mqpcb->timeout = attr->timeout;
+               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_TIMEOUT, 1);
+       }
+       if (attr_mask & IB_QP_RETRY_CNT) {
+               mqpcb->retry_count = attr->retry_cnt;
+               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_RETRY_COUNT, 1);
+       }
+       if (attr_mask & IB_QP_RNR_RETRY) {
+               mqpcb->rnr_retry_count = attr->rnr_retry;
+               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_RNR_RETRY_COUNT, 1);
+       }
+       if (attr_mask & IB_QP_RQ_PSN) {
+               mqpcb->receive_psn = attr->rq_psn;
+               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_RECEIVE_PSN, 1);
+       }
+       if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) {
+               mqpcb->rdma_nr_atomic_resp_res = attr->max_dest_rd_atomic < 3 ?
+                       attr->max_dest_rd_atomic : 2;
+               update_mask |=
+                       EHCA_BMASK_SET(MQPCB_MASK_RDMA_NR_ATOMIC_RESP_RES, 1);
+       }
+       if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC) {
+               mqpcb->rdma_atomic_outst_dest_qp = attr->max_rd_atomic < 3 ?
+                       attr->max_rd_atomic : 2;
+               update_mask |=
+                       EHCA_BMASK_SET
+                       (MQPCB_MASK_RDMA_ATOMIC_OUTST_DEST_QP, 1);
+       }
+       if (attr_mask & IB_QP_ALT_PATH) {
+               if (attr->alt_port_num < 1
+                   || attr->alt_port_num > shca->num_ports) {
+                       ret = -EINVAL;
+                       ehca_err(ibqp->device, "Invalid alt_port=%x. "
+                                "ehca_qp=%p qp_num=%x num_ports=%x",
+                                attr->alt_port_num, my_qp, ibqp->qp_num,
+                                shca->num_ports);
+                       goto modify_qp_exit2;
+               }
+               mqpcb->alt_phys_port = attr->alt_port_num;
+
+               if (attr->alt_pkey_index >= 16) {
+                       ret = -EINVAL;
+                       ehca_err(ibqp->device, "Invalid alt_pkey_index=%x. "
+                                "ehca_qp=%p qp_num=%x max_pkey_index=f",
+                                attr->pkey_index, my_qp, ibqp->qp_num);
+                       goto modify_qp_exit2;
+               }
+               mqpcb->alt_p_key_idx = attr->alt_pkey_index;
+
+               mqpcb->timeout_al = attr->alt_timeout;
+               mqpcb->dlid_al = attr->alt_ah_attr.dlid;
+               mqpcb->source_path_bits_al = attr->alt_ah_attr.src_path_bits;
+               mqpcb->service_level_al = attr->alt_ah_attr.sl;
+
+               if (ehca_calc_ipd(shca, mqpcb->alt_phys_port,
+                                 attr->alt_ah_attr.static_rate,
+                                 &mqpcb->max_static_rate_al)) {
+                       ret = -EINVAL;
+                       goto modify_qp_exit2;
+               }
+
+               /* OpenIB doesn't support alternate retry counts - copy them */
+               mqpcb->retry_count_al = mqpcb->retry_count;
+               mqpcb->rnr_retry_count_al = mqpcb->rnr_retry_count;
+
+               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_ALT_PHYS_PORT, 1)
+                       | EHCA_BMASK_SET(MQPCB_MASK_ALT_P_KEY_IDX, 1)
+                       | EHCA_BMASK_SET(MQPCB_MASK_TIMEOUT_AL, 1)
+                       | EHCA_BMASK_SET(MQPCB_MASK_DLID_AL, 1)
+                       | EHCA_BMASK_SET(MQPCB_MASK_SOURCE_PATH_BITS_AL, 1)
+                       | EHCA_BMASK_SET(MQPCB_MASK_SERVICE_LEVEL_AL, 1)
+                       | EHCA_BMASK_SET(MQPCB_MASK_MAX_STATIC_RATE_AL, 1)
+                       | EHCA_BMASK_SET(MQPCB_MASK_RETRY_COUNT_AL, 1)
+                       | EHCA_BMASK_SET(MQPCB_MASK_RNR_RETRY_COUNT_AL, 1);
+
+               /*
+                * Always supply the GRH flag, even if it's zero, to give the
+                * hypervisor a clear "yes" or "no" instead of a "perhaps"
+                */
+               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SEND_GRH_FLAG_AL, 1);
+
+               /*
+                * only if GRH is TRUE we might consider SOURCE_GID_IDX
+                * and DEST_GID otherwise phype will return H_ATTR_PARM!!!
+                */
+               if (attr->alt_ah_attr.ah_flags == IB_AH_GRH) {
+                       mqpcb->send_grh_flag_al = 1;
+
+                       for (cnt = 0; cnt < 16; cnt++)
+                               mqpcb->dest_gid_al.byte[cnt] =
+                                       attr->alt_ah_attr.grh.dgid.raw[cnt];
+                       mqpcb->source_gid_idx_al =
+                               attr->alt_ah_attr.grh.sgid_index;
+                       mqpcb->flow_label_al = attr->alt_ah_attr.grh.flow_label;
+                       mqpcb->hop_limit_al = attr->alt_ah_attr.grh.hop_limit;
+                       mqpcb->traffic_class_al =
+                               attr->alt_ah_attr.grh.traffic_class;
+
+                       update_mask |=
+                               EHCA_BMASK_SET(MQPCB_MASK_SOURCE_GID_IDX_AL, 1)
+                               | EHCA_BMASK_SET(MQPCB_MASK_DEST_GID_AL, 1)
+                               | EHCA_BMASK_SET(MQPCB_MASK_FLOW_LABEL_AL, 1)
+                               | EHCA_BMASK_SET(MQPCB_MASK_HOP_LIMIT_AL, 1) |
+                               EHCA_BMASK_SET(MQPCB_MASK_TRAFFIC_CLASS_AL, 1);
+               }
+       }
+
+       if (attr_mask & IB_QP_MIN_RNR_TIMER) {
+               mqpcb->min_rnr_nak_timer_field = attr->min_rnr_timer;
+               update_mask |=
+                       EHCA_BMASK_SET(MQPCB_MASK_MIN_RNR_NAK_TIMER_FIELD, 1);
+       }
+
+       if (attr_mask & IB_QP_SQ_PSN) {
+               mqpcb->send_psn = attr->sq_psn;
+               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SEND_PSN, 1);
+       }
+
+       if (attr_mask & IB_QP_DEST_QPN) {
+               mqpcb->dest_qp_nr = attr->dest_qp_num;
+               update_mask |= EHCA_BMASK_SET(MQPCB_MASK_DEST_QP_NR, 1);
+       }
+
+       if (attr_mask & IB_QP_PATH_MIG_STATE) {
+               if (attr->path_mig_state != IB_MIG_REARM
+                   && attr->path_mig_state != IB_MIG_MIGRATED) {
+                       ret = -EINVAL;
+                       ehca_err(ibqp->device, "Invalid mig_state=%x",
+                                attr->path_mig_state);
+                       goto modify_qp_exit2;
+               }
+               mqpcb->path_migration_state = attr->path_mig_state + 1;
+               if (attr->path_mig_state == IB_MIG_REARM)
+                       my_qp->mig_armed = 1;
+               update_mask |=
+                       EHCA_BMASK_SET(MQPCB_MASK_PATH_MIGRATION_STATE, 1);
+       }
+
+       if (attr_mask & IB_QP_CAP) {
+               mqpcb->max_nr_outst_send_wr = attr->cap.max_send_wr+1;
+               update_mask |=
+                       EHCA_BMASK_SET(MQPCB_MASK_MAX_NR_OUTST_SEND_WR, 1);
+               mqpcb->max_nr_outst_recv_wr = attr->cap.max_recv_wr+1;
+               update_mask |=
+                       EHCA_BMASK_SET(MQPCB_MASK_MAX_NR_OUTST_RECV_WR, 1);
+               /* no support for max_send/recv_sge yet */
+       }
+
+       if (ehca_debug_level >= 2)
+               ehca_dmp(mqpcb, 4*70, "qp_num=%x", ibqp->qp_num);
+
+       h_ret = hipz_h_modify_qp(shca->ipz_hca_handle,
+                                my_qp->ipz_qp_handle,
+                                &my_qp->pf,
+                                update_mask,
+                                mqpcb, my_qp->galpas.kernel);
+
+       if (h_ret != H_SUCCESS) {
+               ret = ehca2ib_return_code(h_ret);
+               ehca_err(ibqp->device, "hipz_h_modify_qp() failed h_ret=%lli "
+                        "ehca_qp=%p qp_num=%x", h_ret, my_qp, ibqp->qp_num);
+               goto modify_qp_exit2;
+       }
+
+       if ((my_qp->qp_type == IB_QPT_UD ||
+            my_qp->qp_type == IB_QPT_GSI ||
+            my_qp->qp_type == IB_QPT_SMI) &&
+           statetrans == IB_QPST_SQE2RTS) {
+               /* doorbell to reprocessing wqes */
+               iosync(); /* serialize GAL register access */
+               hipz_update_sqa(my_qp, bad_wqe_cnt-1);
+               ehca_gen_dbg("doorbell for %x wqes", bad_wqe_cnt);
+       }
+
+       if (statetrans == IB_QPST_RESET2INIT ||
+           statetrans == IB_QPST_INIT2INIT) {
+               mqpcb->qp_enable = 1;
+               mqpcb->qp_state = EHCA_QPS_INIT;
+               update_mask = 0;
+               update_mask = EHCA_BMASK_SET(MQPCB_MASK_QP_ENABLE, 1);
+
+               h_ret = hipz_h_modify_qp(shca->ipz_hca_handle,
+                                        my_qp->ipz_qp_handle,
+                                        &my_qp->pf,
+                                        update_mask,
+                                        mqpcb,
+                                        my_qp->galpas.kernel);
+
+               if (h_ret != H_SUCCESS) {
+                       ret = ehca2ib_return_code(h_ret);
+                       ehca_err(ibqp->device, "ENABLE in context of "
+                                "RESET_2_INIT failed! Maybe you didn't get "
+                                "a LID h_ret=%lli ehca_qp=%p qp_num=%x",
+                                h_ret, my_qp, ibqp->qp_num);
+                       goto modify_qp_exit2;
+               }
+       }
+       if ((qp_new_state == IB_QPS_ERR) && (qp_cur_state != IB_QPS_ERR)
+           && !is_user) {
+               ret = check_for_left_cqes(my_qp, shca);
+               if (ret)
+                       goto modify_qp_exit2;
+       }
+
+       if (statetrans == IB_QPST_ANY2RESET) {
+               ipz_qeit_reset(&my_qp->ipz_rqueue);
+               ipz_qeit_reset(&my_qp->ipz_squeue);
+
+               if (qp_cur_state == IB_QPS_ERR && !is_user) {
+                       del_from_err_list(my_qp->send_cq, &my_qp->sq_err_node);
+
+                       if (HAS_RQ(my_qp))
+                               del_from_err_list(my_qp->recv_cq,
+                                                 &my_qp->rq_err_node);
+               }
+               if (!is_user)
+                       reset_queue_map(&my_qp->sq_map);
+
+               if (HAS_RQ(my_qp) && !is_user)
+                       reset_queue_map(&my_qp->rq_map);
+       }
+
+       if (attr_mask & IB_QP_QKEY)
+               my_qp->qkey = attr->qkey;
+
+modify_qp_exit2:
+       if (squeue_locked) { /* this means: sqe -> rts */
+               spin_unlock_irqrestore(&my_qp->spinlock_s, flags);
+               my_qp->sqerr_purgeflag = 1;
+       }
+
+modify_qp_exit1:
+       ehca_free_fw_ctrlblock(mqpcb);
+
+       return ret;
+}
+
+int ehca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
+                  struct ib_udata *udata)
+{
+       int ret = 0;
+
+       struct ehca_shca *shca = container_of(ibqp->device, struct ehca_shca,
+                                             ib_device);
+       struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp);
+
+       /* The if-block below caches qp_attr to be modified for GSI and SMI
+        * qps during the initialization by ib_mad. When the respective port
+        * is activated, ie we got an event PORT_ACTIVE, we'll replay the
+        * cached modify calls sequence, see ehca_recover_sqs() below.
+        * Why that is required:
+        * 1) If one port is connected, older code requires that port one
+        *    to be connected and module option nr_ports=1 to be given by
+        *    user, which is very inconvenient for end user.
+        * 2) Firmware accepts modify_qp() only if respective port has become
+        *    active. Older code had a wait loop of 30sec create_qp()/
+        *    define_aqp1(), which is not appropriate in practice. This
+        *    code now removes that wait loop, see define_aqp1(), and always
+        *    reports all ports to ib_mad resp. users. Only activated ports
+        *    will then usable for the users.
+        */
+       if (ibqp->qp_type == IB_QPT_GSI || ibqp->qp_type == IB_QPT_SMI) {
+               int port = my_qp->init_attr.port_num;
+               struct ehca_sport *sport = &shca->sport[port - 1];
+               unsigned long flags;
+               spin_lock_irqsave(&sport->mod_sqp_lock, flags);
+               /* cache qp_attr only during init */
+               if (my_qp->mod_qp_parm) {
+                       struct ehca_mod_qp_parm *p;
+                       if (my_qp->mod_qp_parm_idx >= EHCA_MOD_QP_PARM_MAX) {
+                               ehca_err(&shca->ib_device,
+                                        "mod_qp_parm overflow state=%x port=%x"
+                                        " type=%x", attr->qp_state,
+                                        my_qp->init_attr.port_num,
+                                        ibqp->qp_type);
+                               spin_unlock_irqrestore(&sport->mod_sqp_lock,
+                                                      flags);
+                               return -EINVAL;
+                       }
+                       p = &my_qp->mod_qp_parm[my_qp->mod_qp_parm_idx];
+                       p->mask = attr_mask;
+                       p->attr = *attr;
+                       my_qp->mod_qp_parm_idx++;
+                       ehca_dbg(&shca->ib_device,
+                                "Saved qp_attr for state=%x port=%x type=%x",
+                                attr->qp_state, my_qp->init_attr.port_num,
+                                ibqp->qp_type);
+                       spin_unlock_irqrestore(&sport->mod_sqp_lock, flags);
+                       goto out;
+               }
+               spin_unlock_irqrestore(&sport->mod_sqp_lock, flags);
+       }
+
+       ret = internal_modify_qp(ibqp, attr, attr_mask, 0);
+
+out:
+       if ((ret == 0) && (attr_mask & IB_QP_STATE))
+               my_qp->state = attr->qp_state;
+
+       return ret;
+}
+
+void ehca_recover_sqp(struct ib_qp *sqp)
+{
+       struct ehca_qp *my_sqp = container_of(sqp, struct ehca_qp, ib_qp);
+       int port = my_sqp->init_attr.port_num;
+       struct ib_qp_attr attr;
+       struct ehca_mod_qp_parm *qp_parm;
+       int i, qp_parm_idx, ret;
+       unsigned long flags, wr_cnt;
+
+       if (!my_sqp->mod_qp_parm)
+               return;
+       ehca_dbg(sqp->device, "SQP port=%x qp_num=%x", port, sqp->qp_num);
+
+       qp_parm = my_sqp->mod_qp_parm;
+       qp_parm_idx = my_sqp->mod_qp_parm_idx;
+       for (i = 0; i < qp_parm_idx; i++) {
+               attr = qp_parm[i].attr;
+               ret = internal_modify_qp(sqp, &attr, qp_parm[i].mask, 0);
+               if (ret) {
+                       ehca_err(sqp->device, "Could not modify SQP port=%x "
+                                "qp_num=%x ret=%x", port, sqp->qp_num, ret);
+                       goto free_qp_parm;
+               }
+               ehca_dbg(sqp->device, "SQP port=%x qp_num=%x in state=%x",
+                        port, sqp->qp_num, attr.qp_state);
+       }
+
+       /* re-trigger posted recv wrs */
+       wr_cnt =  my_sqp->ipz_rqueue.current_q_offset /
+               my_sqp->ipz_rqueue.qe_size;
+       if (wr_cnt) {
+               spin_lock_irqsave(&my_sqp->spinlock_r, flags);
+               hipz_update_rqa(my_sqp, wr_cnt);
+               spin_unlock_irqrestore(&my_sqp->spinlock_r, flags);
+               ehca_dbg(sqp->device, "doorbell port=%x qp_num=%x wr_cnt=%lx",
+                        port, sqp->qp_num, wr_cnt);
+       }
+
+free_qp_parm:
+       kfree(qp_parm);
+       /* this prevents subsequent calls to modify_qp() to cache qp_attr */
+       my_sqp->mod_qp_parm = NULL;
+}
+
+int ehca_query_qp(struct ib_qp *qp,
+                 struct ib_qp_attr *qp_attr,
+                 int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr)
+{
+       struct ehca_qp *my_qp = container_of(qp, struct ehca_qp, ib_qp);
+       struct ehca_shca *shca = container_of(qp->device, struct ehca_shca,
+                                             ib_device);
+       struct ipz_adapter_handle adapter_handle = shca->ipz_hca_handle;
+       struct hcp_modify_qp_control_block *qpcb;
+       int cnt, ret = 0;
+       u64 h_ret;
+
+       if (qp_attr_mask & QP_ATTR_QUERY_NOT_SUPPORTED) {
+               ehca_err(qp->device, "Invalid attribute mask "
+                        "ehca_qp=%p qp_num=%x qp_attr_mask=%x ",
+                        my_qp, qp->qp_num, qp_attr_mask);
+               return -EINVAL;
+       }
+
+       qpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
+       if (!qpcb) {
+               ehca_err(qp->device, "Out of memory for qpcb "
+                        "ehca_qp=%p qp_num=%x", my_qp, qp->qp_num);
+               return -ENOMEM;
+       }
+
+       h_ret = hipz_h_query_qp(adapter_handle,
+                               my_qp->ipz_qp_handle,
+                               &my_qp->pf,
+                               qpcb, my_qp->galpas.kernel);
+
+       if (h_ret != H_SUCCESS) {
+               ret = ehca2ib_return_code(h_ret);
+               ehca_err(qp->device, "hipz_h_query_qp() failed "
+                        "ehca_qp=%p qp_num=%x h_ret=%lli",
+                        my_qp, qp->qp_num, h_ret);
+               goto query_qp_exit1;
+       }
+
+       qp_attr->cur_qp_state = ehca2ib_qp_state(qpcb->qp_state);
+       qp_attr->qp_state = qp_attr->cur_qp_state;
+
+       if (qp_attr->cur_qp_state == -EINVAL) {
+               ret = -EINVAL;
+               ehca_err(qp->device, "Got invalid ehca_qp_state=%x "
+                        "ehca_qp=%p qp_num=%x",
+                        qpcb->qp_state, my_qp, qp->qp_num);
+               goto query_qp_exit1;
+       }
+
+       if (qp_attr->qp_state == IB_QPS_SQD)
+               qp_attr->sq_draining = 1;
+
+       qp_attr->qkey = qpcb->qkey;
+       qp_attr->path_mtu = qpcb->path_mtu;
+       qp_attr->path_mig_state = qpcb->path_migration_state - 1;
+       qp_attr->rq_psn = qpcb->receive_psn;
+       qp_attr->sq_psn = qpcb->send_psn;
+       qp_attr->min_rnr_timer = qpcb->min_rnr_nak_timer_field;
+       qp_attr->cap.max_send_wr = qpcb->max_nr_outst_send_wr-1;
+       qp_attr->cap.max_recv_wr = qpcb->max_nr_outst_recv_wr-1;
+       /* UD_AV CIRCUMVENTION */
+       if (my_qp->qp_type == IB_QPT_UD) {
+               qp_attr->cap.max_send_sge =
+                       qpcb->actual_nr_sges_in_sq_wqe - 2;
+               qp_attr->cap.max_recv_sge =
+                       qpcb->actual_nr_sges_in_rq_wqe - 2;
+       } else {
+               qp_attr->cap.max_send_sge =
+                       qpcb->actual_nr_sges_in_sq_wqe;
+               qp_attr->cap.max_recv_sge =
+                       qpcb->actual_nr_sges_in_rq_wqe;
+       }
+
+       qp_attr->cap.max_inline_data = my_qp->sq_max_inline_data_size;
+       qp_attr->dest_qp_num = qpcb->dest_qp_nr;
+
+       qp_attr->pkey_index = qpcb->prim_p_key_idx;
+       qp_attr->port_num = qpcb->prim_phys_port;
+       qp_attr->timeout = qpcb->timeout;
+       qp_attr->retry_cnt = qpcb->retry_count;
+       qp_attr->rnr_retry = qpcb->rnr_retry_count;
+
+       qp_attr->alt_pkey_index = qpcb->alt_p_key_idx;
+       qp_attr->alt_port_num = qpcb->alt_phys_port;
+       qp_attr->alt_timeout = qpcb->timeout_al;
+
+       qp_attr->max_dest_rd_atomic = qpcb->rdma_nr_atomic_resp_res;
+       qp_attr->max_rd_atomic = qpcb->rdma_atomic_outst_dest_qp;
+
+       /* primary av */
+       qp_attr->ah_attr.sl = qpcb->service_level;
+
+       if (qpcb->send_grh_flag) {
+               qp_attr->ah_attr.ah_flags = IB_AH_GRH;
+       }
+
+       qp_attr->ah_attr.static_rate = qpcb->max_static_rate;
+       qp_attr->ah_attr.dlid = qpcb->dlid;
+       qp_attr->ah_attr.src_path_bits = qpcb->source_path_bits;
+       qp_attr->ah_attr.port_num = qp_attr->port_num;
+
+       /* primary GRH */
+       qp_attr->ah_attr.grh.traffic_class = qpcb->traffic_class;
+       qp_attr->ah_attr.grh.hop_limit = qpcb->hop_limit;
+       qp_attr->ah_attr.grh.sgid_index = qpcb->source_gid_idx;
+       qp_attr->ah_attr.grh.flow_label = qpcb->flow_label;
+
+       for (cnt = 0; cnt < 16; cnt++)
+               qp_attr->ah_attr.grh.dgid.raw[cnt] =
+                       qpcb->dest_gid.byte[cnt];
+
+       /* alternate AV */
+       qp_attr->alt_ah_attr.sl = qpcb->service_level_al;
+       if (qpcb->send_grh_flag_al) {
+               qp_attr->alt_ah_attr.ah_flags = IB_AH_GRH;
+       }
+
+       qp_attr->alt_ah_attr.static_rate = qpcb->max_static_rate_al;
+       qp_attr->alt_ah_attr.dlid = qpcb->dlid_al;
+       qp_attr->alt_ah_attr.src_path_bits = qpcb->source_path_bits_al;
+
+       /* alternate GRH */
+       qp_attr->alt_ah_attr.grh.traffic_class = qpcb->traffic_class_al;
+       qp_attr->alt_ah_attr.grh.hop_limit = qpcb->hop_limit_al;
+       qp_attr->alt_ah_attr.grh.sgid_index = qpcb->source_gid_idx_al;
+       qp_attr->alt_ah_attr.grh.flow_label = qpcb->flow_label_al;
+
+       for (cnt = 0; cnt < 16; cnt++)
+               qp_attr->alt_ah_attr.grh.dgid.raw[cnt] =
+                       qpcb->dest_gid_al.byte[cnt];
+
+       /* return init attributes given in ehca_create_qp */
+       if (qp_init_attr)
+               *qp_init_attr = my_qp->init_attr;
+
+       if (ehca_debug_level >= 2)
+               ehca_dmp(qpcb, 4*70, "qp_num=%x", qp->qp_num);
+
+query_qp_exit1:
+       ehca_free_fw_ctrlblock(qpcb);
+
+       return ret;
+}
+
+int ehca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
+                   enum ib_srq_attr_mask attr_mask, struct ib_udata *udata)
+{
+       struct ehca_qp *my_qp =
+               container_of(ibsrq, struct ehca_qp, ib_srq);
+       struct ehca_shca *shca =
+               container_of(ibsrq->pd->device, struct ehca_shca, ib_device);
+       struct hcp_modify_qp_control_block *mqpcb;
+       u64 update_mask;
+       u64 h_ret;
+       int ret = 0;
+
+       mqpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
+       if (!mqpcb) {
+               ehca_err(ibsrq->device, "Could not get zeroed page for mqpcb "
+                        "ehca_qp=%p qp_num=%x ", my_qp, my_qp->real_qp_num);
+               return -ENOMEM;
+       }
+
+       update_mask = 0;
+       if (attr_mask & IB_SRQ_LIMIT) {
+               attr_mask &= ~IB_SRQ_LIMIT;
+               update_mask |=
+                       EHCA_BMASK_SET(MQPCB_MASK_CURR_SRQ_LIMIT, 1)
+                       | EHCA_BMASK_SET(MQPCB_MASK_QP_AFF_ASYN_EV_LOG_REG, 1);
+               mqpcb->curr_srq_limit = attr->srq_limit;
+               mqpcb->qp_aff_asyn_ev_log_reg =
+                       EHCA_BMASK_SET(QPX_AAELOG_RESET_SRQ_LIMIT, 1);
+       }
+
+       /* by now, all bits in attr_mask should have been cleared */
+       if (attr_mask) {
+               ehca_err(ibsrq->device, "invalid attribute mask bits set  "
+                        "attr_mask=%x", attr_mask);
+               ret = -EINVAL;
+               goto modify_srq_exit0;
+       }
+
+       if (ehca_debug_level >= 2)
+               ehca_dmp(mqpcb, 4*70, "qp_num=%x", my_qp->real_qp_num);
+
+       h_ret = hipz_h_modify_qp(shca->ipz_hca_handle, my_qp->ipz_qp_handle,
+                                NULL, update_mask, mqpcb,
+                                my_qp->galpas.kernel);
+
+       if (h_ret != H_SUCCESS) {
+               ret = ehca2ib_return_code(h_ret);
+               ehca_err(ibsrq->device, "hipz_h_modify_qp() failed h_ret=%lli "
+                        "ehca_qp=%p qp_num=%x",
+                        h_ret, my_qp, my_qp->real_qp_num);
+       }
+
+modify_srq_exit0:
+       ehca_free_fw_ctrlblock(mqpcb);
+
+       return ret;
+}
+
+int ehca_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr)
+{
+       struct ehca_qp *my_qp = container_of(srq, struct ehca_qp, ib_srq);
+       struct ehca_shca *shca = container_of(srq->device, struct ehca_shca,
+                                             ib_device);
+       struct ipz_adapter_handle adapter_handle = shca->ipz_hca_handle;
+       struct hcp_modify_qp_control_block *qpcb;
+       int ret = 0;
+       u64 h_ret;
+
+       qpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
+       if (!qpcb) {
+               ehca_err(srq->device, "Out of memory for qpcb "
+                        "ehca_qp=%p qp_num=%x", my_qp, my_qp->real_qp_num);
+               return -ENOMEM;
+       }
+
+       h_ret = hipz_h_query_qp(adapter_handle, my_qp->ipz_qp_handle,
+                               NULL, qpcb, my_qp->galpas.kernel);
+
+       if (h_ret != H_SUCCESS) {
+               ret = ehca2ib_return_code(h_ret);
+               ehca_err(srq->device, "hipz_h_query_qp() failed "
+                        "ehca_qp=%p qp_num=%x h_ret=%lli",
+                        my_qp, my_qp->real_qp_num, h_ret);
+               goto query_srq_exit1;
+       }
+
+       srq_attr->max_wr = qpcb->max_nr_outst_recv_wr - 1;
+       srq_attr->max_sge = 3;
+       srq_attr->srq_limit = qpcb->curr_srq_limit;
+
+       if (ehca_debug_level >= 2)
+               ehca_dmp(qpcb, 4*70, "qp_num=%x", my_qp->real_qp_num);
+
+query_srq_exit1:
+       ehca_free_fw_ctrlblock(qpcb);
+
+       return ret;
+}
+
+static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
+                              struct ib_uobject *uobject)
+{
+       struct ehca_shca *shca = container_of(dev, struct ehca_shca, ib_device);
+       struct ehca_pd *my_pd = container_of(my_qp->ib_qp.pd, struct ehca_pd,
+                                            ib_pd);
+       struct ehca_sport *sport = &shca->sport[my_qp->init_attr.port_num - 1];
+       u32 qp_num = my_qp->real_qp_num;
+       int ret;
+       u64 h_ret;
+       u8 port_num;
+       int is_user = 0;
+       enum ib_qp_type qp_type;
+       unsigned long flags;
+
+       if (uobject) {
+               is_user = 1;
+               if (my_qp->mm_count_galpa ||
+                   my_qp->mm_count_rqueue || my_qp->mm_count_squeue) {
+                       ehca_err(dev, "Resources still referenced in "
+                                "user space qp_num=%x", qp_num);
+                       return -EINVAL;
+               }
+       }
+
+       if (my_qp->send_cq) {
+               ret = ehca_cq_unassign_qp(my_qp->send_cq, qp_num);
+               if (ret) {
+                       ehca_err(dev, "Couldn't unassign qp from "
+                                "send_cq ret=%i qp_num=%x cq_num=%x", ret,
+                                qp_num, my_qp->send_cq->cq_number);
+                       return ret;
+               }
+       }
+
+       write_lock_irqsave(&ehca_qp_idr_lock, flags);
+       idr_remove(&ehca_qp_idr, my_qp->token);
+       write_unlock_irqrestore(&ehca_qp_idr_lock, flags);
+
+       /*
+        * SRQs will never get into an error list and do not have a recv_cq,
+        * so we need to skip them here.
+        */
+       if (HAS_RQ(my_qp) && !IS_SRQ(my_qp) && !is_user)
+               del_from_err_list(my_qp->recv_cq, &my_qp->rq_err_node);
+
+       if (HAS_SQ(my_qp) && !is_user)
+               del_from_err_list(my_qp->send_cq, &my_qp->sq_err_node);
+
+       /* now wait until all pending events have completed */
+       wait_event(my_qp->wait_completion, !atomic_read(&my_qp->nr_events));
+
+       h_ret = hipz_h_destroy_qp(shca->ipz_hca_handle, my_qp);
+       if (h_ret != H_SUCCESS) {
+               ehca_err(dev, "hipz_h_destroy_qp() failed h_ret=%lli "
+                        "ehca_qp=%p qp_num=%x", h_ret, my_qp, qp_num);
+               return ehca2ib_return_code(h_ret);
+       }
+
+       port_num = my_qp->init_attr.port_num;
+       qp_type  = my_qp->init_attr.qp_type;
+
+       if (qp_type == IB_QPT_SMI || qp_type == IB_QPT_GSI) {
+               spin_lock_irqsave(&sport->mod_sqp_lock, flags);
+               kfree(my_qp->mod_qp_parm);
+               my_qp->mod_qp_parm = NULL;
+               shca->sport[port_num - 1].ibqp_sqp[qp_type] = NULL;
+               spin_unlock_irqrestore(&sport->mod_sqp_lock, flags);
+       }
+
+       /* no support for IB_QPT_SMI yet */
+       if (qp_type == IB_QPT_GSI) {
+               struct ib_event event;
+               ehca_info(dev, "device %s: port %x is inactive.",
+                               shca->ib_device.name, port_num);
+               event.device = &shca->ib_device;
+               event.event = IB_EVENT_PORT_ERR;
+               event.element.port_num = port_num;
+               shca->sport[port_num - 1].port_state = IB_PORT_DOWN;
+               ib_dispatch_event(&event);
+       }
+
+       if (HAS_RQ(my_qp)) {
+               ipz_queue_dtor(my_pd, &my_qp->ipz_rqueue);
+               if (!is_user)
+                       vfree(my_qp->rq_map.map);
+       }
+       if (HAS_SQ(my_qp)) {
+               ipz_queue_dtor(my_pd, &my_qp->ipz_squeue);
+               if (!is_user)
+                       vfree(my_qp->sq_map.map);
+       }
+       kmem_cache_free(qp_cache, my_qp);
+       atomic_dec(&shca->num_qps);
+       return 0;
+}
+
+int ehca_destroy_qp(struct ib_qp *qp)
+{
+       return internal_destroy_qp(qp->device,
+                                  container_of(qp, struct ehca_qp, ib_qp),
+                                  qp->uobject);
+}
+
+int ehca_destroy_srq(struct ib_srq *srq)
+{
+       return internal_destroy_qp(srq->device,
+                                  container_of(srq, struct ehca_qp, ib_srq),
+                                  srq->uobject);
+}
+
+int ehca_init_qp_cache(void)
+{
+       qp_cache = kmem_cache_create("ehca_cache_qp",
+                                    sizeof(struct ehca_qp), 0,
+                                    SLAB_HWCACHE_ALIGN,
+                                    NULL);
+       if (!qp_cache)
+               return -ENOMEM;
+       return 0;
+}
+
+void ehca_cleanup_qp_cache(void)
+{
+       if (qp_cache)
+               kmem_cache_destroy(qp_cache);
+}
diff --git a/drivers/staging/rdma/ehca/ehca_reqs.c b/drivers/staging/rdma/ehca/ehca_reqs.c
new file mode 100644 (file)
index 0000000..47f9498
--- /dev/null
@@ -0,0 +1,953 @@
+/*
+ *  IBM eServer eHCA Infiniband device driver for Linux on POWER
+ *
+ *  post_send/recv, poll_cq, req_notify
+ *
+ *  Authors: Hoang-Nam Nguyen <hnguyen@de.ibm.com>
+ *           Waleri Fomin <fomin@de.ibm.com>
+ *           Joachim Fenkes <fenkes@de.ibm.com>
+ *           Reinhard Ernst <rernst@de.ibm.com>
+ *
+ *  Copyright (c) 2005 IBM Corporation
+ *
+ *  All rights reserved.
+ *
+ *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
+ *  BSD.
+ *
+ * OpenIB BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "ehca_classes.h"
+#include "ehca_tools.h"
+#include "ehca_qes.h"
+#include "ehca_iverbs.h"
+#include "hcp_if.h"
+#include "hipz_fns.h"
+
+/* in RC traffic, insert an empty RDMA READ every this many packets */
+#define ACK_CIRC_THRESHOLD 2000000
+
+static u64 replace_wr_id(u64 wr_id, u16 idx)
+{
+       u64 ret;
+
+       ret = wr_id & ~QMAP_IDX_MASK;
+       ret |= idx & QMAP_IDX_MASK;
+
+       return ret;
+}
+
+static u16 get_app_wr_id(u64 wr_id)
+{
+       return wr_id & QMAP_IDX_MASK;
+}
+
+static inline int ehca_write_rwqe(struct ipz_queue *ipz_rqueue,
+                                 struct ehca_wqe *wqe_p,
+                                 struct ib_recv_wr *recv_wr,
+                                 u32 rq_map_idx)
+{
+       u8 cnt_ds;
+       if (unlikely((recv_wr->num_sge < 0) ||
+                    (recv_wr->num_sge > ipz_rqueue->act_nr_of_sg))) {
+               ehca_gen_err("Invalid number of WQE SGE. "
+                        "num_sqe=%x max_nr_of_sg=%x",
+                        recv_wr->num_sge, ipz_rqueue->act_nr_of_sg);
+               return -EINVAL; /* invalid SG list length */
+       }
+
+       /* clear wqe header until sglist */
+       memset(wqe_p, 0, offsetof(struct ehca_wqe, u.ud_av.sg_list));
+
+       wqe_p->work_request_id = replace_wr_id(recv_wr->wr_id, rq_map_idx);
+       wqe_p->nr_of_data_seg = recv_wr->num_sge;
+
+       for (cnt_ds = 0; cnt_ds < recv_wr->num_sge; cnt_ds++) {
+               wqe_p->u.all_rcv.sg_list[cnt_ds].vaddr =
+                       recv_wr->sg_list[cnt_ds].addr;
+               wqe_p->u.all_rcv.sg_list[cnt_ds].lkey =
+                       recv_wr->sg_list[cnt_ds].lkey;
+               wqe_p->u.all_rcv.sg_list[cnt_ds].length =
+                       recv_wr->sg_list[cnt_ds].length;
+       }
+
+       if (ehca_debug_level >= 3) {
+               ehca_gen_dbg("RECEIVE WQE written into ipz_rqueue=%p",
+                            ipz_rqueue);
+               ehca_dmp(wqe_p, 16*(6 + wqe_p->nr_of_data_seg), "recv wqe");
+       }
+
+       return 0;
+}
+
+#if defined(DEBUG_GSI_SEND_WR)
+
+/* need ib_mad struct */
+#include <rdma/ib_mad.h>
+
+static void trace_send_wr_ud(const struct ib_send_wr *send_wr)
+{
+       int idx;
+       int j;
+       while (send_wr) {
+               struct ib_mad_hdr *mad_hdr = send_wr->wr.ud.mad_hdr;
+               struct ib_sge *sge = send_wr->sg_list;
+               ehca_gen_dbg("send_wr#%x wr_id=%lx num_sge=%x "
+                            "send_flags=%x opcode=%x", idx, send_wr->wr_id,
+                            send_wr->num_sge, send_wr->send_flags,
+                            send_wr->opcode);
+               if (mad_hdr) {
+                       ehca_gen_dbg("send_wr#%x mad_hdr base_version=%x "
+                                    "mgmt_class=%x class_version=%x method=%x "
+                                    "status=%x class_specific=%x tid=%lx "
+                                    "attr_id=%x resv=%x attr_mod=%x",
+                                    idx, mad_hdr->base_version,
+                                    mad_hdr->mgmt_class,
+                                    mad_hdr->class_version, mad_hdr->method,
+                                    mad_hdr->status, mad_hdr->class_specific,
+                                    mad_hdr->tid, mad_hdr->attr_id,
+                                    mad_hdr->resv,
+                                    mad_hdr->attr_mod);
+               }
+               for (j = 0; j < send_wr->num_sge; j++) {
+                       u8 *data = __va(sge->addr);
+                       ehca_gen_dbg("send_wr#%x sge#%x addr=%p length=%x "
+                                    "lkey=%x",
+                                    idx, j, data, sge->length, sge->lkey);
+                       /* assume length is n*16 */
+                       ehca_dmp(data, sge->length, "send_wr#%x sge#%x",
+                                idx, j);
+                       sge++;
+               } /* eof for j */
+               idx++;
+               send_wr = send_wr->next;
+       } /* eof while send_wr */
+}
+
+#endif /* DEBUG_GSI_SEND_WR */
+
+static inline int ehca_write_swqe(struct ehca_qp *qp,
+                                 struct ehca_wqe *wqe_p,
+                                 const struct ib_send_wr *send_wr,
+                                 u32 sq_map_idx,
+                                 int hidden)
+{
+       u32 idx;
+       u64 dma_length;
+       struct ehca_av *my_av;
+       u32 remote_qkey = send_wr->wr.ud.remote_qkey;
+       struct ehca_qmap_entry *qmap_entry = &qp->sq_map.map[sq_map_idx];
+
+       if (unlikely((send_wr->num_sge < 0) ||
+                    (send_wr->num_sge > qp->ipz_squeue.act_nr_of_sg))) {
+               ehca_gen_err("Invalid number of WQE SGE. "
+                        "num_sqe=%x max_nr_of_sg=%x",
+                        send_wr->num_sge, qp->ipz_squeue.act_nr_of_sg);
+               return -EINVAL; /* invalid SG list length */
+       }
+
+       /* clear wqe header until sglist */
+       memset(wqe_p, 0, offsetof(struct ehca_wqe, u.ud_av.sg_list));
+
+       wqe_p->work_request_id = replace_wr_id(send_wr->wr_id, sq_map_idx);
+
+       qmap_entry->app_wr_id = get_app_wr_id(send_wr->wr_id);
+       qmap_entry->reported = 0;
+       qmap_entry->cqe_req = 0;
+
+       switch (send_wr->opcode) {
+       case IB_WR_SEND:
+       case IB_WR_SEND_WITH_IMM:
+               wqe_p->optype = WQE_OPTYPE_SEND;
+               break;
+       case IB_WR_RDMA_WRITE:
+       case IB_WR_RDMA_WRITE_WITH_IMM:
+               wqe_p->optype = WQE_OPTYPE_RDMAWRITE;
+               break;
+       case IB_WR_RDMA_READ:
+               wqe_p->optype = WQE_OPTYPE_RDMAREAD;
+               break;
+       default:
+               ehca_gen_err("Invalid opcode=%x", send_wr->opcode);
+               return -EINVAL; /* invalid opcode */
+       }
+
+       wqe_p->wqef = (send_wr->opcode) & WQEF_HIGH_NIBBLE;
+
+       wqe_p->wr_flag = 0;
+
+       if ((send_wr->send_flags & IB_SEND_SIGNALED ||
+           qp->init_attr.sq_sig_type == IB_SIGNAL_ALL_WR)
+           && !hidden) {
+               wqe_p->wr_flag |= WQE_WRFLAG_REQ_SIGNAL_COM;
+               qmap_entry->cqe_req = 1;
+       }
+
+       if (send_wr->opcode == IB_WR_SEND_WITH_IMM ||
+           send_wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM) {
+               /* this might not work as long as HW does not support it */
+               wqe_p->immediate_data = be32_to_cpu(send_wr->ex.imm_data);
+               wqe_p->wr_flag |= WQE_WRFLAG_IMM_DATA_PRESENT;
+       }
+
+       wqe_p->nr_of_data_seg = send_wr->num_sge;
+
+       switch (qp->qp_type) {
+       case IB_QPT_SMI:
+       case IB_QPT_GSI:
+               /* no break is intential here */
+       case IB_QPT_UD:
+               /* IB 1.2 spec C10-15 compliance */
+               if (send_wr->wr.ud.remote_qkey & 0x80000000)
+                       remote_qkey = qp->qkey;
+
+               wqe_p->destination_qp_number = send_wr->wr.ud.remote_qpn << 8;
+               wqe_p->local_ee_context_qkey = remote_qkey;
+               if (unlikely(!send_wr->wr.ud.ah)) {
+                       ehca_gen_err("wr.ud.ah is NULL. qp=%p", qp);
+                       return -EINVAL;
+               }
+               if (unlikely(send_wr->wr.ud.remote_qpn == 0)) {
+                       ehca_gen_err("dest QP# is 0. qp=%x", qp->real_qp_num);
+                       return -EINVAL;
+               }
+               my_av = container_of(send_wr->wr.ud.ah, struct ehca_av, ib_ah);
+               wqe_p->u.ud_av.ud_av = my_av->av;
+
+               /*
+                * omitted check of IB_SEND_INLINE
+                * since HW does not support it
+                */
+               for (idx = 0; idx < send_wr->num_sge; idx++) {
+                       wqe_p->u.ud_av.sg_list[idx].vaddr =
+                               send_wr->sg_list[idx].addr;
+                       wqe_p->u.ud_av.sg_list[idx].lkey =
+                               send_wr->sg_list[idx].lkey;
+                       wqe_p->u.ud_av.sg_list[idx].length =
+                               send_wr->sg_list[idx].length;
+               } /* eof for idx */
+               if (qp->qp_type == IB_QPT_SMI ||
+                   qp->qp_type == IB_QPT_GSI)
+                       wqe_p->u.ud_av.ud_av.pmtu = 1;
+               if (qp->qp_type == IB_QPT_GSI) {
+                       wqe_p->pkeyi = send_wr->wr.ud.pkey_index;
+#ifdef DEBUG_GSI_SEND_WR
+                       trace_send_wr_ud(send_wr);
+#endif /* DEBUG_GSI_SEND_WR */
+               }
+               break;
+
+       case IB_QPT_UC:
+               if (send_wr->send_flags & IB_SEND_FENCE)
+                       wqe_p->wr_flag |= WQE_WRFLAG_FENCE;
+               /* no break is intentional here */
+       case IB_QPT_RC:
+               /* TODO: atomic not implemented */
+               wqe_p->u.nud.remote_virtual_address =
+                       send_wr->wr.rdma.remote_addr;
+               wqe_p->u.nud.rkey = send_wr->wr.rdma.rkey;
+
+               /*
+                * omitted checking of IB_SEND_INLINE
+                * since HW does not support it
+                */
+               dma_length = 0;
+               for (idx = 0; idx < send_wr->num_sge; idx++) {
+                       wqe_p->u.nud.sg_list[idx].vaddr =
+                               send_wr->sg_list[idx].addr;
+                       wqe_p->u.nud.sg_list[idx].lkey =
+                               send_wr->sg_list[idx].lkey;
+                       wqe_p->u.nud.sg_list[idx].length =
+                               send_wr->sg_list[idx].length;
+                       dma_length += send_wr->sg_list[idx].length;
+               } /* eof idx */
+               wqe_p->u.nud.atomic_1st_op_dma_len = dma_length;
+
+               /* unsolicited ack circumvention */
+               if (send_wr->opcode == IB_WR_RDMA_READ) {
+                       /* on RDMA read, switch on and reset counters */
+                       qp->message_count = qp->packet_count = 0;
+                       qp->unsol_ack_circ = 1;
+               } else
+                       /* else estimate #packets */
+                       qp->packet_count += (dma_length >> qp->mtu_shift) + 1;
+
+               break;
+
+       default:
+               ehca_gen_err("Invalid qptype=%x", qp->qp_type);
+               return -EINVAL;
+       }
+
+       if (ehca_debug_level >= 3) {
+               ehca_gen_dbg("SEND WQE written into queue qp=%p ", qp);
+               ehca_dmp( wqe_p, 16*(6 + wqe_p->nr_of_data_seg), "send wqe");
+       }
+       return 0;
+}
+
+/* map_ib_wc_status converts raw cqe_status to ib_wc_status */
+static inline void map_ib_wc_status(u32 cqe_status,
+                                   enum ib_wc_status *wc_status)
+{
+       if (unlikely(cqe_status & WC_STATUS_ERROR_BIT)) {
+               switch (cqe_status & 0x3F) {
+               case 0x01:
+               case 0x21:
+                       *wc_status = IB_WC_LOC_LEN_ERR;
+                       break;
+               case 0x02:
+               case 0x22:
+                       *wc_status = IB_WC_LOC_QP_OP_ERR;
+                       break;
+               case 0x03:
+               case 0x23:
+                       *wc_status = IB_WC_LOC_EEC_OP_ERR;
+                       break;
+               case 0x04:
+               case 0x24:
+                       *wc_status = IB_WC_LOC_PROT_ERR;
+                       break;
+               case 0x05:
+               case 0x25:
+                       *wc_status = IB_WC_WR_FLUSH_ERR;
+                       break;
+               case 0x06:
+                       *wc_status = IB_WC_MW_BIND_ERR;
+                       break;
+               case 0x07: /* remote error - look into bits 20:24 */
+                       switch ((cqe_status
+                                & WC_STATUS_REMOTE_ERROR_FLAGS) >> 11) {
+                       case 0x0:
+                               /*
+                                * PSN Sequence Error!
+                                * couldn't find a matching status!
+                                */
+                               *wc_status = IB_WC_GENERAL_ERR;
+                               break;
+                       case 0x1:
+                               *wc_status = IB_WC_REM_INV_REQ_ERR;
+                               break;
+                       case 0x2:
+                               *wc_status = IB_WC_REM_ACCESS_ERR;
+                               break;
+                       case 0x3:
+                               *wc_status = IB_WC_REM_OP_ERR;
+                               break;
+                       case 0x4:
+                               *wc_status = IB_WC_REM_INV_RD_REQ_ERR;
+                               break;
+                       }
+                       break;
+               case 0x08:
+                       *wc_status = IB_WC_RETRY_EXC_ERR;
+                       break;
+               case 0x09:
+                       *wc_status = IB_WC_RNR_RETRY_EXC_ERR;
+                       break;
+               case 0x0A:
+               case 0x2D:
+                       *wc_status = IB_WC_REM_ABORT_ERR;
+                       break;
+               case 0x0B:
+               case 0x2E:
+                       *wc_status = IB_WC_INV_EECN_ERR;
+                       break;
+               case 0x0C:
+               case 0x2F:
+                       *wc_status = IB_WC_INV_EEC_STATE_ERR;
+                       break;
+               case 0x0D:
+                       *wc_status = IB_WC_BAD_RESP_ERR;
+                       break;
+               case 0x10:
+                       /* WQE purged */
+                       *wc_status = IB_WC_WR_FLUSH_ERR;
+                       break;
+               default:
+                       *wc_status = IB_WC_FATAL_ERR;
+
+               }
+       } else
+               *wc_status = IB_WC_SUCCESS;
+}
+
+static inline int post_one_send(struct ehca_qp *my_qp,
+                        struct ib_send_wr *cur_send_wr,
+                        int hidden)
+{
+       struct ehca_wqe *wqe_p;
+       int ret;
+       u32 sq_map_idx;
+       u64 start_offset = my_qp->ipz_squeue.current_q_offset;
+
+       /* get pointer next to free WQE */
+       wqe_p = ipz_qeit_get_inc(&my_qp->ipz_squeue);
+       if (unlikely(!wqe_p)) {
+               /* too many posted work requests: queue overflow */
+               ehca_err(my_qp->ib_qp.device, "Too many posted WQEs "
+                        "qp_num=%x", my_qp->ib_qp.qp_num);
+               return -ENOMEM;
+       }
+
+       /*
+        * Get the index of the WQE in the send queue. The same index is used
+        * for writing into the sq_map.
+        */
+       sq_map_idx = start_offset / my_qp->ipz_squeue.qe_size;
+
+       /* write a SEND WQE into the QUEUE */
+       ret = ehca_write_swqe(my_qp, wqe_p, cur_send_wr, sq_map_idx, hidden);
+       /*
+        * if something failed,
+        * reset the free entry pointer to the start value
+        */
+       if (unlikely(ret)) {
+               my_qp->ipz_squeue.current_q_offset = start_offset;
+               ehca_err(my_qp->ib_qp.device, "Could not write WQE "
+                        "qp_num=%x", my_qp->ib_qp.qp_num);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+int ehca_post_send(struct ib_qp *qp,
+                  struct ib_send_wr *send_wr,
+                  struct ib_send_wr **bad_send_wr)
+{
+       struct ehca_qp *my_qp = container_of(qp, struct ehca_qp, ib_qp);
+       int wqe_cnt = 0;
+       int ret = 0;
+       unsigned long flags;
+
+       /* Reject WR if QP is in RESET, INIT or RTR state */
+       if (unlikely(my_qp->state < IB_QPS_RTS)) {
+               ehca_err(qp->device, "Invalid QP state  qp_state=%d qpn=%x",
+                        my_qp->state, qp->qp_num);
+               ret = -EINVAL;
+               goto out;
+       }
+
+       /* LOCK the QUEUE */
+       spin_lock_irqsave(&my_qp->spinlock_s, flags);
+
+       /* Send an empty extra RDMA read if:
+        *  1) there has been an RDMA read on this connection before
+        *  2) no RDMA read occurred for ACK_CIRC_THRESHOLD link packets
+        *  3) we can be sure that any previous extra RDMA read has been
+        *     processed so we don't overflow the SQ
+        */
+       if (unlikely(my_qp->unsol_ack_circ &&
+                    my_qp->packet_count > ACK_CIRC_THRESHOLD &&
+                    my_qp->message_count > my_qp->init_attr.cap.max_send_wr)) {
+               /* insert an empty RDMA READ to fix up the remote QP state */
+               struct ib_send_wr circ_wr;
+               memset(&circ_wr, 0, sizeof(circ_wr));
+               circ_wr.opcode = IB_WR_RDMA_READ;
+               post_one_send(my_qp, &circ_wr, 1); /* ignore retcode */
+               wqe_cnt++;
+               ehca_dbg(qp->device, "posted circ wr  qp_num=%x", qp->qp_num);
+               my_qp->message_count = my_qp->packet_count = 0;
+       }
+
+       /* loop processes list of send reqs */
+       while (send_wr) {
+               ret = post_one_send(my_qp, send_wr, 0);
+               if (unlikely(ret)) {
+                       goto post_send_exit0;
+               }
+               wqe_cnt++;
+               send_wr = send_wr->next;
+       }
+
+post_send_exit0:
+       iosync(); /* serialize GAL register access */
+       hipz_update_sqa(my_qp, wqe_cnt);
+       if (unlikely(ret || ehca_debug_level >= 2))
+               ehca_dbg(qp->device, "ehca_qp=%p qp_num=%x wqe_cnt=%d ret=%i",
+                        my_qp, qp->qp_num, wqe_cnt, ret);
+       my_qp->message_count += wqe_cnt;
+       spin_unlock_irqrestore(&my_qp->spinlock_s, flags);
+
+out:
+       if (ret)
+               *bad_send_wr = send_wr;
+       return ret;
+}
+
+static int internal_post_recv(struct ehca_qp *my_qp,
+                             struct ib_device *dev,
+                             struct ib_recv_wr *recv_wr,
+                             struct ib_recv_wr **bad_recv_wr)
+{
+       struct ehca_wqe *wqe_p;
+       int wqe_cnt = 0;
+       int ret = 0;
+       u32 rq_map_idx;
+       unsigned long flags;
+       struct ehca_qmap_entry *qmap_entry;
+
+       if (unlikely(!HAS_RQ(my_qp))) {
+               ehca_err(dev, "QP has no RQ  ehca_qp=%p qp_num=%x ext_type=%d",
+                        my_qp, my_qp->real_qp_num, my_qp->ext_type);
+               ret = -ENODEV;
+               goto out;
+       }
+
+       /* LOCK the QUEUE */
+       spin_lock_irqsave(&my_qp->spinlock_r, flags);
+
+       /* loop processes list of recv reqs */
+       while (recv_wr) {
+               u64 start_offset = my_qp->ipz_rqueue.current_q_offset;
+               /* get pointer next to free WQE */
+               wqe_p = ipz_qeit_get_inc(&my_qp->ipz_rqueue);
+               if (unlikely(!wqe_p)) {
+                       /* too many posted work requests: queue overflow */
+                       ret = -ENOMEM;
+                       ehca_err(dev, "Too many posted WQEs "
+                               "qp_num=%x", my_qp->real_qp_num);
+                       goto post_recv_exit0;
+               }
+               /*
+                * Get the index of the WQE in the recv queue. The same index
+                * is used for writing into the rq_map.
+                */
+               rq_map_idx = start_offset / my_qp->ipz_rqueue.qe_size;
+
+               /* write a RECV WQE into the QUEUE */
+               ret = ehca_write_rwqe(&my_qp->ipz_rqueue, wqe_p, recv_wr,
+                               rq_map_idx);
+               /*
+                * if something failed,
+                * reset the free entry pointer to the start value
+                */
+               if (unlikely(ret)) {
+                       my_qp->ipz_rqueue.current_q_offset = start_offset;
+                       ret = -EINVAL;
+                       ehca_err(dev, "Could not write WQE "
+                               "qp_num=%x", my_qp->real_qp_num);
+                       goto post_recv_exit0;
+               }
+
+               qmap_entry = &my_qp->rq_map.map[rq_map_idx];
+               qmap_entry->app_wr_id = get_app_wr_id(recv_wr->wr_id);
+               qmap_entry->reported = 0;
+               qmap_entry->cqe_req = 1;
+
+               wqe_cnt++;
+               recv_wr = recv_wr->next;
+       } /* eof for recv_wr */
+
+post_recv_exit0:
+       iosync(); /* serialize GAL register access */
+       hipz_update_rqa(my_qp, wqe_cnt);
+       if (unlikely(ret || ehca_debug_level >= 2))
+           ehca_dbg(dev, "ehca_qp=%p qp_num=%x wqe_cnt=%d ret=%i",
+                    my_qp, my_qp->real_qp_num, wqe_cnt, ret);
+       spin_unlock_irqrestore(&my_qp->spinlock_r, flags);
+
+out:
+       if (ret)
+               *bad_recv_wr = recv_wr;
+
+       return ret;
+}
+
+int ehca_post_recv(struct ib_qp *qp,
+                  struct ib_recv_wr *recv_wr,
+                  struct ib_recv_wr **bad_recv_wr)
+{
+       struct ehca_qp *my_qp = container_of(qp, struct ehca_qp, ib_qp);
+
+       /* Reject WR if QP is in RESET state */
+       if (unlikely(my_qp->state == IB_QPS_RESET)) {
+               ehca_err(qp->device, "Invalid QP state  qp_state=%d qpn=%x",
+                        my_qp->state, qp->qp_num);
+               *bad_recv_wr = recv_wr;
+               return -EINVAL;
+       }
+
+       return internal_post_recv(my_qp, qp->device, recv_wr, bad_recv_wr);
+}
+
+int ehca_post_srq_recv(struct ib_srq *srq,
+                      struct ib_recv_wr *recv_wr,
+                      struct ib_recv_wr **bad_recv_wr)
+{
+       return internal_post_recv(container_of(srq, struct ehca_qp, ib_srq),
+                                 srq->device, recv_wr, bad_recv_wr);
+}
+
+/*
+ * ib_wc_opcode table converts ehca wc opcode to ib
+ * Since we use zero to indicate invalid opcode, the actual ib opcode must
+ * be decremented!!!
+ */
+static const u8 ib_wc_opcode[255] = {
+       [0x01] = IB_WC_RECV+1,
+       [0x02] = IB_WC_RECV_RDMA_WITH_IMM+1,
+       [0x04] = IB_WC_BIND_MW+1,
+       [0x08] = IB_WC_FETCH_ADD+1,
+       [0x10] = IB_WC_COMP_SWAP+1,
+       [0x20] = IB_WC_RDMA_WRITE+1,
+       [0x40] = IB_WC_RDMA_READ+1,
+       [0x80] = IB_WC_SEND+1
+};
+
+/* internal function to poll one entry of cq */
+static inline int ehca_poll_cq_one(struct ib_cq *cq, struct ib_wc *wc)
+{
+       int ret = 0, qmap_tail_idx;
+       struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq);
+       struct ehca_cqe *cqe;
+       struct ehca_qp *my_qp;
+       struct ehca_qmap_entry *qmap_entry;
+       struct ehca_queue_map *qmap;
+       int cqe_count = 0, is_error;
+
+repoll:
+       cqe = (struct ehca_cqe *)
+               ipz_qeit_get_inc_valid(&my_cq->ipz_queue);
+       if (!cqe) {
+               ret = -EAGAIN;
+               if (ehca_debug_level >= 3)
+                       ehca_dbg(cq->device, "Completion queue is empty  "
+                                "my_cq=%p cq_num=%x", my_cq, my_cq->cq_number);
+               goto poll_cq_one_exit0;
+       }
+
+       /* prevents loads being reordered across this point */
+       rmb();
+
+       cqe_count++;
+       if (unlikely(cqe->status & WC_STATUS_PURGE_BIT)) {
+               struct ehca_qp *qp;
+               int purgeflag;
+               unsigned long flags;
+
+               qp = ehca_cq_get_qp(my_cq, cqe->local_qp_number);
+               if (!qp) {
+                       ehca_err(cq->device, "cq_num=%x qp_num=%x "
+                                "could not find qp -> ignore cqe",
+                                my_cq->cq_number, cqe->local_qp_number);
+                       ehca_dmp(cqe, 64, "cq_num=%x qp_num=%x",
+                                my_cq->cq_number, cqe->local_qp_number);
+                       /* ignore this purged cqe */
+                       goto repoll;
+               }
+               spin_lock_irqsave(&qp->spinlock_s, flags);
+               purgeflag = qp->sqerr_purgeflag;
+               spin_unlock_irqrestore(&qp->spinlock_s, flags);
+
+               if (purgeflag) {
+                       ehca_dbg(cq->device,
+                                "Got CQE with purged bit qp_num=%x src_qp=%x",
+                                cqe->local_qp_number, cqe->remote_qp_number);
+                       if (ehca_debug_level >= 2)
+                               ehca_dmp(cqe, 64, "qp_num=%x src_qp=%x",
+                                        cqe->local_qp_number,
+                                        cqe->remote_qp_number);
+                       /*
+                        * ignore this to avoid double cqes of bad wqe
+                        * that caused sqe and turn off purge flag
+                        */
+                       qp->sqerr_purgeflag = 0;
+                       goto repoll;
+               }
+       }
+
+       is_error = cqe->status & WC_STATUS_ERROR_BIT;
+
+       /* trace error CQEs if debug_level >= 1, trace all CQEs if >= 3 */
+       if (unlikely(ehca_debug_level >= 3 || (ehca_debug_level && is_error))) {
+               ehca_dbg(cq->device,
+                        "Received %sCOMPLETION ehca_cq=%p cq_num=%x -----",
+                        is_error ? "ERROR " : "", my_cq, my_cq->cq_number);
+               ehca_dmp(cqe, 64, "ehca_cq=%p cq_num=%x",
+                        my_cq, my_cq->cq_number);
+               ehca_dbg(cq->device,
+                        "ehca_cq=%p cq_num=%x -------------------------",
+                        my_cq, my_cq->cq_number);
+       }
+
+       read_lock(&ehca_qp_idr_lock);
+       my_qp = idr_find(&ehca_qp_idr, cqe->qp_token);
+       read_unlock(&ehca_qp_idr_lock);
+       if (!my_qp)
+               goto repoll;
+       wc->qp = &my_qp->ib_qp;
+
+       qmap_tail_idx = get_app_wr_id(cqe->work_request_id);
+       if (!(cqe->w_completion_flags & WC_SEND_RECEIVE_BIT))
+               /* We got a send completion. */
+               qmap = &my_qp->sq_map;
+       else
+               /* We got a receive completion. */
+               qmap = &my_qp->rq_map;
+
+       /* advance the tail pointer */
+       qmap->tail = qmap_tail_idx;
+
+       if (is_error) {
+               /*
+                * set left_to_poll to 0 because in error state, we will not
+                * get any additional CQEs
+                */
+               my_qp->sq_map.next_wqe_idx = next_index(my_qp->sq_map.tail,
+                                                       my_qp->sq_map.entries);
+               my_qp->sq_map.left_to_poll = 0;
+               ehca_add_to_err_list(my_qp, 1);
+
+               my_qp->rq_map.next_wqe_idx = next_index(my_qp->rq_map.tail,
+                                                       my_qp->rq_map.entries);
+               my_qp->rq_map.left_to_poll = 0;
+               if (HAS_RQ(my_qp))
+                       ehca_add_to_err_list(my_qp, 0);
+       }
+
+       qmap_entry = &qmap->map[qmap_tail_idx];
+       if (qmap_entry->reported) {
+               ehca_warn(cq->device, "Double cqe on qp_num=%#x",
+                               my_qp->real_qp_num);
+               /* found a double cqe, discard it and read next one */
+               goto repoll;
+       }
+
+       wc->wr_id = replace_wr_id(cqe->work_request_id, qmap_entry->app_wr_id);
+       qmap_entry->reported = 1;
+
+       /* if left_to_poll is decremented to 0, add the QP to the error list */
+       if (qmap->left_to_poll > 0) {
+               qmap->left_to_poll--;
+               if ((my_qp->sq_map.left_to_poll == 0) &&
+                               (my_qp->rq_map.left_to_poll == 0)) {
+                       ehca_add_to_err_list(my_qp, 1);
+                       if (HAS_RQ(my_qp))
+                               ehca_add_to_err_list(my_qp, 0);
+               }
+       }
+
+       /* eval ib_wc_opcode */
+       wc->opcode = ib_wc_opcode[cqe->optype]-1;
+       if (unlikely(wc->opcode == -1)) {
+               ehca_err(cq->device, "Invalid cqe->OPType=%x cqe->status=%x "
+                        "ehca_cq=%p cq_num=%x",
+                        cqe->optype, cqe->status, my_cq, my_cq->cq_number);
+               /* dump cqe for other infos */
+               ehca_dmp(cqe, 64, "ehca_cq=%p cq_num=%x",
+                        my_cq, my_cq->cq_number);
+               /* update also queue adder to throw away this entry!!! */
+               goto repoll;
+       }
+
+       /* eval ib_wc_status */
+       if (unlikely(is_error)) {
+               /* complete with errors */
+               map_ib_wc_status(cqe->status, &wc->status);
+               wc->vendor_err = wc->status;
+       } else
+               wc->status = IB_WC_SUCCESS;
+
+       wc->byte_len = cqe->nr_bytes_transferred;
+       wc->pkey_index = cqe->pkey_index;
+       wc->slid = cqe->rlid;
+       wc->dlid_path_bits = cqe->dlid;
+       wc->src_qp = cqe->remote_qp_number;
+       /*
+        * HW has "Immed data present" and "GRH present" in bits 6 and 5.
+        * SW defines those in bits 1 and 0, so we can just shift and mask.
+        */
+       wc->wc_flags = (cqe->w_completion_flags >> 5) & 3;
+       wc->ex.imm_data = cpu_to_be32(cqe->immediate_data);
+       wc->sl = cqe->service_level;
+
+poll_cq_one_exit0:
+       if (cqe_count > 0)
+               hipz_update_feca(my_cq, cqe_count);
+
+       return ret;
+}
+
+static int generate_flush_cqes(struct ehca_qp *my_qp, struct ib_cq *cq,
+                              struct ib_wc *wc, int num_entries,
+                              struct ipz_queue *ipz_queue, int on_sq)
+{
+       int nr = 0;
+       struct ehca_wqe *wqe;
+       u64 offset;
+       struct ehca_queue_map *qmap;
+       struct ehca_qmap_entry *qmap_entry;
+
+       if (on_sq)
+               qmap = &my_qp->sq_map;
+       else
+               qmap = &my_qp->rq_map;
+
+       qmap_entry = &qmap->map[qmap->next_wqe_idx];
+
+       while ((nr < num_entries) && (qmap_entry->reported == 0)) {
+               /* generate flush CQE */
+
+               memset(wc, 0, sizeof(*wc));
+
+               offset = qmap->next_wqe_idx * ipz_queue->qe_size;
+               wqe = (struct ehca_wqe *)ipz_qeit_calc(ipz_queue, offset);
+               if (!wqe) {
+                       ehca_err(cq->device, "Invalid wqe offset=%#llx on "
+                                "qp_num=%#x", offset, my_qp->real_qp_num);
+                       return nr;
+               }
+
+               wc->wr_id = replace_wr_id(wqe->work_request_id,
+                                         qmap_entry->app_wr_id);
+
+               if (on_sq) {
+                       switch (wqe->optype) {
+                       case WQE_OPTYPE_SEND:
+                               wc->opcode = IB_WC_SEND;
+                               break;
+                       case WQE_OPTYPE_RDMAWRITE:
+                               wc->opcode = IB_WC_RDMA_WRITE;
+                               break;
+                       case WQE_OPTYPE_RDMAREAD:
+                               wc->opcode = IB_WC_RDMA_READ;
+                               break;
+                       default:
+                               ehca_err(cq->device, "Invalid optype=%x",
+                                               wqe->optype);
+                               return nr;
+                       }
+               } else
+                       wc->opcode = IB_WC_RECV;
+
+               if (wqe->wr_flag & WQE_WRFLAG_IMM_DATA_PRESENT) {
+                       wc->ex.imm_data = wqe->immediate_data;
+                       wc->wc_flags |= IB_WC_WITH_IMM;
+               }
+
+               wc->status = IB_WC_WR_FLUSH_ERR;
+
+               wc->qp = &my_qp->ib_qp;
+
+               /* mark as reported and advance next_wqe pointer */
+               qmap_entry->reported = 1;
+               qmap->next_wqe_idx = next_index(qmap->next_wqe_idx,
+                                               qmap->entries);
+               qmap_entry = &qmap->map[qmap->next_wqe_idx];
+
+               wc++; nr++;
+       }
+
+       return nr;
+
+}
+
+int ehca_poll_cq(struct ib_cq *cq, int num_entries, struct ib_wc *wc)
+{
+       struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq);
+       int nr;
+       struct ehca_qp *err_qp;
+       struct ib_wc *current_wc = wc;
+       int ret = 0;
+       unsigned long flags;
+       int entries_left = num_entries;
+
+       if (num_entries < 1) {
+               ehca_err(cq->device, "Invalid num_entries=%d ehca_cq=%p "
+                        "cq_num=%x", num_entries, my_cq, my_cq->cq_number);
+               ret = -EINVAL;
+               goto poll_cq_exit0;
+       }
+
+       spin_lock_irqsave(&my_cq->spinlock, flags);
+
+       /* generate flush cqes for send queues */
+       list_for_each_entry(err_qp, &my_cq->sqp_err_list, sq_err_node) {
+               nr = generate_flush_cqes(err_qp, cq, current_wc, entries_left,
+                               &err_qp->ipz_squeue, 1);
+               entries_left -= nr;
+               current_wc += nr;
+
+               if (entries_left == 0)
+                       break;
+       }
+
+       /* generate flush cqes for receive queues */
+       list_for_each_entry(err_qp, &my_cq->rqp_err_list, rq_err_node) {
+               nr = generate_flush_cqes(err_qp, cq, current_wc, entries_left,
+                               &err_qp->ipz_rqueue, 0);
+               entries_left -= nr;
+               current_wc += nr;
+
+               if (entries_left == 0)
+                       break;
+       }
+
+       for (nr = 0; nr < entries_left; nr++) {
+               ret = ehca_poll_cq_one(cq, current_wc);
+               if (ret)
+                       break;
+               current_wc++;
+       } /* eof for nr */
+       entries_left -= nr;
+
+       spin_unlock_irqrestore(&my_cq->spinlock, flags);
+       if (ret == -EAGAIN  || !ret)
+               ret = num_entries - entries_left;
+
+poll_cq_exit0:
+       return ret;
+}
+
+int ehca_req_notify_cq(struct ib_cq *cq, enum ib_cq_notify_flags notify_flags)
+{
+       struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq);
+       int ret = 0;
+
+       switch (notify_flags & IB_CQ_SOLICITED_MASK) {
+       case IB_CQ_SOLICITED:
+               hipz_set_cqx_n0(my_cq, 1);
+               break;
+       case IB_CQ_NEXT_COMP:
+               hipz_set_cqx_n1(my_cq, 1);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (notify_flags & IB_CQ_REPORT_MISSED_EVENTS) {
+               unsigned long spl_flags;
+               spin_lock_irqsave(&my_cq->spinlock, spl_flags);
+               ret = ipz_qeit_is_valid(&my_cq->ipz_queue);
+               spin_unlock_irqrestore(&my_cq->spinlock, spl_flags);
+       }
+
+       return ret;
+}
diff --git a/drivers/staging/rdma/ehca/ehca_sqp.c b/drivers/staging/rdma/ehca/ehca_sqp.c
new file mode 100644 (file)
index 0000000..376b031
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ *  IBM eServer eHCA Infiniband device driver for Linux on POWER
+ *
+ *  SQP functions
+ *
+ *  Authors: Khadija Souissi <souissi@de.ibm.com>
+ *           Heiko J Schick <schickhj@de.ibm.com>
+ *
+ *  Copyright (c) 2005 IBM Corporation
+ *
+ *  All rights reserved.
+ *
+ *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
+ *  BSD.
+ *
+ * OpenIB BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <rdma/ib_mad.h>
+
+#include "ehca_classes.h"
+#include "ehca_tools.h"
+#include "ehca_iverbs.h"
+#include "hcp_if.h"
+
+#define IB_MAD_STATUS_REDIRECT         cpu_to_be16(0x0002)
+#define IB_MAD_STATUS_UNSUP_VERSION    cpu_to_be16(0x0004)
+#define IB_MAD_STATUS_UNSUP_METHOD     cpu_to_be16(0x0008)
+
+#define IB_PMA_CLASS_PORT_INFO         cpu_to_be16(0x0001)
+
+/**
+ * ehca_define_sqp - Defines special queue pair 1 (GSI QP). When special queue
+ * pair is created successfully, the corresponding port gets active.
+ *
+ * Define Special Queue pair 0 (SMI QP) is still not supported.
+ *
+ * @qp_init_attr: Queue pair init attributes with port and queue pair type
+ */
+
+u64 ehca_define_sqp(struct ehca_shca *shca,
+                   struct ehca_qp *ehca_qp,
+                   struct ib_qp_init_attr *qp_init_attr)
+{
+       u32 pma_qp_nr, bma_qp_nr;
+       u64 ret;
+       u8 port = qp_init_attr->port_num;
+       int counter;
+
+       shca->sport[port - 1].port_state = IB_PORT_DOWN;
+
+       switch (qp_init_attr->qp_type) {
+       case IB_QPT_SMI:
+               /* function not supported yet */
+               break;
+       case IB_QPT_GSI:
+               ret = hipz_h_define_aqp1(shca->ipz_hca_handle,
+                                        ehca_qp->ipz_qp_handle,
+                                        ehca_qp->galpas.kernel,
+                                        (u32) qp_init_attr->port_num,
+                                        &pma_qp_nr, &bma_qp_nr);
+
+               if (ret != H_SUCCESS) {
+                       ehca_err(&shca->ib_device,
+                                "Can't define AQP1 for port %x. h_ret=%lli",
+                                port, ret);
+                       return ret;
+               }
+               shca->sport[port - 1].pma_qp_nr = pma_qp_nr;
+               ehca_dbg(&shca->ib_device, "port=%x pma_qp_nr=%x",
+                        port, pma_qp_nr);
+               break;
+       default:
+               ehca_err(&shca->ib_device, "invalid qp_type=%x",
+                        qp_init_attr->qp_type);
+               return H_PARAMETER;
+       }
+
+       if (ehca_nr_ports < 0) /* autodetect mode */
+               return H_SUCCESS;
+
+       for (counter = 0;
+            shca->sport[port - 1].port_state != IB_PORT_ACTIVE &&
+                    counter < ehca_port_act_time;
+            counter++) {
+               ehca_dbg(&shca->ib_device, "... wait until port %x is active",
+                        port);
+               msleep_interruptible(1000);
+       }
+
+       if (counter == ehca_port_act_time) {
+               ehca_err(&shca->ib_device, "Port %x is not active.", port);
+               return H_HARDWARE;
+       }
+
+       return H_SUCCESS;
+}
+
+struct ib_perf {
+       struct ib_mad_hdr mad_hdr;
+       u8 reserved[40];
+       u8 data[192];
+} __attribute__ ((packed));
+
+/* TC/SL/FL packed into 32 bits, as in ClassPortInfo */
+struct tcslfl {
+       u32 tc:8;
+       u32 sl:4;
+       u32 fl:20;
+} __attribute__ ((packed));
+
+/* IP Version/TC/FL packed into 32 bits, as in GRH */
+struct vertcfl {
+       u32 ver:4;
+       u32 tc:8;
+       u32 fl:20;
+} __attribute__ ((packed));
+
+static int ehca_process_perf(struct ib_device *ibdev, u8 port_num,
+                            const struct ib_wc *in_wc, const struct ib_grh *in_grh,
+                            const struct ib_mad *in_mad, struct ib_mad *out_mad)
+{
+       const struct ib_perf *in_perf = (const struct ib_perf *)in_mad;
+       struct ib_perf *out_perf = (struct ib_perf *)out_mad;
+       struct ib_class_port_info *poi =
+               (struct ib_class_port_info *)out_perf->data;
+       struct tcslfl *tcslfl =
+               (struct tcslfl *)&poi->redirect_tcslfl;
+       struct ehca_shca *shca =
+               container_of(ibdev, struct ehca_shca, ib_device);
+       struct ehca_sport *sport = &shca->sport[port_num - 1];
+
+       ehca_dbg(ibdev, "method=%x", in_perf->mad_hdr.method);
+
+       *out_mad = *in_mad;
+
+       if (in_perf->mad_hdr.class_version != 1) {
+               ehca_warn(ibdev, "Unsupported class_version=%x",
+                         in_perf->mad_hdr.class_version);
+               out_perf->mad_hdr.status = IB_MAD_STATUS_UNSUP_VERSION;
+               goto perf_reply;
+       }
+
+       switch (in_perf->mad_hdr.method) {
+       case IB_MGMT_METHOD_GET:
+       case IB_MGMT_METHOD_SET:
+               /* set class port info for redirection */
+               out_perf->mad_hdr.attr_id = IB_PMA_CLASS_PORT_INFO;
+               out_perf->mad_hdr.status = IB_MAD_STATUS_REDIRECT;
+               memset(poi, 0, sizeof(*poi));
+               poi->base_version = 1;
+               poi->class_version = 1;
+               poi->resp_time_value = 18;
+
+               /* copy local routing information from WC where applicable */
+               tcslfl->sl         = in_wc->sl;
+               poi->redirect_lid  =
+                       sport->saved_attr.lid | in_wc->dlid_path_bits;
+               poi->redirect_qp   = sport->pma_qp_nr;
+               poi->redirect_qkey = IB_QP1_QKEY;
+
+               ehca_query_pkey(ibdev, port_num, in_wc->pkey_index,
+                               &poi->redirect_pkey);
+
+               /* if request was globally routed, copy route info */
+               if (in_grh) {
+                       const struct vertcfl *vertcfl =
+                               (const struct vertcfl *)&in_grh->version_tclass_flow;
+                       memcpy(poi->redirect_gid, in_grh->dgid.raw,
+                              sizeof(poi->redirect_gid));
+                       tcslfl->tc        = vertcfl->tc;
+                       tcslfl->fl        = vertcfl->fl;
+               } else
+                       /* else only fill in default GID */
+                       ehca_query_gid(ibdev, port_num, 0,
+                                      (union ib_gid *)&poi->redirect_gid);
+
+               ehca_dbg(ibdev, "ehca_pma_lid=%x ehca_pma_qp=%x",
+                        sport->saved_attr.lid, sport->pma_qp_nr);
+               break;
+
+       case IB_MGMT_METHOD_GET_RESP:
+               return IB_MAD_RESULT_FAILURE;
+
+       default:
+               out_perf->mad_hdr.status = IB_MAD_STATUS_UNSUP_METHOD;
+               break;
+       }
+
+perf_reply:
+       out_perf->mad_hdr.method = IB_MGMT_METHOD_GET_RESP;
+
+       return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY;
+}
+
+int ehca_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
+                    const struct ib_wc *in_wc, const struct ib_grh *in_grh,
+                    const struct ib_mad_hdr *in, size_t in_mad_size,
+                    struct ib_mad_hdr *out, size_t *out_mad_size,
+                    u16 *out_mad_pkey_index)
+{
+       int ret;
+       const struct ib_mad *in_mad = (const struct ib_mad *)in;
+       struct ib_mad *out_mad = (struct ib_mad *)out;
+
+       if (WARN_ON_ONCE(in_mad_size != sizeof(*in_mad) ||
+                        *out_mad_size != sizeof(*out_mad)))
+               return IB_MAD_RESULT_FAILURE;
+
+       if (!port_num || port_num > ibdev->phys_port_cnt || !in_wc)
+               return IB_MAD_RESULT_FAILURE;
+
+       /* accept only pma request */
+       if (in_mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_PERF_MGMT)
+               return IB_MAD_RESULT_SUCCESS;
+
+       ehca_dbg(ibdev, "port_num=%x src_qp=%x", port_num, in_wc->src_qp);
+       ret = ehca_process_perf(ibdev, port_num, in_wc, in_grh,
+                               in_mad, out_mad);
+
+       return ret;
+}
diff --git a/drivers/staging/rdma/ehca/ehca_tools.h b/drivers/staging/rdma/ehca/ehca_tools.h
new file mode 100644 (file)
index 0000000..d280b12
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ *  IBM eServer eHCA Infiniband device driver for Linux on POWER
+ *
+ *  auxiliary functions
+ *
+ *  Authors: Christoph Raisch <raisch@de.ibm.com>
+ *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
+ *           Khadija Souissi <souissik@de.ibm.com>
+ *           Waleri Fomin <fomin@de.ibm.com>
+ *           Heiko J Schick <schickhj@de.ibm.com>
+ *
+ *  Copyright (c) 2005 IBM Corporation
+ *
+ *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
+ *  BSD.
+ *
+ * OpenIB BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef EHCA_TOOLS_H
+#define EHCA_TOOLS_H
+
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/idr.h>
+#include <linux/kthread.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/vmalloc.h>
+#include <linux/notifier.h>
+#include <linux/cpu.h>
+#include <linux/device.h>
+
+#include <linux/atomic.h>
+#include <asm/ibmebus.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/hvcall.h>
+
+extern int ehca_debug_level;
+
+#define ehca_dbg(ib_dev, format, arg...) \
+       do { \
+               if (unlikely(ehca_debug_level)) \
+                       dev_printk(KERN_DEBUG, (ib_dev)->dma_device, \
+                                  "PU%04x EHCA_DBG:%s " format "\n", \
+                                  raw_smp_processor_id(), __func__, \
+                                  ## arg); \
+       } while (0)
+
+#define ehca_info(ib_dev, format, arg...) \
+       dev_info((ib_dev)->dma_device, "PU%04x EHCA_INFO:%s " format "\n", \
+                raw_smp_processor_id(), __func__, ## arg)
+
+#define ehca_warn(ib_dev, format, arg...) \
+       dev_warn((ib_dev)->dma_device, "PU%04x EHCA_WARN:%s " format "\n", \
+                raw_smp_processor_id(), __func__, ## arg)
+
+#define ehca_err(ib_dev, format, arg...) \
+       dev_err((ib_dev)->dma_device, "PU%04x EHCA_ERR:%s " format "\n", \
+               raw_smp_processor_id(), __func__, ## arg)
+
+/* use this one only if no ib_dev available */
+#define ehca_gen_dbg(format, arg...) \
+       do { \
+               if (unlikely(ehca_debug_level)) \
+                       printk(KERN_DEBUG "PU%04x EHCA_DBG:%s " format "\n", \
+                              raw_smp_processor_id(), __func__, ## arg); \
+       } while (0)
+
+#define ehca_gen_warn(format, arg...) \
+       printk(KERN_INFO "PU%04x EHCA_WARN:%s " format "\n", \
+              raw_smp_processor_id(), __func__, ## arg)
+
+#define ehca_gen_err(format, arg...) \
+       printk(KERN_ERR "PU%04x EHCA_ERR:%s " format "\n", \
+              raw_smp_processor_id(), __func__, ## arg)
+
+/**
+ * ehca_dmp - printk a memory block, whose length is n*8 bytes.
+ * Each line has the following layout:
+ * <format string> adr=X ofs=Y <8 bytes hex> <8 bytes hex>
+ */
+#define ehca_dmp(adr, len, format, args...) \
+       do { \
+               unsigned int x; \
+               unsigned int l = (unsigned int)(len); \
+               unsigned char *deb = (unsigned char *)(adr); \
+               for (x = 0; x < l; x += 16) { \
+                       printk(KERN_INFO "EHCA_DMP:%s " format \
+                              " adr=%p ofs=%04x %016llx %016llx\n", \
+                              __func__, ##args, deb, x, \
+                              *((u64 *)&deb[0]), *((u64 *)&deb[8])); \
+                       deb += 16; \
+               } \
+       } while (0)
+
+/* define a bitmask, little endian version */
+#define EHCA_BMASK(pos, length) (((pos) << 16) + (length))
+
+/* define a bitmask, the ibm way... */
+#define EHCA_BMASK_IBM(from, to) (((63 - to) << 16) + ((to) - (from) + 1))
+
+/* internal function, don't use */
+#define EHCA_BMASK_SHIFTPOS(mask) (((mask) >> 16) & 0xffff)
+
+/* internal function, don't use */
+#define EHCA_BMASK_MASK(mask) (~0ULL >> ((64 - (mask)) & 0xffff))
+
+/**
+ * EHCA_BMASK_SET - return value shifted and masked by mask
+ * variable|=EHCA_BMASK_SET(MY_MASK,0x4711) ORs the bits in variable
+ * variable&=~EHCA_BMASK_SET(MY_MASK,-1) clears the bits from the mask
+ * in variable
+ */
+#define EHCA_BMASK_SET(mask, value) \
+       ((EHCA_BMASK_MASK(mask) & ((u64)(value))) << EHCA_BMASK_SHIFTPOS(mask))
+
+/**
+ * EHCA_BMASK_GET - extract a parameter from value by mask
+ */
+#define EHCA_BMASK_GET(mask, value) \
+       (EHCA_BMASK_MASK(mask) & (((u64)(value)) >> EHCA_BMASK_SHIFTPOS(mask)))
+
+/* Converts ehca to ib return code */
+int ehca2ib_return_code(u64 ehca_rc);
+
+#endif /* EHCA_TOOLS_H */
diff --git a/drivers/staging/rdma/ehca/ehca_uverbs.c b/drivers/staging/rdma/ehca/ehca_uverbs.c
new file mode 100644 (file)
index 0000000..1a1d5d9
--- /dev/null
@@ -0,0 +1,309 @@
+/*
+ *  IBM eServer eHCA Infiniband device driver for Linux on POWER
+ *
+ *  userspace support verbs
+ *
+ *  Authors: Christoph Raisch <raisch@de.ibm.com>
+ *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
+ *           Heiko J Schick <schickhj@de.ibm.com>
+ *
+ *  Copyright (c) 2005 IBM Corporation
+ *
+ *  All rights reserved.
+ *
+ *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
+ *  BSD.
+ *
+ * OpenIB BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/slab.h>
+
+#include "ehca_classes.h"
+#include "ehca_iverbs.h"
+#include "ehca_mrmw.h"
+#include "ehca_tools.h"
+#include "hcp_if.h"
+
+struct ib_ucontext *ehca_alloc_ucontext(struct ib_device *device,
+                                       struct ib_udata *udata)
+{
+       struct ehca_ucontext *my_context;
+
+       my_context = kzalloc(sizeof *my_context, GFP_KERNEL);
+       if (!my_context) {
+               ehca_err(device, "Out of memory device=%p", device);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       return &my_context->ib_ucontext;
+}
+
+int ehca_dealloc_ucontext(struct ib_ucontext *context)
+{
+       kfree(container_of(context, struct ehca_ucontext, ib_ucontext));
+       return 0;
+}
+
+static void ehca_mm_open(struct vm_area_struct *vma)
+{
+       u32 *count = (u32 *)vma->vm_private_data;
+       if (!count) {
+               ehca_gen_err("Invalid vma struct vm_start=%lx vm_end=%lx",
+                            vma->vm_start, vma->vm_end);
+               return;
+       }
+       (*count)++;
+       if (!(*count))
+               ehca_gen_err("Use count overflow vm_start=%lx vm_end=%lx",
+                            vma->vm_start, vma->vm_end);
+       ehca_gen_dbg("vm_start=%lx vm_end=%lx count=%x",
+                    vma->vm_start, vma->vm_end, *count);
+}
+
+static void ehca_mm_close(struct vm_area_struct *vma)
+{
+       u32 *count = (u32 *)vma->vm_private_data;
+       if (!count) {
+               ehca_gen_err("Invalid vma struct vm_start=%lx vm_end=%lx",
+                            vma->vm_start, vma->vm_end);
+               return;
+       }
+       (*count)--;
+       ehca_gen_dbg("vm_start=%lx vm_end=%lx count=%x",
+                    vma->vm_start, vma->vm_end, *count);
+}
+
+static const struct vm_operations_struct vm_ops = {
+       .open = ehca_mm_open,
+       .close = ehca_mm_close,
+};
+
+static int ehca_mmap_fw(struct vm_area_struct *vma, struct h_galpas *galpas,
+                       u32 *mm_count)
+{
+       int ret;
+       u64 vsize, physical;
+
+       vsize = vma->vm_end - vma->vm_start;
+       if (vsize < EHCA_PAGESIZE) {
+               ehca_gen_err("invalid vsize=%lx", vma->vm_end - vma->vm_start);
+               return -EINVAL;
+       }
+
+       physical = galpas->user.fw_handle;
+       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+       ehca_gen_dbg("vsize=%llx physical=%llx", vsize, physical);
+       /* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */
+       ret = remap_4k_pfn(vma, vma->vm_start, physical >> EHCA_PAGESHIFT,
+                          vma->vm_page_prot);
+       if (unlikely(ret)) {
+               ehca_gen_err("remap_pfn_range() failed ret=%i", ret);
+               return -ENOMEM;
+       }
+
+       vma->vm_private_data = mm_count;
+       (*mm_count)++;
+       vma->vm_ops = &vm_ops;
+
+       return 0;
+}
+
+static int ehca_mmap_queue(struct vm_area_struct *vma, struct ipz_queue *queue,
+                          u32 *mm_count)
+{
+       int ret;
+       u64 start, ofs;
+       struct page *page;
+
+       vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
+       start = vma->vm_start;
+       for (ofs = 0; ofs < queue->queue_length; ofs += PAGE_SIZE) {
+               u64 virt_addr = (u64)ipz_qeit_calc(queue, ofs);
+               page = virt_to_page(virt_addr);
+               ret = vm_insert_page(vma, start, page);
+               if (unlikely(ret)) {
+                       ehca_gen_err("vm_insert_page() failed rc=%i", ret);
+                       return ret;
+               }
+               start += PAGE_SIZE;
+       }
+       vma->vm_private_data = mm_count;
+       (*mm_count)++;
+       vma->vm_ops = &vm_ops;
+
+       return 0;
+}
+
+static int ehca_mmap_cq(struct vm_area_struct *vma, struct ehca_cq *cq,
+                       u32 rsrc_type)
+{
+       int ret;
+
+       switch (rsrc_type) {
+       case 0: /* galpa fw handle */
+               ehca_dbg(cq->ib_cq.device, "cq_num=%x fw", cq->cq_number);
+               ret = ehca_mmap_fw(vma, &cq->galpas, &cq->mm_count_galpa);
+               if (unlikely(ret)) {
+                       ehca_err(cq->ib_cq.device,
+                                "ehca_mmap_fw() failed rc=%i cq_num=%x",
+                                ret, cq->cq_number);
+                       return ret;
+               }
+               break;
+
+       case 1: /* cq queue_addr */
+               ehca_dbg(cq->ib_cq.device, "cq_num=%x queue", cq->cq_number);
+               ret = ehca_mmap_queue(vma, &cq->ipz_queue, &cq->mm_count_queue);
+               if (unlikely(ret)) {
+                       ehca_err(cq->ib_cq.device,
+                                "ehca_mmap_queue() failed rc=%i cq_num=%x",
+                                ret, cq->cq_number);
+                       return ret;
+               }
+               break;
+
+       default:
+               ehca_err(cq->ib_cq.device, "bad resource type=%x cq_num=%x",
+                        rsrc_type, cq->cq_number);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int ehca_mmap_qp(struct vm_area_struct *vma, struct ehca_qp *qp,
+                       u32 rsrc_type)
+{
+       int ret;
+
+       switch (rsrc_type) {
+       case 0: /* galpa fw handle */
+               ehca_dbg(qp->ib_qp.device, "qp_num=%x fw", qp->ib_qp.qp_num);
+               ret = ehca_mmap_fw(vma, &qp->galpas, &qp->mm_count_galpa);
+               if (unlikely(ret)) {
+                       ehca_err(qp->ib_qp.device,
+                                "remap_pfn_range() failed ret=%i qp_num=%x",
+                                ret, qp->ib_qp.qp_num);
+                       return -ENOMEM;
+               }
+               break;
+
+       case 1: /* qp rqueue_addr */
+               ehca_dbg(qp->ib_qp.device, "qp_num=%x rq", qp->ib_qp.qp_num);
+               ret = ehca_mmap_queue(vma, &qp->ipz_rqueue,
+                                     &qp->mm_count_rqueue);
+               if (unlikely(ret)) {
+                       ehca_err(qp->ib_qp.device,
+                                "ehca_mmap_queue(rq) failed rc=%i qp_num=%x",
+                                ret, qp->ib_qp.qp_num);
+                       return ret;
+               }
+               break;
+
+       case 2: /* qp squeue_addr */
+               ehca_dbg(qp->ib_qp.device, "qp_num=%x sq", qp->ib_qp.qp_num);
+               ret = ehca_mmap_queue(vma, &qp->ipz_squeue,
+                                     &qp->mm_count_squeue);
+               if (unlikely(ret)) {
+                       ehca_err(qp->ib_qp.device,
+                                "ehca_mmap_queue(sq) failed rc=%i qp_num=%x",
+                                ret, qp->ib_qp.qp_num);
+                       return ret;
+               }
+               break;
+
+       default:
+               ehca_err(qp->ib_qp.device, "bad resource type=%x qp=num=%x",
+                        rsrc_type, qp->ib_qp.qp_num);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
+{
+       u64 fileoffset = vma->vm_pgoff;
+       u32 idr_handle = fileoffset & 0x1FFFFFF;
+       u32 q_type = (fileoffset >> 27) & 0x1;    /* CQ, QP,...        */
+       u32 rsrc_type = (fileoffset >> 25) & 0x3; /* sq,rq,cmnd_window */
+       u32 ret;
+       struct ehca_cq *cq;
+       struct ehca_qp *qp;
+       struct ib_uobject *uobject;
+
+       switch (q_type) {
+       case  0: /* CQ */
+               read_lock(&ehca_cq_idr_lock);
+               cq = idr_find(&ehca_cq_idr, idr_handle);
+               read_unlock(&ehca_cq_idr_lock);
+
+               /* make sure this mmap really belongs to the authorized user */
+               if (!cq)
+                       return -EINVAL;
+
+               if (!cq->ib_cq.uobject || cq->ib_cq.uobject->context != context)
+                       return -EINVAL;
+
+               ret = ehca_mmap_cq(vma, cq, rsrc_type);
+               if (unlikely(ret)) {
+                       ehca_err(cq->ib_cq.device,
+                                "ehca_mmap_cq() failed rc=%i cq_num=%x",
+                                ret, cq->cq_number);
+                       return ret;
+               }
+               break;
+
+       case 1: /* QP */
+               read_lock(&ehca_qp_idr_lock);
+               qp = idr_find(&ehca_qp_idr, idr_handle);
+               read_unlock(&ehca_qp_idr_lock);
+
+               /* make sure this mmap really belongs to the authorized user */
+               if (!qp)
+                       return -EINVAL;
+
+               uobject = IS_SRQ(qp) ? qp->ib_srq.uobject : qp->ib_qp.uobject;
+               if (!uobject || uobject->context != context)
+                       return -EINVAL;
+
+               ret = ehca_mmap_qp(vma, qp, rsrc_type);
+               if (unlikely(ret)) {
+                       ehca_err(qp->ib_qp.device,
+                                "ehca_mmap_qp() failed rc=%i qp_num=%x",
+                                ret, qp->ib_qp.qp_num);
+                       return ret;
+               }
+               break;
+
+       default:
+               ehca_gen_err("bad queue type %x", q_type);
+               return -EINVAL;
+       }
+
+       return 0;
+}
diff --git a/drivers/staging/rdma/ehca/hcp_if.c b/drivers/staging/rdma/ehca/hcp_if.c
new file mode 100644 (file)
index 0000000..89517ff
--- /dev/null
@@ -0,0 +1,949 @@
+/*
+ *  IBM eServer eHCA Infiniband device driver for Linux on POWER
+ *
+ *  Firmware Infiniband Interface code for POWER
+ *
+ *  Authors: Christoph Raisch <raisch@de.ibm.com>
+ *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
+ *           Joachim Fenkes <fenkes@de.ibm.com>
+ *           Gerd Bayer <gerd.bayer@de.ibm.com>
+ *           Waleri Fomin <fomin@de.ibm.com>
+ *
+ *  Copyright (c) 2005 IBM Corporation
+ *
+ *  All rights reserved.
+ *
+ *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
+ *  BSD.
+ *
+ * OpenIB BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <asm/hvcall.h>
+#include "ehca_tools.h"
+#include "hcp_if.h"
+#include "hcp_phyp.h"
+#include "hipz_fns.h"
+#include "ipz_pt_fn.h"
+
+#define H_ALL_RES_QP_ENHANCED_OPS       EHCA_BMASK_IBM(9, 11)
+#define H_ALL_RES_QP_PTE_PIN            EHCA_BMASK_IBM(12, 12)
+#define H_ALL_RES_QP_SERVICE_TYPE       EHCA_BMASK_IBM(13, 15)
+#define H_ALL_RES_QP_STORAGE            EHCA_BMASK_IBM(16, 17)
+#define H_ALL_RES_QP_LL_RQ_CQE_POSTING  EHCA_BMASK_IBM(18, 18)
+#define H_ALL_RES_QP_LL_SQ_CQE_POSTING  EHCA_BMASK_IBM(19, 21)
+#define H_ALL_RES_QP_SIGNALING_TYPE     EHCA_BMASK_IBM(22, 23)
+#define H_ALL_RES_QP_UD_AV_LKEY_CTRL    EHCA_BMASK_IBM(31, 31)
+#define H_ALL_RES_QP_SMALL_SQ_PAGE_SIZE EHCA_BMASK_IBM(32, 35)
+#define H_ALL_RES_QP_SMALL_RQ_PAGE_SIZE EHCA_BMASK_IBM(36, 39)
+#define H_ALL_RES_QP_RESOURCE_TYPE      EHCA_BMASK_IBM(56, 63)
+
+#define H_ALL_RES_QP_MAX_OUTST_SEND_WR  EHCA_BMASK_IBM(0, 15)
+#define H_ALL_RES_QP_MAX_OUTST_RECV_WR  EHCA_BMASK_IBM(16, 31)
+#define H_ALL_RES_QP_MAX_SEND_SGE       EHCA_BMASK_IBM(32, 39)
+#define H_ALL_RES_QP_MAX_RECV_SGE       EHCA_BMASK_IBM(40, 47)
+
+#define H_ALL_RES_QP_UD_AV_LKEY         EHCA_BMASK_IBM(32, 63)
+#define H_ALL_RES_QP_SRQ_QP_TOKEN       EHCA_BMASK_IBM(0, 31)
+#define H_ALL_RES_QP_SRQ_QP_HANDLE      EHCA_BMASK_IBM(0, 64)
+#define H_ALL_RES_QP_SRQ_LIMIT          EHCA_BMASK_IBM(48, 63)
+#define H_ALL_RES_QP_SRQ_QPN            EHCA_BMASK_IBM(40, 63)
+
+#define H_ALL_RES_QP_ACT_OUTST_SEND_WR  EHCA_BMASK_IBM(16, 31)
+#define H_ALL_RES_QP_ACT_OUTST_RECV_WR  EHCA_BMASK_IBM(48, 63)
+#define H_ALL_RES_QP_ACT_SEND_SGE       EHCA_BMASK_IBM(8, 15)
+#define H_ALL_RES_QP_ACT_RECV_SGE       EHCA_BMASK_IBM(24, 31)
+
+#define H_ALL_RES_QP_SQUEUE_SIZE_PAGES  EHCA_BMASK_IBM(0, 31)
+#define H_ALL_RES_QP_RQUEUE_SIZE_PAGES  EHCA_BMASK_IBM(32, 63)
+
+#define H_MP_INIT_TYPE                  EHCA_BMASK_IBM(44, 47)
+#define H_MP_SHUTDOWN                   EHCA_BMASK_IBM(48, 48)
+#define H_MP_RESET_QKEY_CTR             EHCA_BMASK_IBM(49, 49)
+
+#define HCALL4_REGS_FORMAT "r4=%lx r5=%lx r6=%lx r7=%lx"
+#define HCALL7_REGS_FORMAT HCALL4_REGS_FORMAT " r8=%lx r9=%lx r10=%lx"
+#define HCALL9_REGS_FORMAT HCALL7_REGS_FORMAT " r11=%lx r12=%lx"
+
+static DEFINE_SPINLOCK(hcall_lock);
+
+static long ehca_plpar_hcall_norets(unsigned long opcode,
+                                   unsigned long arg1,
+                                   unsigned long arg2,
+                                   unsigned long arg3,
+                                   unsigned long arg4,
+                                   unsigned long arg5,
+                                   unsigned long arg6,
+                                   unsigned long arg7)
+{
+       long ret;
+       int i, sleep_msecs;
+       unsigned long flags = 0;
+
+       if (unlikely(ehca_debug_level >= 2))
+               ehca_gen_dbg("opcode=%lx " HCALL7_REGS_FORMAT,
+                            opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+
+       for (i = 0; i < 5; i++) {
+               /* serialize hCalls to work around firmware issue */
+               if (ehca_lock_hcalls)
+                       spin_lock_irqsave(&hcall_lock, flags);
+
+               ret = plpar_hcall_norets(opcode, arg1, arg2, arg3, arg4,
+                                        arg5, arg6, arg7);
+
+               if (ehca_lock_hcalls)
+                       spin_unlock_irqrestore(&hcall_lock, flags);
+
+               if (H_IS_LONG_BUSY(ret)) {
+                       sleep_msecs = get_longbusy_msecs(ret);
+                       msleep_interruptible(sleep_msecs);
+                       continue;
+               }
+
+               if (ret < H_SUCCESS)
+                       ehca_gen_err("opcode=%lx ret=%li " HCALL7_REGS_FORMAT,
+                                    opcode, ret, arg1, arg2, arg3,
+                                    arg4, arg5, arg6, arg7);
+               else
+                       if (unlikely(ehca_debug_level >= 2))
+                               ehca_gen_dbg("opcode=%lx ret=%li", opcode, ret);
+
+               return ret;
+       }
+
+       return H_BUSY;
+}
+
+static long ehca_plpar_hcall9(unsigned long opcode,
+                             unsigned long *outs, /* array of 9 outputs */
+                             unsigned long arg1,
+                             unsigned long arg2,
+                             unsigned long arg3,
+                             unsigned long arg4,
+                             unsigned long arg5,
+                             unsigned long arg6,
+                             unsigned long arg7,
+                             unsigned long arg8,
+                             unsigned long arg9)
+{
+       long ret;
+       int i, sleep_msecs;
+       unsigned long flags = 0;
+
+       if (unlikely(ehca_debug_level >= 2))
+               ehca_gen_dbg("INPUT -- opcode=%lx " HCALL9_REGS_FORMAT, opcode,
+                            arg1, arg2, arg3, arg4, arg5,
+                            arg6, arg7, arg8, arg9);
+
+       for (i = 0; i < 5; i++) {
+               /* serialize hCalls to work around firmware issue */
+               if (ehca_lock_hcalls)
+                       spin_lock_irqsave(&hcall_lock, flags);
+
+               ret = plpar_hcall9(opcode, outs,
+                                  arg1, arg2, arg3, arg4, arg5,
+                                  arg6, arg7, arg8, arg9);
+
+               if (ehca_lock_hcalls)
+                       spin_unlock_irqrestore(&hcall_lock, flags);
+
+               if (H_IS_LONG_BUSY(ret)) {
+                       sleep_msecs = get_longbusy_msecs(ret);
+                       msleep_interruptible(sleep_msecs);
+                       continue;
+               }
+
+               if (ret < H_SUCCESS) {
+                       ehca_gen_err("INPUT -- opcode=%lx " HCALL9_REGS_FORMAT,
+                                    opcode, arg1, arg2, arg3, arg4, arg5,
+                                    arg6, arg7, arg8, arg9);
+                       ehca_gen_err("OUTPUT -- ret=%li " HCALL9_REGS_FORMAT,
+                                    ret, outs[0], outs[1], outs[2], outs[3],
+                                    outs[4], outs[5], outs[6], outs[7],
+                                    outs[8]);
+               } else if (unlikely(ehca_debug_level >= 2))
+                       ehca_gen_dbg("OUTPUT -- ret=%li " HCALL9_REGS_FORMAT,
+                                    ret, outs[0], outs[1], outs[2], outs[3],
+                                    outs[4], outs[5], outs[6], outs[7],
+                                    outs[8]);
+               return ret;
+       }
+
+       return H_BUSY;
+}
+
+u64 hipz_h_alloc_resource_eq(const struct ipz_adapter_handle adapter_handle,
+                            struct ehca_pfeq *pfeq,
+                            const u32 neq_control,
+                            const u32 number_of_entries,
+                            struct ipz_eq_handle *eq_handle,
+                            u32 *act_nr_of_entries,
+                            u32 *act_pages,
+                            u32 *eq_ist)
+{
+       u64 ret;
+       unsigned long outs[PLPAR_HCALL9_BUFSIZE];
+       u64 allocate_controls;
+
+       /* resource type */
+       allocate_controls = 3ULL;
+
+       /* ISN is associated */
+       if (neq_control != 1)
+               allocate_controls = (1ULL << (63 - 7)) | allocate_controls;
+       else /* notification event queue */
+               allocate_controls = (1ULL << 63) | allocate_controls;
+
+       ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
+                               adapter_handle.handle,  /* r4 */
+                               allocate_controls,      /* r5 */
+                               number_of_entries,      /* r6 */
+                               0, 0, 0, 0, 0, 0);
+       eq_handle->handle = outs[0];
+       *act_nr_of_entries = (u32)outs[3];
+       *act_pages = (u32)outs[4];
+       *eq_ist = (u32)outs[5];
+
+       if (ret == H_NOT_ENOUGH_RESOURCES)
+               ehca_gen_err("Not enough resource - ret=%lli ", ret);
+
+       return ret;
+}
+
+u64 hipz_h_reset_event(const struct ipz_adapter_handle adapter_handle,
+                      struct ipz_eq_handle eq_handle,
+                      const u64 event_mask)
+{
+       return ehca_plpar_hcall_norets(H_RESET_EVENTS,
+                                      adapter_handle.handle, /* r4 */
+                                      eq_handle.handle,      /* r5 */
+                                      event_mask,            /* r6 */
+                                      0, 0, 0, 0);
+}
+
+u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle,
+                            struct ehca_cq *cq,
+                            struct ehca_alloc_cq_parms *param)
+{
+       int rc;
+       u64 ret;
+       unsigned long outs[PLPAR_HCALL9_BUFSIZE];
+
+       ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
+                               adapter_handle.handle,   /* r4  */
+                               2,                       /* r5  */
+                               param->eq_handle.handle, /* r6  */
+                               cq->token,               /* r7  */
+                               param->nr_cqe,           /* r8  */
+                               0, 0, 0, 0);
+       cq->ipz_cq_handle.handle = outs[0];
+       param->act_nr_of_entries = (u32)outs[3];
+       param->act_pages = (u32)outs[4];
+
+       if (ret == H_SUCCESS) {
+               rc = hcp_galpas_ctor(&cq->galpas, 0, outs[5], outs[6]);
+               if (rc) {
+                       ehca_gen_err("Could not establish HW access. rc=%d paddr=%#lx",
+                                    rc, outs[5]);
+
+                       ehca_plpar_hcall_norets(H_FREE_RESOURCE,
+                                               adapter_handle.handle,     /* r4 */
+                                               cq->ipz_cq_handle.handle,  /* r5 */
+                                               0, 0, 0, 0, 0);
+                       ret = H_NO_MEM;
+               }
+       }
+
+       if (ret == H_NOT_ENOUGH_RESOURCES)
+               ehca_gen_err("Not enough resources. ret=%lli", ret);
+
+       return ret;
+}
+
+u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle,
+                            struct ehca_alloc_qp_parms *parms, int is_user)
+{
+       int rc;
+       u64 ret;
+       u64 allocate_controls, max_r10_reg, r11, r12;
+       unsigned long outs[PLPAR_HCALL9_BUFSIZE];
+
+       allocate_controls =
+               EHCA_BMASK_SET(H_ALL_RES_QP_ENHANCED_OPS, parms->ext_type)
+               | EHCA_BMASK_SET(H_ALL_RES_QP_PTE_PIN, 0)
+               | EHCA_BMASK_SET(H_ALL_RES_QP_SERVICE_TYPE, parms->servicetype)
+               | EHCA_BMASK_SET(H_ALL_RES_QP_SIGNALING_TYPE, parms->sigtype)
+               | EHCA_BMASK_SET(H_ALL_RES_QP_STORAGE, parms->qp_storage)
+               | EHCA_BMASK_SET(H_ALL_RES_QP_SMALL_SQ_PAGE_SIZE,
+                                parms->squeue.page_size)
+               | EHCA_BMASK_SET(H_ALL_RES_QP_SMALL_RQ_PAGE_SIZE,
+                                parms->rqueue.page_size)
+               | EHCA_BMASK_SET(H_ALL_RES_QP_LL_RQ_CQE_POSTING,
+                                !!(parms->ll_comp_flags & LLQP_RECV_COMP))
+               | EHCA_BMASK_SET(H_ALL_RES_QP_LL_SQ_CQE_POSTING,
+                                !!(parms->ll_comp_flags & LLQP_SEND_COMP))
+               | EHCA_BMASK_SET(H_ALL_RES_QP_UD_AV_LKEY_CTRL,
+                                parms->ud_av_l_key_ctl)
+               | EHCA_BMASK_SET(H_ALL_RES_QP_RESOURCE_TYPE, 1);
+
+       max_r10_reg =
+               EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_SEND_WR,
+                              parms->squeue.max_wr + 1)
+               | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_RECV_WR,
+                                parms->rqueue.max_wr + 1)
+               | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_SEND_SGE,
+                                parms->squeue.max_sge)
+               | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_RECV_SGE,
+                                parms->rqueue.max_sge);
+
+       r11 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_QP_TOKEN, parms->srq_token);
+
+       if (parms->ext_type == EQPT_SRQ)
+               r12 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_LIMIT, parms->srq_limit);
+       else
+               r12 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_QPN, parms->srq_qpn);
+
+       ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
+                               adapter_handle.handle,             /* r4  */
+                               allocate_controls,                 /* r5  */
+                               parms->send_cq_handle.handle,
+                               parms->recv_cq_handle.handle,
+                               parms->eq_handle.handle,
+                               ((u64)parms->token << 32) | parms->pd.value,
+                               max_r10_reg, r11, r12);
+
+       parms->qp_handle.handle = outs[0];
+       parms->real_qp_num = (u32)outs[1];
+       parms->squeue.act_nr_wqes =
+               (u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_SEND_WR, outs[2]);
+       parms->rqueue.act_nr_wqes =
+               (u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_RECV_WR, outs[2]);
+       parms->squeue.act_nr_sges =
+               (u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_SEND_SGE, outs[3]);
+       parms->rqueue.act_nr_sges =
+               (u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_RECV_SGE, outs[3]);
+       parms->squeue.queue_size =
+               (u32)EHCA_BMASK_GET(H_ALL_RES_QP_SQUEUE_SIZE_PAGES, outs[4]);
+       parms->rqueue.queue_size =
+               (u32)EHCA_BMASK_GET(H_ALL_RES_QP_RQUEUE_SIZE_PAGES, outs[4]);
+
+       if (ret == H_SUCCESS) {
+               rc = hcp_galpas_ctor(&parms->galpas, is_user, outs[6], outs[6]);
+               if (rc) {
+                       ehca_gen_err("Could not establish HW access. rc=%d paddr=%#lx",
+                                    rc, outs[6]);
+
+                       ehca_plpar_hcall_norets(H_FREE_RESOURCE,
+                                               adapter_handle.handle,     /* r4 */
+                                               parms->qp_handle.handle,  /* r5 */
+                                               0, 0, 0, 0, 0);
+                       ret = H_NO_MEM;
+               }
+       }
+
+       if (ret == H_NOT_ENOUGH_RESOURCES)
+               ehca_gen_err("Not enough resources. ret=%lli", ret);
+
+       return ret;
+}
+
+u64 hipz_h_query_port(const struct ipz_adapter_handle adapter_handle,
+                     const u8 port_id,
+                     struct hipz_query_port *query_port_response_block)
+{
+       u64 ret;
+       u64 r_cb = __pa(query_port_response_block);
+
+       if (r_cb & (EHCA_PAGESIZE-1)) {
+               ehca_gen_err("response block not page aligned");
+               return H_PARAMETER;
+       }
+
+       ret = ehca_plpar_hcall_norets(H_QUERY_PORT,
+                                     adapter_handle.handle, /* r4 */
+                                     port_id,               /* r5 */
+                                     r_cb,                  /* r6 */
+                                     0, 0, 0, 0);
+
+       if (ehca_debug_level >= 2)
+               ehca_dmp(query_port_response_block, 64, "response_block");
+
+       return ret;
+}
+
+u64 hipz_h_modify_port(const struct ipz_adapter_handle adapter_handle,
+                      const u8 port_id, const u32 port_cap,
+                      const u8 init_type, const int modify_mask)
+{
+       u64 port_attributes = port_cap;
+
+       if (modify_mask & IB_PORT_SHUTDOWN)
+               port_attributes |= EHCA_BMASK_SET(H_MP_SHUTDOWN, 1);
+       if (modify_mask & IB_PORT_INIT_TYPE)
+               port_attributes |= EHCA_BMASK_SET(H_MP_INIT_TYPE, init_type);
+       if (modify_mask & IB_PORT_RESET_QKEY_CNTR)
+               port_attributes |= EHCA_BMASK_SET(H_MP_RESET_QKEY_CTR, 1);
+
+       return ehca_plpar_hcall_norets(H_MODIFY_PORT,
+                                      adapter_handle.handle, /* r4 */
+                                      port_id,               /* r5 */
+                                      port_attributes,       /* r6 */
+                                      0, 0, 0, 0);
+}
+
+u64 hipz_h_query_hca(const struct ipz_adapter_handle adapter_handle,
+                    struct hipz_query_hca *query_hca_rblock)
+{
+       u64 r_cb = __pa(query_hca_rblock);
+
+       if (r_cb & (EHCA_PAGESIZE-1)) {
+               ehca_gen_err("response_block=%p not page aligned",
+                            query_hca_rblock);
+               return H_PARAMETER;
+       }
+
+       return ehca_plpar_hcall_norets(H_QUERY_HCA,
+                                      adapter_handle.handle, /* r4 */
+                                      r_cb,                  /* r5 */
+                                      0, 0, 0, 0, 0);
+}
+
+u64 hipz_h_register_rpage(const struct ipz_adapter_handle adapter_handle,
+                         const u8 pagesize,
+                         const u8 queue_type,
+                         const u64 resource_handle,
+                         const u64 logical_address_of_page,
+                         u64 count)
+{
+       return ehca_plpar_hcall_norets(H_REGISTER_RPAGES,
+                                      adapter_handle.handle,      /* r4  */
+                                      (u64)queue_type | ((u64)pagesize) << 8,
+                                      /* r5  */
+                                      resource_handle,            /* r6  */
+                                      logical_address_of_page,    /* r7  */
+                                      count,                      /* r8  */
+                                      0, 0);
+}
+
+u64 hipz_h_register_rpage_eq(const struct ipz_adapter_handle adapter_handle,
+                            const struct ipz_eq_handle eq_handle,
+                            struct ehca_pfeq *pfeq,
+                            const u8 pagesize,
+                            const u8 queue_type,
+                            const u64 logical_address_of_page,
+                            const u64 count)
+{
+       if (count != 1) {
+               ehca_gen_err("Ppage counter=%llx", count);
+               return H_PARAMETER;
+       }
+       return hipz_h_register_rpage(adapter_handle,
+                                    pagesize,
+                                    queue_type,
+                                    eq_handle.handle,
+                                    logical_address_of_page, count);
+}
+
+u64 hipz_h_query_int_state(const struct ipz_adapter_handle adapter_handle,
+                          u32 ist)
+{
+       u64 ret;
+       ret = ehca_plpar_hcall_norets(H_QUERY_INT_STATE,
+                                     adapter_handle.handle, /* r4 */
+                                     ist,                   /* r5 */
+                                     0, 0, 0, 0, 0);
+
+       if (ret != H_SUCCESS && ret != H_BUSY)
+               ehca_gen_err("Could not query interrupt state.");
+
+       return ret;
+}
+
+u64 hipz_h_register_rpage_cq(const struct ipz_adapter_handle adapter_handle,
+                            const struct ipz_cq_handle cq_handle,
+                            struct ehca_pfcq *pfcq,
+                            const u8 pagesize,
+                            const u8 queue_type,
+                            const u64 logical_address_of_page,
+                            const u64 count,
+                            const struct h_galpa gal)
+{
+       if (count != 1) {
+               ehca_gen_err("Page counter=%llx", count);
+               return H_PARAMETER;
+       }
+
+       return hipz_h_register_rpage(adapter_handle, pagesize, queue_type,
+                                    cq_handle.handle, logical_address_of_page,
+                                    count);
+}
+
+u64 hipz_h_register_rpage_qp(const struct ipz_adapter_handle adapter_handle,
+                            const struct ipz_qp_handle qp_handle,
+                            struct ehca_pfqp *pfqp,
+                            const u8 pagesize,
+                            const u8 queue_type,
+                            const u64 logical_address_of_page,
+                            const u64 count,
+                            const struct h_galpa galpa)
+{
+       if (count > 1) {
+               ehca_gen_err("Page counter=%llx", count);
+               return H_PARAMETER;
+       }
+
+       return hipz_h_register_rpage(adapter_handle, pagesize, queue_type,
+                                    qp_handle.handle, logical_address_of_page,
+                                    count);
+}
+
+u64 hipz_h_disable_and_get_wqe(const struct ipz_adapter_handle adapter_handle,
+                              const struct ipz_qp_handle qp_handle,
+                              struct ehca_pfqp *pfqp,
+                              void **log_addr_next_sq_wqe2processed,
+                              void **log_addr_next_rq_wqe2processed,
+                              int dis_and_get_function_code)
+{
+       u64 ret;
+       unsigned long outs[PLPAR_HCALL9_BUFSIZE];
+
+       ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs,
+                               adapter_handle.handle,     /* r4 */
+                               dis_and_get_function_code, /* r5 */
+                               qp_handle.handle,          /* r6 */
+                               0, 0, 0, 0, 0, 0);
+       if (log_addr_next_sq_wqe2processed)
+               *log_addr_next_sq_wqe2processed = (void *)outs[0];
+       if (log_addr_next_rq_wqe2processed)
+               *log_addr_next_rq_wqe2processed = (void *)outs[1];
+
+       return ret;
+}
+
+u64 hipz_h_modify_qp(const struct ipz_adapter_handle adapter_handle,
+                    const struct ipz_qp_handle qp_handle,
+                    struct ehca_pfqp *pfqp,
+                    const u64 update_mask,
+                    struct hcp_modify_qp_control_block *mqpcb,
+                    struct h_galpa gal)
+{
+       u64 ret;
+       unsigned long outs[PLPAR_HCALL9_BUFSIZE];
+       ret = ehca_plpar_hcall9(H_MODIFY_QP, outs,
+                               adapter_handle.handle, /* r4 */
+                               qp_handle.handle,      /* r5 */
+                               update_mask,           /* r6 */
+                               __pa(mqpcb),           /* r7 */
+                               0, 0, 0, 0, 0);
+
+       if (ret == H_NOT_ENOUGH_RESOURCES)
+               ehca_gen_err("Insufficient resources ret=%lli", ret);
+
+       return ret;
+}
+
+u64 hipz_h_query_qp(const struct ipz_adapter_handle adapter_handle,
+                   const struct ipz_qp_handle qp_handle,
+                   struct ehca_pfqp *pfqp,
+                   struct hcp_modify_qp_control_block *qqpcb,
+                   struct h_galpa gal)
+{
+       return ehca_plpar_hcall_norets(H_QUERY_QP,
+                                      adapter_handle.handle, /* r4 */
+                                      qp_handle.handle,      /* r5 */
+                                      __pa(qqpcb),           /* r6 */
+                                      0, 0, 0, 0);
+}
+
+u64 hipz_h_destroy_qp(const struct ipz_adapter_handle adapter_handle,
+                     struct ehca_qp *qp)
+{
+       u64 ret;
+       unsigned long outs[PLPAR_HCALL9_BUFSIZE];
+
+       ret = hcp_galpas_dtor(&qp->galpas);
+       if (ret) {
+               ehca_gen_err("Could not destruct qp->galpas");
+               return H_RESOURCE;
+       }
+       ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs,
+                               adapter_handle.handle,     /* r4 */
+                               /* function code */
+                               1,                         /* r5 */
+                               qp->ipz_qp_handle.handle,  /* r6 */
+                               0, 0, 0, 0, 0, 0);
+       if (ret == H_HARDWARE)
+               ehca_gen_err("HCA not operational. ret=%lli", ret);
+
+       ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
+                                     adapter_handle.handle,     /* r4 */
+                                     qp->ipz_qp_handle.handle,  /* r5 */
+                                     0, 0, 0, 0, 0);
+
+       if (ret == H_RESOURCE)
+               ehca_gen_err("Resource still in use. ret=%lli", ret);
+
+       return ret;
+}
+
+u64 hipz_h_define_aqp0(const struct ipz_adapter_handle adapter_handle,
+                      const struct ipz_qp_handle qp_handle,
+                      struct h_galpa gal,
+                      u32 port)
+{
+       return ehca_plpar_hcall_norets(H_DEFINE_AQP0,
+                                      adapter_handle.handle, /* r4 */
+                                      qp_handle.handle,      /* r5 */
+                                      port,                  /* r6 */
+                                      0, 0, 0, 0);
+}
+
+u64 hipz_h_define_aqp1(const struct ipz_adapter_handle adapter_handle,
+                      const struct ipz_qp_handle qp_handle,
+                      struct h_galpa gal,
+                      u32 port, u32 * pma_qp_nr,
+                      u32 * bma_qp_nr)
+{
+       u64 ret;
+       unsigned long outs[PLPAR_HCALL9_BUFSIZE];
+
+       ret = ehca_plpar_hcall9(H_DEFINE_AQP1, outs,
+                               adapter_handle.handle, /* r4 */
+                               qp_handle.handle,      /* r5 */
+                               port,                  /* r6 */
+                               0, 0, 0, 0, 0, 0);
+       *pma_qp_nr = (u32)outs[0];
+       *bma_qp_nr = (u32)outs[1];
+
+       if (ret == H_ALIAS_EXIST)
+               ehca_gen_err("AQP1 already exists. ret=%lli", ret);
+
+       return ret;
+}
+
+u64 hipz_h_attach_mcqp(const struct ipz_adapter_handle adapter_handle,
+                      const struct ipz_qp_handle qp_handle,
+                      struct h_galpa gal,
+                      u16 mcg_dlid,
+                      u64 subnet_prefix, u64 interface_id)
+{
+       u64 ret;
+
+       ret = ehca_plpar_hcall_norets(H_ATTACH_MCQP,
+                                     adapter_handle.handle,  /* r4 */
+                                     qp_handle.handle,       /* r5 */
+                                     mcg_dlid,               /* r6 */
+                                     interface_id,           /* r7 */
+                                     subnet_prefix,          /* r8 */
+                                     0, 0);
+
+       if (ret == H_NOT_ENOUGH_RESOURCES)
+               ehca_gen_err("Not enough resources. ret=%lli", ret);
+
+       return ret;
+}
+
+u64 hipz_h_detach_mcqp(const struct ipz_adapter_handle adapter_handle,
+                      const struct ipz_qp_handle qp_handle,
+                      struct h_galpa gal,
+                      u16 mcg_dlid,
+                      u64 subnet_prefix, u64 interface_id)
+{
+       return ehca_plpar_hcall_norets(H_DETACH_MCQP,
+                                      adapter_handle.handle, /* r4 */
+                                      qp_handle.handle,      /* r5 */
+                                      mcg_dlid,              /* r6 */
+                                      interface_id,          /* r7 */
+                                      subnet_prefix,         /* r8 */
+                                      0, 0);
+}
+
+u64 hipz_h_destroy_cq(const struct ipz_adapter_handle adapter_handle,
+                     struct ehca_cq *cq,
+                     u8 force_flag)
+{
+       u64 ret;
+
+       ret = hcp_galpas_dtor(&cq->galpas);
+       if (ret) {
+               ehca_gen_err("Could not destruct cp->galpas");
+               return H_RESOURCE;
+       }
+
+       ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
+                                     adapter_handle.handle,     /* r4 */
+                                     cq->ipz_cq_handle.handle,  /* r5 */
+                                     force_flag != 0 ? 1L : 0L, /* r6 */
+                                     0, 0, 0, 0);
+
+       if (ret == H_RESOURCE)
+               ehca_gen_err("H_FREE_RESOURCE failed ret=%lli ", ret);
+
+       return ret;
+}
+
+u64 hipz_h_destroy_eq(const struct ipz_adapter_handle adapter_handle,
+                     struct ehca_eq *eq)
+{
+       u64 ret;
+
+       ret = hcp_galpas_dtor(&eq->galpas);
+       if (ret) {
+               ehca_gen_err("Could not destruct eq->galpas");
+               return H_RESOURCE;
+       }
+
+       ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE,
+                                     adapter_handle.handle,     /* r4 */
+                                     eq->ipz_eq_handle.handle,  /* r5 */
+                                     0, 0, 0, 0, 0);
+
+       if (ret == H_RESOURCE)
+               ehca_gen_err("Resource in use. ret=%lli ", ret);
+
+       return ret;
+}
+
+u64 hipz_h_alloc_resource_mr(const struct ipz_adapter_handle adapter_handle,
+                            const struct ehca_mr *mr,
+                            const u64 vaddr,
+                            const u64 length,
+                            const u32 access_ctrl,
+                            const struct ipz_pd pd,
+                            struct ehca_mr_hipzout_parms *outparms)
+{
+       u64 ret;
+       unsigned long outs[PLPAR_HCALL9_BUFSIZE];
+
+       ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
+                               adapter_handle.handle,            /* r4 */
+                               5,                                /* r5 */
+                               vaddr,                            /* r6 */
+                               length,                           /* r7 */
+                               (((u64)access_ctrl) << 32ULL),    /* r8 */
+                               pd.value,                         /* r9 */
+                               0, 0, 0);
+       outparms->handle.handle = outs[0];
+       outparms->lkey = (u32)outs[2];
+       outparms->rkey = (u32)outs[3];
+
+       return ret;
+}
+
+u64 hipz_h_register_rpage_mr(const struct ipz_adapter_handle adapter_handle,
+                            const struct ehca_mr *mr,
+                            const u8 pagesize,
+                            const u8 queue_type,
+                            const u64 logical_address_of_page,
+                            const u64 count)
+{
+       u64 ret;
+
+       if (unlikely(ehca_debug_level >= 3)) {
+               if (count > 1) {
+                       u64 *kpage;
+                       int i;
+                       kpage = __va(logical_address_of_page);
+                       for (i = 0; i < count; i++)
+                               ehca_gen_dbg("kpage[%d]=%p",
+                                            i, (void *)kpage[i]);
+               } else
+                       ehca_gen_dbg("kpage=%p",
+                                    (void *)logical_address_of_page);
+       }
+
+       if ((count > 1) && (logical_address_of_page & (EHCA_PAGESIZE-1))) {
+               ehca_gen_err("logical_address_of_page not on a 4k boundary "
+                            "adapter_handle=%llx mr=%p mr_handle=%llx "
+                            "pagesize=%x queue_type=%x "
+                            "logical_address_of_page=%llx count=%llx",
+                            adapter_handle.handle, mr,
+                            mr->ipz_mr_handle.handle, pagesize, queue_type,
+                            logical_address_of_page, count);
+               ret = H_PARAMETER;
+       } else
+               ret = hipz_h_register_rpage(adapter_handle, pagesize,
+                                           queue_type,
+                                           mr->ipz_mr_handle.handle,
+                                           logical_address_of_page, count);
+       return ret;
+}
+
+u64 hipz_h_query_mr(const struct ipz_adapter_handle adapter_handle,
+                   const struct ehca_mr *mr,
+                   struct ehca_mr_hipzout_parms *outparms)
+{
+       u64 ret;
+       unsigned long outs[PLPAR_HCALL9_BUFSIZE];
+
+       ret = ehca_plpar_hcall9(H_QUERY_MR, outs,
+                               adapter_handle.handle,     /* r4 */
+                               mr->ipz_mr_handle.handle,  /* r5 */
+                               0, 0, 0, 0, 0, 0, 0);
+       outparms->len = outs[0];
+       outparms->vaddr = outs[1];
+       outparms->acl  = outs[4] >> 32;
+       outparms->lkey = (u32)(outs[5] >> 32);
+       outparms->rkey = (u32)(outs[5] & (0xffffffff));
+
+       return ret;
+}
+
+u64 hipz_h_free_resource_mr(const struct ipz_adapter_handle adapter_handle,
+                           const struct ehca_mr *mr)
+{
+       return ehca_plpar_hcall_norets(H_FREE_RESOURCE,
+                                      adapter_handle.handle,    /* r4 */
+                                      mr->ipz_mr_handle.handle, /* r5 */
+                                      0, 0, 0, 0, 0);
+}
+
+u64 hipz_h_reregister_pmr(const struct ipz_adapter_handle adapter_handle,
+                         const struct ehca_mr *mr,
+                         const u64 vaddr_in,
+                         const u64 length,
+                         const u32 access_ctrl,
+                         const struct ipz_pd pd,
+                         const u64 mr_addr_cb,
+                         struct ehca_mr_hipzout_parms *outparms)
+{
+       u64 ret;
+       unsigned long outs[PLPAR_HCALL9_BUFSIZE];
+
+       ret = ehca_plpar_hcall9(H_REREGISTER_PMR, outs,
+                               adapter_handle.handle,    /* r4 */
+                               mr->ipz_mr_handle.handle, /* r5 */
+                               vaddr_in,                 /* r6 */
+                               length,                   /* r7 */
+                               /* r8 */
+                               ((((u64)access_ctrl) << 32ULL) | pd.value),
+                               mr_addr_cb,               /* r9 */
+                               0, 0, 0);
+       outparms->vaddr = outs[1];
+       outparms->lkey = (u32)outs[2];
+       outparms->rkey = (u32)outs[3];
+
+       return ret;
+}
+
+u64 hipz_h_register_smr(const struct ipz_adapter_handle adapter_handle,
+                       const struct ehca_mr *mr,
+                       const struct ehca_mr *orig_mr,
+                       const u64 vaddr_in,
+                       const u32 access_ctrl,
+                       const struct ipz_pd pd,
+                       struct ehca_mr_hipzout_parms *outparms)
+{
+       u64 ret;
+       unsigned long outs[PLPAR_HCALL9_BUFSIZE];
+
+       ret = ehca_plpar_hcall9(H_REGISTER_SMR, outs,
+                               adapter_handle.handle,            /* r4 */
+                               orig_mr->ipz_mr_handle.handle,    /* r5 */
+                               vaddr_in,                         /* r6 */
+                               (((u64)access_ctrl) << 32ULL),    /* r7 */
+                               pd.value,                         /* r8 */
+                               0, 0, 0, 0);
+       outparms->handle.handle = outs[0];
+       outparms->lkey = (u32)outs[2];
+       outparms->rkey = (u32)outs[3];
+
+       return ret;
+}
+
+u64 hipz_h_alloc_resource_mw(const struct ipz_adapter_handle adapter_handle,
+                            const struct ehca_mw *mw,
+                            const struct ipz_pd pd,
+                            struct ehca_mw_hipzout_parms *outparms)
+{
+       u64 ret;
+       unsigned long outs[PLPAR_HCALL9_BUFSIZE];
+
+       ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
+                               adapter_handle.handle,      /* r4 */
+                               6,                          /* r5 */
+                               pd.value,                   /* r6 */
+                               0, 0, 0, 0, 0, 0);
+       outparms->handle.handle = outs[0];
+       outparms->rkey = (u32)outs[3];
+
+       return ret;
+}
+
+u64 hipz_h_query_mw(const struct ipz_adapter_handle adapter_handle,
+                   const struct ehca_mw *mw,
+                   struct ehca_mw_hipzout_parms *outparms)
+{
+       u64 ret;
+       unsigned long outs[PLPAR_HCALL9_BUFSIZE];
+
+       ret = ehca_plpar_hcall9(H_QUERY_MW, outs,
+                               adapter_handle.handle,    /* r4 */
+                               mw->ipz_mw_handle.handle, /* r5 */
+                               0, 0, 0, 0, 0, 0, 0);
+       outparms->rkey = (u32)outs[3];
+
+       return ret;
+}
+
+u64 hipz_h_free_resource_mw(const struct ipz_adapter_handle adapter_handle,
+                           const struct ehca_mw *mw)
+{
+       return ehca_plpar_hcall_norets(H_FREE_RESOURCE,
+                                      adapter_handle.handle,    /* r4 */
+                                      mw->ipz_mw_handle.handle, /* r5 */
+                                      0, 0, 0, 0, 0);
+}
+
+u64 hipz_h_error_data(const struct ipz_adapter_handle adapter_handle,
+                     const u64 ressource_handle,
+                     void *rblock,
+                     unsigned long *byte_count)
+{
+       u64 r_cb = __pa(rblock);
+
+       if (r_cb & (EHCA_PAGESIZE-1)) {
+               ehca_gen_err("rblock not page aligned.");
+               return H_PARAMETER;
+       }
+
+       return ehca_plpar_hcall_norets(H_ERROR_DATA,
+                                      adapter_handle.handle,
+                                      ressource_handle,
+                                      r_cb,
+                                      0, 0, 0, 0);
+}
+
+u64 hipz_h_eoi(int irq)
+{
+       unsigned long xirr;
+
+       iosync();
+       xirr = (0xffULL << 24) | irq;
+
+       return plpar_hcall_norets(H_EOI, xirr);
+}
diff --git a/drivers/staging/rdma/ehca/hcp_if.h b/drivers/staging/rdma/ehca/hcp_if.h
new file mode 100644 (file)
index 0000000..a46e514
--- /dev/null
@@ -0,0 +1,265 @@
+/*
+ *  IBM eServer eHCA Infiniband device driver for Linux on POWER
+ *
+ *  Firmware Infiniband Interface code for POWER
+ *
+ *  Authors: Christoph Raisch <raisch@de.ibm.com>
+ *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
+ *           Gerd Bayer <gerd.bayer@de.ibm.com>
+ *           Waleri Fomin <fomin@de.ibm.com>
+ *
+ *  Copyright (c) 2005 IBM Corporation
+ *
+ *  All rights reserved.
+ *
+ *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
+ *  BSD.
+ *
+ * OpenIB BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HCP_IF_H__
+#define __HCP_IF_H__
+
+#include "ehca_classes.h"
+#include "ehca_tools.h"
+#include "hipz_hw.h"
+
+/*
+ * hipz_h_alloc_resource_eq allocates EQ resources in HW and FW, initialize
+ * resources, create the empty EQPT (ring).
+ */
+u64 hipz_h_alloc_resource_eq(const struct ipz_adapter_handle adapter_handle,
+                            struct ehca_pfeq *pfeq,
+                            const u32 neq_control,
+                            const u32 number_of_entries,
+                            struct ipz_eq_handle *eq_handle,
+                            u32 * act_nr_of_entries,
+                            u32 * act_pages,
+                            u32 * eq_ist);
+
+u64 hipz_h_reset_event(const struct ipz_adapter_handle adapter_handle,
+                      struct ipz_eq_handle eq_handle,
+                      const u64 event_mask);
+/*
+ * hipz_h_allocate_resource_cq allocates CQ resources in HW and FW, initialize
+ * resources, create the empty CQPT (ring).
+ */
+u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle,
+                            struct ehca_cq *cq,
+                            struct ehca_alloc_cq_parms *param);
+
+
+/*
+ * hipz_h_alloc_resource_qp allocates QP resources in HW and FW,
+ * initialize resources, create empty QPPTs (2 rings).
+ */
+u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle,
+                            struct ehca_alloc_qp_parms *parms, int is_user);
+
+u64 hipz_h_query_port(const struct ipz_adapter_handle adapter_handle,
+                     const u8 port_id,
+                     struct hipz_query_port *query_port_response_block);
+
+u64 hipz_h_modify_port(const struct ipz_adapter_handle adapter_handle,
+                      const u8 port_id, const u32 port_cap,
+                      const u8 init_type, const int modify_mask);
+
+u64 hipz_h_query_hca(const struct ipz_adapter_handle adapter_handle,
+                    struct hipz_query_hca *query_hca_rblock);
+
+/*
+ * hipz_h_register_rpage internal function in hcp_if.h for all
+ * hcp_H_REGISTER_RPAGE calls.
+ */
+u64 hipz_h_register_rpage(const struct ipz_adapter_handle adapter_handle,
+                         const u8 pagesize,
+                         const u8 queue_type,
+                         const u64 resource_handle,
+                         const u64 logical_address_of_page,
+                         u64 count);
+
+u64 hipz_h_register_rpage_eq(const struct ipz_adapter_handle adapter_handle,
+                            const struct ipz_eq_handle eq_handle,
+                            struct ehca_pfeq *pfeq,
+                            const u8 pagesize,
+                            const u8 queue_type,
+                            const u64 logical_address_of_page,
+                            const u64 count);
+
+u64 hipz_h_query_int_state(const struct ipz_adapter_handle
+                          hcp_adapter_handle,
+                          u32 ist);
+
+u64 hipz_h_register_rpage_cq(const struct ipz_adapter_handle adapter_handle,
+                            const struct ipz_cq_handle cq_handle,
+                            struct ehca_pfcq *pfcq,
+                            const u8 pagesize,
+                            const u8 queue_type,
+                            const u64 logical_address_of_page,
+                            const u64 count,
+                            const struct h_galpa gal);
+
+u64 hipz_h_register_rpage_qp(const struct ipz_adapter_handle adapter_handle,
+                            const struct ipz_qp_handle qp_handle,
+                            struct ehca_pfqp *pfqp,
+                            const u8 pagesize,
+                            const u8 queue_type,
+                            const u64 logical_address_of_page,
+                            const u64 count,
+                            const struct h_galpa galpa);
+
+u64 hipz_h_disable_and_get_wqe(const struct ipz_adapter_handle adapter_handle,
+                              const struct ipz_qp_handle qp_handle,
+                              struct ehca_pfqp *pfqp,
+                              void **log_addr_next_sq_wqe_tb_processed,
+                              void **log_addr_next_rq_wqe_tb_processed,
+                              int dis_and_get_function_code);
+enum hcall_sigt {
+       HCALL_SIGT_NO_CQE = 0,
+       HCALL_SIGT_BY_WQE = 1,
+       HCALL_SIGT_EVERY = 2
+};
+
+u64 hipz_h_modify_qp(const struct ipz_adapter_handle adapter_handle,
+                    const struct ipz_qp_handle qp_handle,
+                    struct ehca_pfqp *pfqp,
+                    const u64 update_mask,
+                    struct hcp_modify_qp_control_block *mqpcb,
+                    struct h_galpa gal);
+
+u64 hipz_h_query_qp(const struct ipz_adapter_handle adapter_handle,
+                   const struct ipz_qp_handle qp_handle,
+                   struct ehca_pfqp *pfqp,
+                   struct hcp_modify_qp_control_block *qqpcb,
+                   struct h_galpa gal);
+
+u64 hipz_h_destroy_qp(const struct ipz_adapter_handle adapter_handle,
+                     struct ehca_qp *qp);
+
+u64 hipz_h_define_aqp0(const struct ipz_adapter_handle adapter_handle,
+                      const struct ipz_qp_handle qp_handle,
+                      struct h_galpa gal,
+                      u32 port);
+
+u64 hipz_h_define_aqp1(const struct ipz_adapter_handle adapter_handle,
+                      const struct ipz_qp_handle qp_handle,
+                      struct h_galpa gal,
+                      u32 port, u32 * pma_qp_nr,
+                      u32 * bma_qp_nr);
+
+u64 hipz_h_attach_mcqp(const struct ipz_adapter_handle adapter_handle,
+                      const struct ipz_qp_handle qp_handle,
+                      struct h_galpa gal,
+                      u16 mcg_dlid,
+                      u64 subnet_prefix, u64 interface_id);
+
+u64 hipz_h_detach_mcqp(const struct ipz_adapter_handle adapter_handle,
+                      const struct ipz_qp_handle qp_handle,
+                      struct h_galpa gal,
+                      u16 mcg_dlid,
+                      u64 subnet_prefix, u64 interface_id);
+
+u64 hipz_h_destroy_cq(const struct ipz_adapter_handle adapter_handle,
+                     struct ehca_cq *cq,
+                     u8 force_flag);
+
+u64 hipz_h_destroy_eq(const struct ipz_adapter_handle adapter_handle,
+                     struct ehca_eq *eq);
+
+/*
+ * hipz_h_alloc_resource_mr allocates MR resources in HW and FW, initialize
+ * resources.
+ */
+u64 hipz_h_alloc_resource_mr(const struct ipz_adapter_handle adapter_handle,
+                            const struct ehca_mr *mr,
+                            const u64 vaddr,
+                            const u64 length,
+                            const u32 access_ctrl,
+                            const struct ipz_pd pd,
+                            struct ehca_mr_hipzout_parms *outparms);
+
+/* hipz_h_register_rpage_mr registers MR resource pages in HW and FW */
+u64 hipz_h_register_rpage_mr(const struct ipz_adapter_handle adapter_handle,
+                            const struct ehca_mr *mr,
+                            const u8 pagesize,
+                            const u8 queue_type,
+                            const u64 logical_address_of_page,
+                            const u64 count);
+
+/* hipz_h_query_mr queries MR in HW and FW */
+u64 hipz_h_query_mr(const struct ipz_adapter_handle adapter_handle,
+                   const struct ehca_mr *mr,
+                   struct ehca_mr_hipzout_parms *outparms);
+
+/* hipz_h_free_resource_mr frees MR resources in HW and FW */
+u64 hipz_h_free_resource_mr(const struct ipz_adapter_handle adapter_handle,
+                           const struct ehca_mr *mr);
+
+/* hipz_h_reregister_pmr reregisters MR in HW and FW */
+u64 hipz_h_reregister_pmr(const struct ipz_adapter_handle adapter_handle,
+                         const struct ehca_mr *mr,
+                         const u64 vaddr_in,
+                         const u64 length,
+                         const u32 access_ctrl,
+                         const struct ipz_pd pd,
+                         const u64 mr_addr_cb,
+                         struct ehca_mr_hipzout_parms *outparms);
+
+/* hipz_h_register_smr register shared MR in HW and FW */
+u64 hipz_h_register_smr(const struct ipz_adapter_handle adapter_handle,
+                       const struct ehca_mr *mr,
+                       const struct ehca_mr *orig_mr,
+                       const u64 vaddr_in,
+                       const u32 access_ctrl,
+                       const struct ipz_pd pd,
+                       struct ehca_mr_hipzout_parms *outparms);
+
+/*
+ * hipz_h_alloc_resource_mw allocates MW resources in HW and FW, initialize
+ * resources.
+ */
+u64 hipz_h_alloc_resource_mw(const struct ipz_adapter_handle adapter_handle,
+                            const struct ehca_mw *mw,
+                            const struct ipz_pd pd,
+                            struct ehca_mw_hipzout_parms *outparms);
+
+/* hipz_h_query_mw queries MW in HW and FW */
+u64 hipz_h_query_mw(const struct ipz_adapter_handle adapter_handle,
+                   const struct ehca_mw *mw,
+                   struct ehca_mw_hipzout_parms *outparms);
+
+/* hipz_h_free_resource_mw frees MW resources in HW and FW */
+u64 hipz_h_free_resource_mw(const struct ipz_adapter_handle adapter_handle,
+                           const struct ehca_mw *mw);
+
+u64 hipz_h_error_data(const struct ipz_adapter_handle adapter_handle,
+                     const u64 ressource_handle,
+                     void *rblock,
+                     unsigned long *byte_count);
+u64 hipz_h_eoi(int irq);
+
+#endif /* __HCP_IF_H__ */
diff --git a/drivers/staging/rdma/ehca/hcp_phyp.c b/drivers/staging/rdma/ehca/hcp_phyp.c
new file mode 100644 (file)
index 0000000..077376f
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ *  IBM eServer eHCA Infiniband device driver for Linux on POWER
+ *
+ *   load store abstraction for ehca register access with tracing
+ *
+ *  Authors: Christoph Raisch <raisch@de.ibm.com>
+ *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
+ *
+ *  Copyright (c) 2005 IBM Corporation
+ *
+ *  All rights reserved.
+ *
+ *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
+ *  BSD.
+ *
+ * OpenIB BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "ehca_classes.h"
+#include "hipz_hw.h"
+
+u64 hcall_map_page(u64 physaddr)
+{
+       return (u64)ioremap(physaddr, EHCA_PAGESIZE);
+}
+
+int hcall_unmap_page(u64 mapaddr)
+{
+       iounmap((volatile void __iomem *) mapaddr);
+       return 0;
+}
+
+int hcp_galpas_ctor(struct h_galpas *galpas, int is_user,
+                   u64 paddr_kernel, u64 paddr_user)
+{
+       if (!is_user) {
+               galpas->kernel.fw_handle = hcall_map_page(paddr_kernel);
+               if (!galpas->kernel.fw_handle)
+                       return -ENOMEM;
+       } else
+               galpas->kernel.fw_handle = 0;
+
+       galpas->user.fw_handle = paddr_user;
+
+       return 0;
+}
+
+int hcp_galpas_dtor(struct h_galpas *galpas)
+{
+       if (galpas->kernel.fw_handle) {
+               int ret = hcall_unmap_page(galpas->kernel.fw_handle);
+               if (ret)
+                       return ret;
+       }
+
+       galpas->user.fw_handle = galpas->kernel.fw_handle = 0;
+
+       return 0;
+}
diff --git a/drivers/staging/rdma/ehca/hcp_phyp.h b/drivers/staging/rdma/ehca/hcp_phyp.h
new file mode 100644 (file)
index 0000000..d1b0299
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ *  IBM eServer eHCA Infiniband device driver for Linux on POWER
+ *
+ *  Firmware calls
+ *
+ *  Authors: Christoph Raisch <raisch@de.ibm.com>
+ *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
+ *           Waleri Fomin <fomin@de.ibm.com>
+ *           Gerd Bayer <gerd.bayer@de.ibm.com>
+ *
+ *  Copyright (c) 2005 IBM Corporation
+ *
+ *  All rights reserved.
+ *
+ *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
+ *  BSD.
+ *
+ * OpenIB BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HCP_PHYP_H__
+#define __HCP_PHYP_H__
+
+
+/*
+ * eHCA page (mapped into memory)
+ * resource to access eHCA register pages in CPU address space
+*/
+struct h_galpa {
+       u64 fw_handle;
+       /* for pSeries this is a 64bit memory address where
+          I/O memory is mapped into CPU address space (kv) */
+};
+
+/*
+ * resource to access eHCA address space registers, all types
+ */
+struct h_galpas {
+       u32 pid;                /*PID of userspace galpa checking */
+       struct h_galpa user;    /* user space accessible resource,
+                                  set to 0 if unused */
+       struct h_galpa kernel;  /* kernel space accessible resource,
+                                  set to 0 if unused */
+};
+
+static inline u64 hipz_galpa_load(struct h_galpa galpa, u32 offset)
+{
+       u64 addr = galpa.fw_handle + offset;
+       return *(volatile u64 __force *)addr;
+}
+
+static inline void hipz_galpa_store(struct h_galpa galpa, u32 offset, u64 value)
+{
+       u64 addr = galpa.fw_handle + offset;
+       *(volatile u64 __force *)addr = value;
+}
+
+int hcp_galpas_ctor(struct h_galpas *galpas, int is_user,
+                   u64 paddr_kernel, u64 paddr_user);
+
+int hcp_galpas_dtor(struct h_galpas *galpas);
+
+u64 hcall_map_page(u64 physaddr);
+
+int hcall_unmap_page(u64 mapaddr);
+
+#endif
diff --git a/drivers/staging/rdma/ehca/hipz_fns.h b/drivers/staging/rdma/ehca/hipz_fns.h
new file mode 100644 (file)
index 0000000..9dac93d
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ *  IBM eServer eHCA Infiniband device driver for Linux on POWER
+ *
+ *  HW abstraction register functions
+ *
+ *  Authors: Christoph Raisch <raisch@de.ibm.com>
+ *           Reinhard Ernst <rernst@de.ibm.com>
+ *
+ *  Copyright (c) 2005 IBM Corporation
+ *
+ *  All rights reserved.
+ *
+ *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
+ *  BSD.
+ *
+ * OpenIB BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HIPZ_FNS_H__
+#define __HIPZ_FNS_H__
+
+#include "ehca_classes.h"
+#include "hipz_hw.h"
+
+#include "hipz_fns_core.h"
+
+#define hipz_galpa_store_eq(gal, offset, value) \
+       hipz_galpa_store(gal, EQTEMM_OFFSET(offset), value)
+
+#define hipz_galpa_load_eq(gal, offset) \
+       hipz_galpa_load(gal, EQTEMM_OFFSET(offset))
+
+#define hipz_galpa_store_qped(gal, offset, value) \
+       hipz_galpa_store(gal, QPEDMM_OFFSET(offset), value)
+
+#define hipz_galpa_load_qped(gal, offset) \
+       hipz_galpa_load(gal, QPEDMM_OFFSET(offset))
+
+#define hipz_galpa_store_mrmw(gal, offset, value) \
+       hipz_galpa_store(gal, MRMWMM_OFFSET(offset), value)
+
+#define hipz_galpa_load_mrmw(gal, offset) \
+       hipz_galpa_load(gal, MRMWMM_OFFSET(offset))
+
+#endif
diff --git a/drivers/staging/rdma/ehca/hipz_fns_core.h b/drivers/staging/rdma/ehca/hipz_fns_core.h
new file mode 100644 (file)
index 0000000..868735f
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ *  IBM eServer eHCA Infiniband device driver for Linux on POWER
+ *
+ *  HW abstraction register functions
+ *
+ *  Authors: Christoph Raisch <raisch@de.ibm.com>
+ *           Heiko J Schick <schickhj@de.ibm.com>
+ *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
+ *           Reinhard Ernst <rernst@de.ibm.com>
+ *
+ *  Copyright (c) 2005 IBM Corporation
+ *
+ *  All rights reserved.
+ *
+ *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
+ *  BSD.
+ *
+ * OpenIB BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HIPZ_FNS_CORE_H__
+#define __HIPZ_FNS_CORE_H__
+
+#include "hcp_phyp.h"
+#include "hipz_hw.h"
+
+#define hipz_galpa_store_cq(gal, offset, value) \
+       hipz_galpa_store(gal, CQTEMM_OFFSET(offset), value)
+
+#define hipz_galpa_load_cq(gal, offset) \
+       hipz_galpa_load(gal, CQTEMM_OFFSET(offset))
+
+#define hipz_galpa_store_qp(gal, offset, value) \
+       hipz_galpa_store(gal, QPTEMM_OFFSET(offset), value)
+#define hipz_galpa_load_qp(gal, offset) \
+       hipz_galpa_load(gal, QPTEMM_OFFSET(offset))
+
+static inline void hipz_update_sqa(struct ehca_qp *qp, u16 nr_wqes)
+{
+       /*  ringing doorbell :-) */
+       hipz_galpa_store_qp(qp->galpas.kernel, qpx_sqa,
+                           EHCA_BMASK_SET(QPX_SQADDER, nr_wqes));
+}
+
+static inline void hipz_update_rqa(struct ehca_qp *qp, u16 nr_wqes)
+{
+       /*  ringing doorbell :-) */
+       hipz_galpa_store_qp(qp->galpas.kernel, qpx_rqa,
+                           EHCA_BMASK_SET(QPX_RQADDER, nr_wqes));
+}
+
+static inline void hipz_update_feca(struct ehca_cq *cq, u32 nr_cqes)
+{
+       hipz_galpa_store_cq(cq->galpas.kernel, cqx_feca,
+                           EHCA_BMASK_SET(CQX_FECADDER, nr_cqes));
+}
+
+static inline void hipz_set_cqx_n0(struct ehca_cq *cq, u32 value)
+{
+       u64 cqx_n0_reg;
+
+       hipz_galpa_store_cq(cq->galpas.kernel, cqx_n0,
+                           EHCA_BMASK_SET(CQX_N0_GENERATE_SOLICITED_COMP_EVENT,
+                                          value));
+       cqx_n0_reg = hipz_galpa_load_cq(cq->galpas.kernel, cqx_n0);
+}
+
+static inline void hipz_set_cqx_n1(struct ehca_cq *cq, u32 value)
+{
+       u64 cqx_n1_reg;
+
+       hipz_galpa_store_cq(cq->galpas.kernel, cqx_n1,
+                           EHCA_BMASK_SET(CQX_N1_GENERATE_COMP_EVENT, value));
+       cqx_n1_reg = hipz_galpa_load_cq(cq->galpas.kernel, cqx_n1);
+}
+
+#endif /* __HIPZ_FNC_CORE_H__ */
diff --git a/drivers/staging/rdma/ehca/hipz_hw.h b/drivers/staging/rdma/ehca/hipz_hw.h
new file mode 100644 (file)
index 0000000..bf996c7
--- /dev/null
@@ -0,0 +1,414 @@
+/*
+ *  IBM eServer eHCA Infiniband device driver for Linux on POWER
+ *
+ *  eHCA register definitions
+ *
+ *  Authors: Waleri Fomin <fomin@de.ibm.com>
+ *           Christoph Raisch <raisch@de.ibm.com>
+ *           Reinhard Ernst <rernst@de.ibm.com>
+ *
+ *  Copyright (c) 2005 IBM Corporation
+ *
+ *  All rights reserved.
+ *
+ *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
+ *  BSD.
+ *
+ * OpenIB BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HIPZ_HW_H__
+#define __HIPZ_HW_H__
+
+#include "ehca_tools.h"
+
+#define EHCA_MAX_MTU 4
+
+/* QP Table Entry Memory Map */
+struct hipz_qptemm {
+       u64 qpx_hcr;
+       u64 qpx_c;
+       u64 qpx_herr;
+       u64 qpx_aer;
+/* 0x20*/
+       u64 qpx_sqa;
+       u64 qpx_sqc;
+       u64 qpx_rqa;
+       u64 qpx_rqc;
+/* 0x40*/
+       u64 qpx_st;
+       u64 qpx_pmstate;
+       u64 qpx_pmfa;
+       u64 qpx_pkey;
+/* 0x60*/
+       u64 qpx_pkeya;
+       u64 qpx_pkeyb;
+       u64 qpx_pkeyc;
+       u64 qpx_pkeyd;
+/* 0x80*/
+       u64 qpx_qkey;
+       u64 qpx_dqp;
+       u64 qpx_dlidp;
+       u64 qpx_portp;
+/* 0xa0*/
+       u64 qpx_slidp;
+       u64 qpx_slidpp;
+       u64 qpx_dlida;
+       u64 qpx_porta;
+/* 0xc0*/
+       u64 qpx_slida;
+       u64 qpx_slidpa;
+       u64 qpx_slvl;
+       u64 qpx_ipd;
+/* 0xe0*/
+       u64 qpx_mtu;
+       u64 qpx_lato;
+       u64 qpx_rlimit;
+       u64 qpx_rnrlimit;
+/* 0x100*/
+       u64 qpx_t;
+       u64 qpx_sqhp;
+       u64 qpx_sqptp;
+       u64 qpx_nspsn;
+/* 0x120*/
+       u64 qpx_nspsnhwm;
+       u64 reserved1;
+       u64 qpx_sdsi;
+       u64 qpx_sdsbc;
+/* 0x140*/
+       u64 qpx_sqwsize;
+       u64 qpx_sqwts;
+       u64 qpx_lsn;
+       u64 qpx_nssn;
+/* 0x160 */
+       u64 qpx_mor;
+       u64 qpx_cor;
+       u64 qpx_sqsize;
+       u64 qpx_erc;
+/* 0x180*/
+       u64 qpx_rnrrc;
+       u64 qpx_ernrwt;
+       u64 qpx_rnrresp;
+       u64 qpx_lmsna;
+/* 0x1a0 */
+       u64 qpx_sqhpc;
+       u64 qpx_sqcptp;
+       u64 qpx_sigt;
+       u64 qpx_wqecnt;
+/* 0x1c0*/
+       u64 qpx_rqhp;
+       u64 qpx_rqptp;
+       u64 qpx_rqsize;
+       u64 qpx_nrr;
+/* 0x1e0*/
+       u64 qpx_rdmac;
+       u64 qpx_nrpsn;
+       u64 qpx_lapsn;
+       u64 qpx_lcr;
+/* 0x200*/
+       u64 qpx_rwc;
+       u64 qpx_rwva;
+       u64 qpx_rdsi;
+       u64 qpx_rdsbc;
+/* 0x220*/
+       u64 qpx_rqwsize;
+       u64 qpx_crmsn;
+       u64 qpx_rdd;
+       u64 qpx_larpsn;
+/* 0x240*/
+       u64 qpx_pd;
+       u64 qpx_scqn;
+       u64 qpx_rcqn;
+       u64 qpx_aeqn;
+/* 0x260*/
+       u64 qpx_aaelog;
+       u64 qpx_ram;
+       u64 qpx_rdmaqe0;
+       u64 qpx_rdmaqe1;
+/* 0x280*/
+       u64 qpx_rdmaqe2;
+       u64 qpx_rdmaqe3;
+       u64 qpx_nrpsnhwm;
+/* 0x298*/
+       u64 reserved[(0x400 - 0x298) / 8];
+/* 0x400 extended data */
+       u64 reserved_ext[(0x500 - 0x400) / 8];
+/* 0x500 */
+       u64 reserved2[(0x1000 - 0x500) / 8];
+/* 0x1000      */
+};
+
+#define QPX_SQADDER EHCA_BMASK_IBM(48, 63)
+#define QPX_RQADDER EHCA_BMASK_IBM(48, 63)
+#define QPX_AAELOG_RESET_SRQ_LIMIT EHCA_BMASK_IBM(3, 3)
+
+#define QPTEMM_OFFSET(x) offsetof(struct hipz_qptemm, x)
+
+/* MRMWPT Entry Memory Map */
+struct hipz_mrmwmm {
+       /* 0x00 */
+       u64 mrx_hcr;
+
+       u64 mrx_c;
+       u64 mrx_herr;
+       u64 mrx_aer;
+       /* 0x20 */
+       u64 mrx_pp;
+       u64 reserved1;
+       u64 reserved2;
+       u64 reserved3;
+       /* 0x40 */
+       u64 reserved4[(0x200 - 0x40) / 8];
+       /* 0x200 */
+       u64 mrx_ctl[64];
+
+};
+
+#define MRMWMM_OFFSET(x) offsetof(struct hipz_mrmwmm, x)
+
+struct hipz_qpedmm {
+       /* 0x00 */
+       u64 reserved0[(0x400) / 8];
+       /* 0x400 */
+       u64 qpedx_phh;
+       u64 qpedx_ppsgp;
+       /* 0x410 */
+       u64 qpedx_ppsgu;
+       u64 qpedx_ppdgp;
+       /* 0x420 */
+       u64 qpedx_ppdgu;
+       u64 qpedx_aph;
+       /* 0x430 */
+       u64 qpedx_apsgp;
+       u64 qpedx_apsgu;
+       /* 0x440 */
+       u64 qpedx_apdgp;
+       u64 qpedx_apdgu;
+       /* 0x450 */
+       u64 qpedx_apav;
+       u64 qpedx_apsav;
+       /* 0x460  */
+       u64 qpedx_hcr;
+       u64 reserved1[4];
+       /* 0x488 */
+       u64 qpedx_rrl0;
+       /* 0x490 */
+       u64 qpedx_rrrkey0;
+       u64 qpedx_rrva0;
+       /* 0x4a0 */
+       u64 reserved2;
+       u64 qpedx_rrl1;
+       /* 0x4b0 */
+       u64 qpedx_rrrkey1;
+       u64 qpedx_rrva1;
+       /* 0x4c0 */
+       u64 reserved3;
+       u64 qpedx_rrl2;
+       /* 0x4d0 */
+       u64 qpedx_rrrkey2;
+       u64 qpedx_rrva2;
+       /* 0x4e0 */
+       u64 reserved4;
+       u64 qpedx_rrl3;
+       /* 0x4f0 */
+       u64 qpedx_rrrkey3;
+       u64 qpedx_rrva3;
+};
+
+#define QPEDMM_OFFSET(x) offsetof(struct hipz_qpedmm, x)
+
+/* CQ Table Entry Memory Map */
+struct hipz_cqtemm {
+       u64 cqx_hcr;
+       u64 cqx_c;
+       u64 cqx_herr;
+       u64 cqx_aer;
+/* 0x20  */
+       u64 cqx_ptp;
+       u64 cqx_tp;
+       u64 cqx_fec;
+       u64 cqx_feca;
+/* 0x40  */
+       u64 cqx_ep;
+       u64 cqx_eq;
+/* 0x50  */
+       u64 reserved1;
+       u64 cqx_n0;
+/* 0x60  */
+       u64 cqx_n1;
+       u64 reserved2[(0x1000 - 0x60) / 8];
+/* 0x1000 */
+};
+
+#define CQX_FEC_CQE_CNT           EHCA_BMASK_IBM(32, 63)
+#define CQX_FECADDER              EHCA_BMASK_IBM(32, 63)
+#define CQX_N0_GENERATE_SOLICITED_COMP_EVENT EHCA_BMASK_IBM(0, 0)
+#define CQX_N1_GENERATE_COMP_EVENT EHCA_BMASK_IBM(0, 0)
+
+#define CQTEMM_OFFSET(x) offsetof(struct hipz_cqtemm, x)
+
+/* EQ Table Entry Memory Map */
+struct hipz_eqtemm {
+       u64 eqx_hcr;
+       u64 eqx_c;
+
+       u64 eqx_herr;
+       u64 eqx_aer;
+/* 0x20 */
+       u64 eqx_ptp;
+       u64 eqx_tp;
+       u64 eqx_ssba;
+       u64 eqx_psba;
+
+/* 0x40 */
+       u64 eqx_cec;
+       u64 eqx_meql;
+       u64 eqx_xisbi;
+       u64 eqx_xisc;
+/* 0x60 */
+       u64 eqx_it;
+
+};
+
+#define EQTEMM_OFFSET(x) offsetof(struct hipz_eqtemm, x)
+
+/* access control defines for MR/MW */
+#define HIPZ_ACCESSCTRL_L_WRITE  0x00800000
+#define HIPZ_ACCESSCTRL_R_WRITE  0x00400000
+#define HIPZ_ACCESSCTRL_R_READ   0x00200000
+#define HIPZ_ACCESSCTRL_R_ATOMIC 0x00100000
+#define HIPZ_ACCESSCTRL_MW_BIND  0x00080000
+
+/* query hca response block */
+struct hipz_query_hca {
+       u32 cur_reliable_dg;
+       u32 cur_qp;
+       u32 cur_cq;
+       u32 cur_eq;
+       u32 cur_mr;
+       u32 cur_mw;
+       u32 cur_ee_context;
+       u32 cur_mcast_grp;
+       u32 cur_qp_attached_mcast_grp;
+       u32 reserved1;
+       u32 cur_ipv6_qp;
+       u32 cur_eth_qp;
+       u32 cur_hp_mr;
+       u32 reserved2[3];
+       u32 max_rd_domain;
+       u32 max_qp;
+       u32 max_cq;
+       u32 max_eq;
+       u32 max_mr;
+       u32 max_hp_mr;
+       u32 max_mw;
+       u32 max_mrwpte;
+       u32 max_special_mrwpte;
+       u32 max_rd_ee_context;
+       u32 max_mcast_grp;
+       u32 max_total_mcast_qp_attach;
+       u32 max_mcast_qp_attach;
+       u32 max_raw_ipv6_qp;
+       u32 max_raw_ethy_qp;
+       u32 internal_clock_frequency;
+       u32 max_pd;
+       u32 max_ah;
+       u32 max_cqe;
+       u32 max_wqes_wq;
+       u32 max_partitions;
+       u32 max_rr_ee_context;
+       u32 max_rr_qp;
+       u32 max_rr_hca;
+       u32 max_act_wqs_ee_context;
+       u32 max_act_wqs_qp;
+       u32 max_sge;
+       u32 max_sge_rd;
+       u32 memory_page_size_supported;
+       u64 max_mr_size;
+       u32 local_ca_ack_delay;
+       u32 num_ports;
+       u32 vendor_id;
+       u32 vendor_part_id;
+       u32 hw_ver;
+       u64 node_guid;
+       u64 hca_cap_indicators;
+       u32 data_counter_register_size;
+       u32 max_shared_rq;
+       u32 max_isns_eq;
+       u32 max_neq;
+} __attribute__ ((packed));
+
+#define HCA_CAP_AH_PORT_NR_CHECK      EHCA_BMASK_IBM( 0,  0)
+#define HCA_CAP_ATOMIC                EHCA_BMASK_IBM( 1,  1)
+#define HCA_CAP_AUTO_PATH_MIG         EHCA_BMASK_IBM( 2,  2)
+#define HCA_CAP_BAD_P_KEY_CTR         EHCA_BMASK_IBM( 3,  3)
+#define HCA_CAP_SQD_RTS_PORT_CHANGE   EHCA_BMASK_IBM( 4,  4)
+#define HCA_CAP_CUR_QP_STATE_MOD      EHCA_BMASK_IBM( 5,  5)
+#define HCA_CAP_INIT_TYPE             EHCA_BMASK_IBM( 6,  6)
+#define HCA_CAP_PORT_ACTIVE_EVENT     EHCA_BMASK_IBM( 7,  7)
+#define HCA_CAP_Q_KEY_VIOL_CTR        EHCA_BMASK_IBM( 8,  8)
+#define HCA_CAP_WQE_RESIZE            EHCA_BMASK_IBM( 9,  9)
+#define HCA_CAP_RAW_PACKET_MCAST      EHCA_BMASK_IBM(10, 10)
+#define HCA_CAP_SHUTDOWN_PORT         EHCA_BMASK_IBM(11, 11)
+#define HCA_CAP_RC_LL_QP              EHCA_BMASK_IBM(12, 12)
+#define HCA_CAP_SRQ                   EHCA_BMASK_IBM(13, 13)
+#define HCA_CAP_UD_LL_QP              EHCA_BMASK_IBM(16, 16)
+#define HCA_CAP_RESIZE_MR             EHCA_BMASK_IBM(17, 17)
+#define HCA_CAP_MINI_QP               EHCA_BMASK_IBM(18, 18)
+#define HCA_CAP_H_ALLOC_RES_SYNC      EHCA_BMASK_IBM(19, 19)
+
+/* query port response block */
+struct hipz_query_port {
+       u32 state;
+       u32 bad_pkey_cntr;
+       u32 lmc;
+       u32 lid;
+       u32 subnet_timeout;
+       u32 qkey_viol_cntr;
+       u32 sm_sl;
+       u32 sm_lid;
+       u32 capability_mask;
+       u32 init_type_reply;
+       u32 pkey_tbl_len;
+       u32 gid_tbl_len;
+       u64 gid_prefix;
+       u32 port_nr;
+       u16 pkey_entries[16];
+       u8  reserved1[32];
+       u32 trent_size;
+       u32 trbuf_size;
+       u64 max_msg_sz;
+       u32 max_mtu;
+       u32 vl_cap;
+       u32 phys_pstate;
+       u32 phys_state;
+       u32 phys_speed;
+       u32 phys_width;
+       u8  reserved2[1884];
+       u64 guid_entries[255];
+} __attribute__ ((packed));
+
+#endif
diff --git a/drivers/staging/rdma/ehca/ipz_pt_fn.c b/drivers/staging/rdma/ehca/ipz_pt_fn.c
new file mode 100644 (file)
index 0000000..7ffc748
--- /dev/null
@@ -0,0 +1,289 @@
+/*
+ *  IBM eServer eHCA Infiniband device driver for Linux on POWER
+ *
+ *  internal queue handling
+ *
+ *  Authors: Waleri Fomin <fomin@de.ibm.com>
+ *           Reinhard Ernst <rernst@de.ibm.com>
+ *           Christoph Raisch <raisch@de.ibm.com>
+ *
+ *  Copyright (c) 2005 IBM Corporation
+ *
+ *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
+ *  BSD.
+ *
+ * OpenIB BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/slab.h>
+
+#include "ehca_tools.h"
+#include "ipz_pt_fn.h"
+#include "ehca_classes.h"
+
+#define PAGES_PER_KPAGE (PAGE_SIZE >> EHCA_PAGESHIFT)
+
+struct kmem_cache *small_qp_cache;
+
+void *ipz_qpageit_get_inc(struct ipz_queue *queue)
+{
+       void *ret = ipz_qeit_get(queue);
+       queue->current_q_offset += queue->pagesize;
+       if (queue->current_q_offset > queue->queue_length) {
+               queue->current_q_offset -= queue->pagesize;
+               ret = NULL;
+       }
+       if (((u64)ret) % queue->pagesize) {
+               ehca_gen_err("ERROR!! not at PAGE-Boundary");
+               return NULL;
+       }
+       return ret;
+}
+
+void *ipz_qeit_eq_get_inc(struct ipz_queue *queue)
+{
+       void *ret = ipz_qeit_get(queue);
+       u64 last_entry_in_q = queue->queue_length - queue->qe_size;
+
+       queue->current_q_offset += queue->qe_size;
+       if (queue->current_q_offset > last_entry_in_q) {
+               queue->current_q_offset = 0;
+               queue->toggle_state = (~queue->toggle_state) & 1;
+       }
+
+       return ret;
+}
+
+int ipz_queue_abs_to_offset(struct ipz_queue *queue, u64 addr, u64 *q_offset)
+{
+       int i;
+       for (i = 0; i < queue->queue_length / queue->pagesize; i++) {
+               u64 page = __pa(queue->queue_pages[i]);
+               if (addr >= page && addr < page + queue->pagesize) {
+                       *q_offset = addr - page + i * queue->pagesize;
+                       return 0;
+               }
+       }
+       return -EINVAL;
+}
+
+#if PAGE_SHIFT < EHCA_PAGESHIFT
+#error Kernel pages must be at least as large than eHCA pages (4K) !
+#endif
+
+/*
+ * allocate pages for queue:
+ * outer loop allocates whole kernel pages (page aligned) and
+ * inner loop divides a kernel page into smaller hca queue pages
+ */
+static int alloc_queue_pages(struct ipz_queue *queue, const u32 nr_of_pages)
+{
+       int k, f = 0;
+       u8 *kpage;
+
+       while (f < nr_of_pages) {
+               kpage = (u8 *)get_zeroed_page(GFP_KERNEL);
+               if (!kpage)
+                       goto out;
+
+               for (k = 0; k < PAGES_PER_KPAGE && f < nr_of_pages; k++) {
+                       queue->queue_pages[f] = (struct ipz_page *)kpage;
+                       kpage += EHCA_PAGESIZE;
+                       f++;
+               }
+       }
+       return 1;
+
+out:
+       for (f = 0; f < nr_of_pages && queue->queue_pages[f];
+            f += PAGES_PER_KPAGE)
+               free_page((unsigned long)(queue->queue_pages)[f]);
+       return 0;
+}
+
+static int alloc_small_queue_page(struct ipz_queue *queue, struct ehca_pd *pd)
+{
+       int order = ilog2(queue->pagesize) - 9;
+       struct ipz_small_queue_page *page;
+       unsigned long bit;
+
+       mutex_lock(&pd->lock);
+
+       if (!list_empty(&pd->free[order]))
+               page = list_entry(pd->free[order].next,
+                                 struct ipz_small_queue_page, list);
+       else {
+               page = kmem_cache_zalloc(small_qp_cache, GFP_KERNEL);
+               if (!page)
+                       goto out;
+
+               page->page = get_zeroed_page(GFP_KERNEL);
+               if (!page->page) {
+                       kmem_cache_free(small_qp_cache, page);
+                       goto out;
+               }
+
+               list_add(&page->list, &pd->free[order]);
+       }
+
+       bit = find_first_zero_bit(page->bitmap, IPZ_SPAGE_PER_KPAGE >> order);
+       __set_bit(bit, page->bitmap);
+       page->fill++;
+
+       if (page->fill == IPZ_SPAGE_PER_KPAGE >> order)
+               list_move(&page->list, &pd->full[order]);
+
+       mutex_unlock(&pd->lock);
+
+       queue->queue_pages[0] = (void *)(page->page | (bit << (order + 9)));
+       queue->small_page = page;
+       queue->offset = bit << (order + 9);
+       return 1;
+
+out:
+       ehca_err(pd->ib_pd.device, "failed to allocate small queue page");
+       mutex_unlock(&pd->lock);
+       return 0;
+}
+
+static void free_small_queue_page(struct ipz_queue *queue, struct ehca_pd *pd)
+{
+       int order = ilog2(queue->pagesize) - 9;
+       struct ipz_small_queue_page *page = queue->small_page;
+       unsigned long bit;
+       int free_page = 0;
+
+       bit = ((unsigned long)queue->queue_pages[0] & ~PAGE_MASK)
+               >> (order + 9);
+
+       mutex_lock(&pd->lock);
+
+       __clear_bit(bit, page->bitmap);
+       page->fill--;
+
+       if (page->fill == 0) {
+               list_del(&page->list);
+               free_page = 1;
+       }
+
+       if (page->fill == (IPZ_SPAGE_PER_KPAGE >> order) - 1)
+               /* the page was full until we freed the chunk */
+               list_move_tail(&page->list, &pd->free[order]);
+
+       mutex_unlock(&pd->lock);
+
+       if (free_page) {
+               free_page(page->page);
+               kmem_cache_free(small_qp_cache, page);
+       }
+}
+
+int ipz_queue_ctor(struct ehca_pd *pd, struct ipz_queue *queue,
+                  const u32 nr_of_pages, const u32 pagesize,
+                  const u32 qe_size, const u32 nr_of_sg,
+                  int is_small)
+{
+       if (pagesize > PAGE_SIZE) {
+               ehca_gen_err("FATAL ERROR: pagesize=%x "
+                            "is greater than kernel page size", pagesize);
+               return 0;
+       }
+
+       /* init queue fields */
+       queue->queue_length = nr_of_pages * pagesize;
+       queue->pagesize = pagesize;
+       queue->qe_size = qe_size;
+       queue->act_nr_of_sg = nr_of_sg;
+       queue->current_q_offset = 0;
+       queue->toggle_state = 1;
+       queue->small_page = NULL;
+
+       /* allocate queue page pointers */
+       queue->queue_pages = kzalloc(nr_of_pages * sizeof(void *),
+                                    GFP_KERNEL | __GFP_NOWARN);
+       if (!queue->queue_pages) {
+               queue->queue_pages = vzalloc(nr_of_pages * sizeof(void *));
+               if (!queue->queue_pages) {
+                       ehca_gen_err("Couldn't allocate queue page list");
+                       return 0;
+               }
+       }
+
+       /* allocate actual queue pages */
+       if (is_small) {
+               if (!alloc_small_queue_page(queue, pd))
+                       goto ipz_queue_ctor_exit0;
+       } else
+               if (!alloc_queue_pages(queue, nr_of_pages))
+                       goto ipz_queue_ctor_exit0;
+
+       return 1;
+
+ipz_queue_ctor_exit0:
+       ehca_gen_err("Couldn't alloc pages queue=%p "
+                "nr_of_pages=%x",  queue, nr_of_pages);
+       kvfree(queue->queue_pages);
+
+       return 0;
+}
+
+int ipz_queue_dtor(struct ehca_pd *pd, struct ipz_queue *queue)
+{
+       int i, nr_pages;
+
+       if (!queue || !queue->queue_pages) {
+               ehca_gen_dbg("queue or queue_pages is NULL");
+               return 0;
+       }
+
+       if (queue->small_page)
+               free_small_queue_page(queue, pd);
+       else {
+               nr_pages = queue->queue_length / queue->pagesize;
+               for (i = 0; i < nr_pages; i += PAGES_PER_KPAGE)
+                       free_page((unsigned long)queue->queue_pages[i]);
+       }
+
+       kvfree(queue->queue_pages);
+
+       return 1;
+}
+
+int ehca_init_small_qp_cache(void)
+{
+       small_qp_cache = kmem_cache_create("ehca_cache_small_qp",
+                                          sizeof(struct ipz_small_queue_page),
+                                          0, SLAB_HWCACHE_ALIGN, NULL);
+       if (!small_qp_cache)
+               return -ENOMEM;
+
+       return 0;
+}
+
+void ehca_cleanup_small_qp_cache(void)
+{
+       kmem_cache_destroy(small_qp_cache);
+}
diff --git a/drivers/staging/rdma/ehca/ipz_pt_fn.h b/drivers/staging/rdma/ehca/ipz_pt_fn.h
new file mode 100644 (file)
index 0000000..a801274
--- /dev/null
@@ -0,0 +1,289 @@
+/*
+ *  IBM eServer eHCA Infiniband device driver for Linux on POWER
+ *
+ *  internal queue handling
+ *
+ *  Authors: Waleri Fomin <fomin@de.ibm.com>
+ *           Reinhard Ernst <rernst@de.ibm.com>
+ *           Christoph Raisch <raisch@de.ibm.com>
+ *
+ *  Copyright (c) 2005 IBM Corporation
+ *
+ *  All rights reserved.
+ *
+ *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
+ *  BSD.
+ *
+ * OpenIB BSD License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __IPZ_PT_FN_H__
+#define __IPZ_PT_FN_H__
+
+#define EHCA_PAGESHIFT   12
+#define EHCA_PAGESIZE   4096UL
+#define EHCA_PAGEMASK   (~(EHCA_PAGESIZE-1))
+#define EHCA_PT_ENTRIES 512UL
+
+#include "ehca_tools.h"
+#include "ehca_qes.h"
+
+struct ehca_pd;
+struct ipz_small_queue_page;
+
+extern struct kmem_cache *small_qp_cache;
+
+/* struct generic ehca page */
+struct ipz_page {
+       u8 entries[EHCA_PAGESIZE];
+};
+
+#define IPZ_SPAGE_PER_KPAGE (PAGE_SIZE / 512)
+
+struct ipz_small_queue_page {
+       unsigned long page;
+       unsigned long bitmap[IPZ_SPAGE_PER_KPAGE / BITS_PER_LONG];
+       int fill;
+       void *mapped_addr;
+       u32 mmap_count;
+       struct list_head list;
+};
+
+/* struct generic queue in linux kernel virtual memory (kv) */
+struct ipz_queue {
+       u64 current_q_offset;   /* current queue entry */
+
+       struct ipz_page **queue_pages;  /* array of pages belonging to queue */
+       u32 qe_size;            /* queue entry size */
+       u32 act_nr_of_sg;
+       u32 queue_length;       /* queue length allocated in bytes */
+       u32 pagesize;
+       u32 toggle_state;       /* toggle flag - per page */
+       u32 offset; /* save offset within page for small_qp */
+       struct ipz_small_queue_page *small_page;
+};
+
+/*
+ * return current Queue Entry for a certain q_offset
+ * returns address (kv) of Queue Entry
+ */
+static inline void *ipz_qeit_calc(struct ipz_queue *queue, u64 q_offset)
+{
+       struct ipz_page *current_page;
+       if (q_offset >= queue->queue_length)
+               return NULL;
+       current_page = (queue->queue_pages)[q_offset >> EHCA_PAGESHIFT];
+       return &current_page->entries[q_offset & (EHCA_PAGESIZE - 1)];
+}
+
+/*
+ * return current Queue Entry
+ * returns address (kv) of Queue Entry
+ */
+static inline void *ipz_qeit_get(struct ipz_queue *queue)
+{
+       return ipz_qeit_calc(queue, queue->current_q_offset);
+}
+
+/*
+ * return current Queue Page , increment Queue Page iterator from
+ * page to page in struct ipz_queue, last increment will return 0! and
+ * NOT wrap
+ * returns address (kv) of Queue Page
+ * warning don't use in parallel with ipz_QE_get_inc()
+ */
+void *ipz_qpageit_get_inc(struct ipz_queue *queue);
+
+/*
+ * return current Queue Entry, increment Queue Entry iterator by one
+ * step in struct ipz_queue, will wrap in ringbuffer
+ * returns address (kv) of Queue Entry BEFORE increment
+ * warning don't use in parallel with ipz_qpageit_get_inc()
+ */
+static inline void *ipz_qeit_get_inc(struct ipz_queue *queue)
+{
+       void *ret = ipz_qeit_get(queue);
+       queue->current_q_offset += queue->qe_size;
+       if (queue->current_q_offset >= queue->queue_length) {
+               queue->current_q_offset = 0;
+               /* toggle the valid flag */
+               queue->toggle_state = (~queue->toggle_state) & 1;
+       }
+
+       return ret;
+}
+
+/*
+ * return a bool indicating whether current Queue Entry is valid
+ */
+static inline int ipz_qeit_is_valid(struct ipz_queue *queue)
+{
+       struct ehca_cqe *cqe = ipz_qeit_get(queue);
+       return ((cqe->cqe_flags >> 7) == (queue->toggle_state & 1));
+}
+
+/*
+ * return current Queue Entry, increment Queue Entry iterator by one
+ * step in struct ipz_queue, will wrap in ringbuffer
+ * returns address (kv) of Queue Entry BEFORE increment
+ * returns 0 and does not increment, if wrong valid state
+ * warning don't use in parallel with ipz_qpageit_get_inc()
+ */
+static inline void *ipz_qeit_get_inc_valid(struct ipz_queue *queue)
+{
+       return ipz_qeit_is_valid(queue) ? ipz_qeit_get_inc(queue) : NULL;
+}
+
+/*
+ * returns and resets Queue Entry iterator
+ * returns address (kv) of first Queue Entry
+ */
+static inline void *ipz_qeit_reset(struct ipz_queue *queue)
+{
+       queue->current_q_offset = 0;
+       return ipz_qeit_get(queue);
+}
+
+/*
+ * return the q_offset corresponding to an absolute address
+ */
+int ipz_queue_abs_to_offset(struct ipz_queue *queue, u64 addr, u64 *q_offset);
+
+/*
+ * return the next queue offset. don't modify the queue.
+ */
+static inline u64 ipz_queue_advance_offset(struct ipz_queue *queue, u64 offset)
+{
+       offset += queue->qe_size;
+       if (offset >= queue->queue_length) offset = 0;
+       return offset;
+}
+
+/* struct generic page table */
+struct ipz_pt {
+       u64 entries[EHCA_PT_ENTRIES];
+};
+
+/* struct page table for a queue, only to be used in pf */
+struct ipz_qpt {
+       /* queue page tables (kv), use u64 because we know the element length */
+       u64 *qpts;
+       u32 n_qpts;
+       u32 n_ptes;       /*  number of page table entries */
+       u64 *current_pte_addr;
+};
+
+/*
+ * constructor for a ipz_queue_t, placement new for ipz_queue_t,
+ * new for all dependent datastructors
+ * all QP Tables are the same
+ * flow:
+ *    allocate+pin queue
+ * see ipz_qpt_ctor()
+ * returns true if ok, false if out of memory
+ */
+int ipz_queue_ctor(struct ehca_pd *pd, struct ipz_queue *queue,
+                  const u32 nr_of_pages, const u32 pagesize,
+                  const u32 qe_size, const u32 nr_of_sg,
+                  int is_small);
+
+/*
+ * destructor for a ipz_queue_t
+ *  -# free queue
+ *  see ipz_queue_ctor()
+ *  returns true if ok, false if queue was NULL-ptr of free failed
+ */
+int ipz_queue_dtor(struct ehca_pd *pd, struct ipz_queue *queue);
+
+/*
+ * constructor for a ipz_qpt_t,
+ * placement new for struct ipz_queue, new for all dependent datastructors
+ * all QP Tables are the same,
+ * flow:
+ * -# allocate+pin queue
+ * -# initialise ptcb
+ * -# allocate+pin PTs
+ * -# link PTs to a ring, according to HCA Arch, set bit62 id needed
+ * -# the ring must have room for exactly nr_of_PTEs
+ * see ipz_qpt_ctor()
+ */
+void ipz_qpt_ctor(struct ipz_qpt *qpt,
+                 const u32 nr_of_qes,
+                 const u32 pagesize,
+                 const u32 qe_size,
+                 const u8 lowbyte, const u8 toggle,
+                 u32 * act_nr_of_QEs, u32 * act_nr_of_pages);
+
+/*
+ * return current Queue Entry, increment Queue Entry iterator by one
+ * step in struct ipz_queue, will wrap in ringbuffer
+ * returns address (kv) of Queue Entry BEFORE increment
+ * warning don't use in parallel with ipz_qpageit_get_inc()
+ * warning unpredictable results may occur if steps>act_nr_of_queue_entries
+ * fix EQ page problems
+ */
+void *ipz_qeit_eq_get_inc(struct ipz_queue *queue);
+
+/*
+ * return current Event Queue Entry, increment Queue Entry iterator
+ * by one step in struct ipz_queue if valid, will wrap in ringbuffer
+ * returns address (kv) of Queue Entry BEFORE increment
+ * returns 0 and does not increment, if wrong valid state
+ * warning don't use in parallel with ipz_queue_QPageit_get_inc()
+ * warning unpredictable results may occur if steps>act_nr_of_queue_entries
+ */
+static inline void *ipz_eqit_eq_get_inc_valid(struct ipz_queue *queue)
+{
+       void *ret = ipz_qeit_get(queue);
+       u32 qe = *(u8 *)ret;
+       if ((qe >> 7) != (queue->toggle_state & 1))
+               return NULL;
+       ipz_qeit_eq_get_inc(queue); /* this is a good one */
+       return ret;
+}
+
+static inline void *ipz_eqit_eq_peek_valid(struct ipz_queue *queue)
+{
+       void *ret = ipz_qeit_get(queue);
+       u32 qe = *(u8 *)ret;
+       if ((qe >> 7) != (queue->toggle_state & 1))
+               return NULL;
+       return ret;
+}
+
+/* returns address (GX) of first queue entry */
+static inline u64 ipz_qpt_get_firstpage(struct ipz_qpt *qpt)
+{
+       return be64_to_cpu(qpt->qpts[0]);
+}
+
+/* returns address (kv) of first page of queue page table */
+static inline void *ipz_qpt_get_qpt(struct ipz_qpt *qpt)
+{
+       return qpt->qpts;
+}
+
+#endif                         /* __IPZ_PT_FN_H__ */
index 654eafef1d30857ead08805911ba71797027028b..aa58e597df0698a4dc3e17d04662f565a5bafbbc 100644 (file)
@@ -2710,7 +2710,7 @@ int acquire_lcb_access(struct hfi1_devdata *dd, int sleep_ok)
        if (sleep_ok) {
                mutex_lock(&ppd->hls_lock);
        } else {
-               while (mutex_trylock(&ppd->hls_lock) == EBUSY)
+               while (!mutex_trylock(&ppd->hls_lock))
                        udelay(1);
        }
 
@@ -2758,7 +2758,7 @@ int release_lcb_access(struct hfi1_devdata *dd, int sleep_ok)
        if (sleep_ok) {
                mutex_lock(&dd->pport->hls_lock);
        } else {
-               while (mutex_trylock(&dd->pport->hls_lock) == EBUSY)
+               while (!mutex_trylock(&dd->pport->hls_lock))
                        udelay(1);
        }
 
index 07c87a87775fd524f497d4478e0ef12b757f8054..bc26a5392712d848ecd6df16676788790a8eb50b 100644 (file)
 #include "device.h"
 
 static struct class *class;
+static struct class *user_class;
 static dev_t hfi1_dev;
 
 int hfi1_cdev_init(int minor, const char *name,
                   const struct file_operations *fops,
-                  struct cdev *cdev, struct device **devp)
+                  struct cdev *cdev, struct device **devp,
+                  bool user_accessible)
 {
        const dev_t dev = MKDEV(MAJOR(hfi1_dev), minor);
        struct device *device = NULL;
@@ -78,7 +80,11 @@ int hfi1_cdev_init(int minor, const char *name,
                goto done;
        }
 
-       device = device_create(class, NULL, dev, NULL, "%s", name);
+       if (user_accessible)
+               device = device_create(user_class, NULL, dev, NULL, "%s", name);
+       else
+               device = device_create(class, NULL, dev, NULL, "%s", name);
+
        if (!IS_ERR(device))
                goto done;
        ret = PTR_ERR(device);
@@ -110,6 +116,26 @@ const char *class_name(void)
        return hfi1_class_name;
 }
 
+static char *hfi1_devnode(struct device *dev, umode_t *mode)
+{
+       if (mode)
+               *mode = 0600;
+       return kasprintf(GFP_KERNEL, "%s", dev_name(dev));
+}
+
+static const char *hfi1_class_name_user = "hfi1_user";
+const char *class_name_user(void)
+{
+       return hfi1_class_name_user;
+}
+
+static char *hfi1_user_devnode(struct device *dev, umode_t *mode)
+{
+       if (mode)
+               *mode = 0666;
+       return kasprintf(GFP_KERNEL, "%s", dev_name(dev));
+}
+
 int __init dev_init(void)
 {
        int ret;
@@ -125,7 +151,22 @@ int __init dev_init(void)
                ret = PTR_ERR(class);
                pr_err("Could not create device class (err %d)\n", -ret);
                unregister_chrdev_region(hfi1_dev, HFI1_NMINORS);
+               goto done;
        }
+       class->devnode = hfi1_devnode;
+
+       user_class = class_create(THIS_MODULE, class_name_user());
+       if (IS_ERR(user_class)) {
+               ret = PTR_ERR(user_class);
+               pr_err("Could not create device class for user accessible files (err %d)\n",
+                      -ret);
+               class_destroy(class);
+               class = NULL;
+               user_class = NULL;
+               unregister_chrdev_region(hfi1_dev, HFI1_NMINORS);
+               goto done;
+       }
+       user_class->devnode = hfi1_user_devnode;
 
 done:
        return ret;
@@ -133,10 +174,11 @@ done:
 
 void dev_cleanup(void)
 {
-       if (class) {
-               class_destroy(class);
-               class = NULL;
-       }
+       class_destroy(class);
+       class = NULL;
+
+       class_destroy(user_class);
+       user_class = NULL;
 
        unregister_chrdev_region(hfi1_dev, HFI1_NMINORS);
 }
index 98caecd3d807eabffc70e01f2c64470a5d14b980..2850ff739d81d354452da2af424f27aa9a0136a3 100644 (file)
@@ -52,7 +52,8 @@
 
 int hfi1_cdev_init(int minor, const char *name,
                   const struct file_operations *fops,
-                  struct cdev *cdev, struct device **devp);
+                  struct cdev *cdev, struct device **devp,
+                  bool user_accessible);
 void hfi1_cdev_cleanup(struct cdev *cdev, struct device **devp);
 const char *class_name(void);
 int __init dev_init(void);
index 6777d6b659cf4e065274061c48fd0551e2115c5e..3e8d5ac4c626901e52b66aa0f3ba27e1c603bc79 100644 (file)
@@ -292,7 +292,7 @@ int hfi1_diag_add(struct hfi1_devdata *dd)
        if (atomic_inc_return(&diagpkt_count) == 1) {
                ret = hfi1_cdev_init(HFI1_DIAGPKT_MINOR, name,
                                     &diagpkt_file_ops, &diagpkt_cdev,
-                                    &diagpkt_device);
+                                    &diagpkt_device, false);
        }
 
        return ret;
@@ -592,7 +592,8 @@ static int hfi1_snoop_add(struct hfi1_devdata *dd, const char *name)
 
        ret = hfi1_cdev_init(HFI1_SNOOP_CAPTURE_BASE + dd->unit, name,
                             &snoop_file_ops,
-                            &dd->hfi1_snoop.cdev, &dd->hfi1_snoop.class_dev);
+                            &dd->hfi1_snoop.cdev, &dd->hfi1_snoop.class_dev,
+                            false);
 
        if (ret) {
                dd_dev_err(dd, "Couldn't create %s device: %d", name, ret);
@@ -1012,11 +1013,10 @@ static long hfi1_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
                case HFI1_SNOOP_IOCSETLINKSTATE_EXTRA:
                        memset(&link_info, 0, sizeof(link_info));
 
-                       ret = copy_from_user(&link_info,
+                       if (copy_from_user(&link_info,
                                (struct hfi1_link_info __user *)arg,
-                               sizeof(link_info));
-                       if (ret)
-                               break;
+                               sizeof(link_info)))
+                               ret = -EFAULT;
 
                        value = link_info.port_state;
                        index = link_info.port_number;
@@ -1080,9 +1080,10 @@ static long hfi1_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
                case HFI1_SNOOP_IOCGETLINKSTATE_EXTRA:
                        if (cmd == HFI1_SNOOP_IOCGETLINKSTATE_EXTRA) {
                                memset(&link_info, 0, sizeof(link_info));
-                               ret = copy_from_user(&link_info,
+                               if (copy_from_user(&link_info,
                                        (struct hfi1_link_info __user *)arg,
-                                       sizeof(link_info));
+                                       sizeof(link_info)))
+                                       ret = -EFAULT;
                                index = link_info.port_number;
                        } else {
                                ret = __get_user(index, (int __user *) arg);
@@ -1114,9 +1115,10 @@ static long hfi1_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
                                                        ppd->link_speed_active;
                                link_info.link_width_active =
                                                        ppd->link_width_active;
-                               ret = copy_to_user(
+                               if (copy_to_user(
                                        (struct hfi1_link_info __user *)arg,
-                                       &link_info, sizeof(link_info));
+                                       &link_info, sizeof(link_info)))
+                                       ret = -EFAULT;
                        } else {
                                ret = __put_user(value, (int __user *)arg);
                        }
@@ -1142,10 +1144,9 @@ static long hfi1_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
                        snoop_dbg("Setting filter");
                        /* just copy command structure */
                        argp = (unsigned long *)arg;
-                       ret = copy_from_user(&filter_cmd, (void __user *)argp,
-                                            sizeof(filter_cmd));
-                       if (ret < 0) {
-                               pr_alert("Error copying filter command\n");
+                       if (copy_from_user(&filter_cmd, (void __user *)argp,
+                                            sizeof(filter_cmd))) {
+                               ret = -EFAULT;
                                break;
                        }
                        if (filter_cmd.opcode >= HFI1_MAX_FILTERS) {
@@ -1167,12 +1168,11 @@ static long hfi1_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
                                break;
                        }
                        /* copy remaining data from userspace */
-                       ret = copy_from_user((u8 *)filter_value,
+                       if (copy_from_user((u8 *)filter_value,
                                        (void __user *)filter_cmd.value_ptr,
-                                       filter_cmd.length);
-                       if (ret < 0) {
+                                       filter_cmd.length)) {
                                kfree(filter_value);
-                               pr_alert("Error copying filter data\n");
+                               ret = -EFAULT;
                                break;
                        }
                        /* Drain packets first */
index 469861750b762a86960495c03932cb1be964b7de..72d38500d8ce4e544cac1141497cbb46a7a4aa71 100644 (file)
@@ -1181,6 +1181,7 @@ static int get_ctxt_info(struct file *fp, void __user *ubase, __u32 len)
        struct hfi1_filedata *fd = fp->private_data;
        int ret = 0;
 
+       memset(&cinfo, 0, sizeof(cinfo));
        ret = hfi1_get_base_kinfo(uctxt, &cinfo);
        if (ret < 0)
                goto done;
@@ -2089,14 +2090,16 @@ static int user_add(struct hfi1_devdata *dd)
 
        if (atomic_inc_return(&user_count) == 1) {
                ret = hfi1_cdev_init(0, class_name(), &hfi1_file_ops,
-                                    &wildcard_cdev, &wildcard_device);
+                                    &wildcard_cdev, &wildcard_device,
+                                    true);
                if (ret)
                        goto done;
        }
 
        snprintf(name, sizeof(name), "%s_%d", class_name(), dd->unit);
        ret = hfi1_cdev_init(dd->unit + 1, name, &hfi1_file_ops,
-                            &dd->user_cdev, &dd->user_device);
+                            &dd->user_cdev, &dd->user_device,
+                            true);
        if (ret)
                goto done;
 
@@ -2104,7 +2107,8 @@ static int user_add(struct hfi1_devdata *dd)
                snprintf(name, sizeof(name),
                         "%s_ui%d", class_name(), dd->unit);
                ret = hfi1_cdev_init(dd->unit + UI_OFFSET, name, &ui_file_ops,
-                                    &dd->ui_cdev, &dd->ui_device);
+                                    &dd->ui_cdev, &dd->ui_device,
+                                    false);
                if (ret)
                        goto done;
        }
index 37269eb90c346caee072df28db613a4d4077ed10..b2c1b72d38ce4621e2e0a334eef24823aeaadf74 100644 (file)
@@ -1717,9 +1717,9 @@ static int __subn_get_opa_psi(struct opa_smp *smp, u32 am, u8 *data,
        psi->port_states.portphysstate_portstate =
                (hfi1_ibphys_portstate(ppd) << 4) | (lstate & 0xf);
        psi->link_width_downgrade_tx_active =
-         ppd->link_width_downgrade_tx_active;
+               cpu_to_be16(ppd->link_width_downgrade_tx_active);
        psi->link_width_downgrade_rx_active =
-         ppd->link_width_downgrade_rx_active;
+               cpu_to_be16(ppd->link_width_downgrade_rx_active);
        if (resp_len)
                *resp_len += sizeof(struct opa_port_state_info);
 
index a8c903caecce0ce4b3d15edfa29cddf351becd33..aecd1a74741c656897f9f4ba367892c2a214e7fa 100644 (file)
@@ -737,7 +737,7 @@ u16 sdma_get_descq_cnt(void)
         */
        if (!is_power_of_2(count))
                return SDMA_DESCQ_CNT;
-       if (count < 64 && count > 32768)
+       if (count < 64 || count > 32768)
                return SDMA_DESCQ_CNT;
        return count;
 }
@@ -1848,7 +1848,7 @@ static void dump_sdma_state(struct sdma_engine *sde)
                        dd_dev_err(sde->dd,
                                "\taidx: %u amode: %u alen: %u\n",
                                (u8)((desc[1] & SDMA_DESC1_HEADER_INDEX_SMASK)
-                                       >> SDMA_DESC1_HEADER_INDEX_MASK),
+                                       >> SDMA_DESC1_HEADER_INDEX_SHIFT),
                                (u8)((desc[1] & SDMA_DESC1_HEADER_MODE_SMASK)
                                        >> SDMA_DESC1_HEADER_MODE_SHIFT),
                                (u8)((desc[1] & SDMA_DESC1_HEADER_DWS_SMASK)
@@ -1926,7 +1926,7 @@ void sdma_seqfile_dump_sde(struct seq_file *s, struct sdma_engine *sde)
                if (desc[0] & SDMA_DESC0_FIRST_DESC_FLAG)
                        seq_printf(s, "\t\tahgidx: %u ahgmode: %u\n",
                                (u8)((desc[1] & SDMA_DESC1_HEADER_INDEX_SMASK)
-                                       >> SDMA_DESC1_HEADER_INDEX_MASK),
+                                       >> SDMA_DESC1_HEADER_INDEX_SHIFT),
                                (u8)((desc[1] & SDMA_DESC1_HEADER_MODE_SMASK)
                                        >> SDMA_DESC1_HEADER_MODE_SHIFT));
                head = (head + 1) & sde->sdma_mask;
index 1e613fcd8f4ca905e06d8f2a05012a771ab58d79..49608690389121181195b76c33027436800c7bba 100644 (file)
 /*
  * Bits defined in the send DMA descriptor.
  */
-#define SDMA_DESC0_FIRST_DESC_FLAG      (1ULL<<63)
-#define SDMA_DESC0_LAST_DESC_FLAG       (1ULL<<62)
+#define SDMA_DESC0_FIRST_DESC_FLAG      (1ULL << 63)
+#define SDMA_DESC0_LAST_DESC_FLAG       (1ULL << 62)
 #define SDMA_DESC0_BYTE_COUNT_SHIFT     48
 #define SDMA_DESC0_BYTE_COUNT_WIDTH     14
 #define SDMA_DESC0_BYTE_COUNT_MASK \
-       ((1ULL<<SDMA_DESC0_BYTE_COUNT_WIDTH)-1ULL)
+       ((1ULL << SDMA_DESC0_BYTE_COUNT_WIDTH) - 1)
 #define SDMA_DESC0_BYTE_COUNT_SMASK \
-       (SDMA_DESC0_BYTE_COUNT_MASK<<SDMA_DESC0_BYTE_COUNT_SHIFT)
+       (SDMA_DESC0_BYTE_COUNT_MASK << SDMA_DESC0_BYTE_COUNT_SHIFT)
 #define SDMA_DESC0_PHY_ADDR_SHIFT       0
 #define SDMA_DESC0_PHY_ADDR_WIDTH       48
 #define SDMA_DESC0_PHY_ADDR_MASK \
-       ((1ULL<<SDMA_DESC0_PHY_ADDR_WIDTH)-1ULL)
+       ((1ULL << SDMA_DESC0_PHY_ADDR_WIDTH) - 1)
 #define SDMA_DESC0_PHY_ADDR_SMASK \
-       (SDMA_DESC0_PHY_ADDR_MASK<<SDMA_DESC0_PHY_ADDR_SHIFT)
+       (SDMA_DESC0_PHY_ADDR_MASK << SDMA_DESC0_PHY_ADDR_SHIFT)
 
 #define SDMA_DESC1_HEADER_UPDATE1_SHIFT 32
 #define SDMA_DESC1_HEADER_UPDATE1_WIDTH 32
 #define SDMA_DESC1_HEADER_UPDATE1_MASK \
-       ((1ULL<<SDMA_DESC1_HEADER_UPDATE1_WIDTH)-1ULL)
+       ((1ULL << SDMA_DESC1_HEADER_UPDATE1_WIDTH) - 1)
 #define SDMA_DESC1_HEADER_UPDATE1_SMASK \
-       (SDMA_DESC1_HEADER_UPDATE1_MASK<<SDMA_DESC1_HEADER_UPDATE1_SHIFT)
+       (SDMA_DESC1_HEADER_UPDATE1_MASK << SDMA_DESC1_HEADER_UPDATE1_SHIFT)
 #define SDMA_DESC1_HEADER_MODE_SHIFT    13
 #define SDMA_DESC1_HEADER_MODE_WIDTH    3
 #define SDMA_DESC1_HEADER_MODE_MASK \
-       ((1ULL<<SDMA_DESC1_HEADER_MODE_WIDTH)-1ULL)
+       ((1ULL << SDMA_DESC1_HEADER_MODE_WIDTH) - 1)
 #define SDMA_DESC1_HEADER_MODE_SMASK \
-       (SDMA_DESC1_HEADER_MODE_MASK<<SDMA_DESC1_HEADER_MODE_SHIFT)
+       (SDMA_DESC1_HEADER_MODE_MASK << SDMA_DESC1_HEADER_MODE_SHIFT)
 #define SDMA_DESC1_HEADER_INDEX_SHIFT   8
 #define SDMA_DESC1_HEADER_INDEX_WIDTH   5
 #define SDMA_DESC1_HEADER_INDEX_MASK \
-       ((1ULL<<SDMA_DESC1_HEADER_INDEX_WIDTH)-1ULL)
+       ((1ULL << SDMA_DESC1_HEADER_INDEX_WIDTH) - 1)
 #define SDMA_DESC1_HEADER_INDEX_SMASK \
-       (SDMA_DESC1_HEADER_INDEX_MASK<<SDMA_DESC1_HEADER_INDEX_SHIFT)
+       (SDMA_DESC1_HEADER_INDEX_MASK << SDMA_DESC1_HEADER_INDEX_SHIFT)
 #define SDMA_DESC1_HEADER_DWS_SHIFT     4
 #define SDMA_DESC1_HEADER_DWS_WIDTH     4
 #define SDMA_DESC1_HEADER_DWS_MASK \
-       ((1ULL<<SDMA_DESC1_HEADER_DWS_WIDTH)-1ULL)
+       ((1ULL << SDMA_DESC1_HEADER_DWS_WIDTH) - 1)
 #define SDMA_DESC1_HEADER_DWS_SMASK \
-       (SDMA_DESC1_HEADER_DWS_MASK<<SDMA_DESC1_HEADER_DWS_SHIFT)
+       (SDMA_DESC1_HEADER_DWS_MASK << SDMA_DESC1_HEADER_DWS_SHIFT)
 #define SDMA_DESC1_GENERATION_SHIFT     2
 #define SDMA_DESC1_GENERATION_WIDTH     2
 #define SDMA_DESC1_GENERATION_MASK \
-       ((1ULL<<SDMA_DESC1_GENERATION_WIDTH)-1ULL)
+       ((1ULL << SDMA_DESC1_GENERATION_WIDTH) - 1)
 #define SDMA_DESC1_GENERATION_SMASK \
-       (SDMA_DESC1_GENERATION_MASK<<SDMA_DESC1_GENERATION_SHIFT)
-#define SDMA_DESC1_INT_REQ_FLAG         (1ULL<<1)
-#define SDMA_DESC1_HEAD_TO_HOST_FLAG    (1ULL<<0)
+       (SDMA_DESC1_GENERATION_MASK << SDMA_DESC1_GENERATION_SHIFT)
+#define SDMA_DESC1_INT_REQ_FLAG         (1ULL << 1)
+#define SDMA_DESC1_HEAD_TO_HOST_FLAG    (1ULL << 0)
 
 enum sdma_states {
        sdma_state_s00_hw_down,
index 53ac21431542732a4cd3f2bc8a37a4110fcdeee9..41bb59eb001c72fe214a4114047fdf03156f9007 100644 (file)
@@ -749,11 +749,13 @@ static inline struct verbs_txreq *get_txreq(struct hfi1_ibdev *dev,
        struct verbs_txreq *tx;
 
        tx = kmem_cache_alloc(dev->verbs_txreq_cache, GFP_ATOMIC);
-       if (!tx)
+       if (!tx) {
                /* call slow path to get the lock */
                tx =  __get_txreq(dev, qp);
-       if (tx)
-               tx->qp = qp;
+               if (IS_ERR(tx))
+                       return tx;
+       }
+       tx->qp = qp;
        return tx;
 }
 
index 4299cf45f947ded9433fa045c1cb54bc957a02c4..5e1f16c36b49adfd45dbd2221435fd9bcda57daa 100644 (file)
@@ -81,6 +81,7 @@ void speakup_fake_down_arrow(void)
        __this_cpu_write(reporting_keystroke, true);
        input_report_key(virt_keyboard, KEY_DOWN, PRESSED);
        input_report_key(virt_keyboard, KEY_DOWN, RELEASED);
+       input_sync(virt_keyboard);
        __this_cpu_write(reporting_keystroke, false);
 
        /* reenable preemption */
index fa27ee5f336cbe60398c8e946c0d275de4da78e7..fc790e7592fce7ccd97548b5d5917abe1b081d24 100644 (file)
@@ -10,4 +10,3 @@ visorbus-y += visorchipset.o
 visorbus-y += periodic_work.o
 
 ccflags-y += -Idrivers/staging/unisys/include
-ccflags-y += -Idrivers/staging/unisys/visorutil
index 2309f5f2b238e574db07c80e509d815a98c643c1..a272b48bab282af2f2ddbebc7cb63db5193a4882 100644 (file)
@@ -37,6 +37,8 @@ static int visorbus_debugref;
 #define POLLJIFFIES_TESTWORK         100
 #define POLLJIFFIES_NORMALCHANNEL     10
 
+static int busreg_rc = -ENODEV; /* stores the result from bus registration */
+
 static int visorbus_uevent(struct device *xdev, struct kobj_uevent_env *env);
 static int visorbus_match(struct device *xdev, struct device_driver *xdrv);
 static void fix_vbus_dev_info(struct visor_device *visordev);
@@ -863,6 +865,9 @@ int visorbus_register_visor_driver(struct visor_driver *drv)
 {
        int rc = 0;
 
+       if (busreg_rc < 0)
+               return -ENODEV; /*can't register on a nonexistent bus*/
+
        drv->driver.name = drv->name;
        drv->driver.bus = &visorbus_type;
        drv->driver.probe = visordriver_probe_device;
@@ -885,6 +890,8 @@ int visorbus_register_visor_driver(struct visor_driver *drv)
        if (rc < 0)
                return rc;
        rc = register_driver_attributes(drv);
+       if (rc < 0)
+               driver_unregister(&drv->driver);
        return rc;
 }
 EXPORT_SYMBOL_GPL(visorbus_register_visor_driver);
@@ -1260,10 +1267,8 @@ remove_bus_instance(struct visor_device *dev)
 static int
 create_bus_type(void)
 {
-       int rc = 0;
-
-       rc = bus_register(&visorbus_type);
-       return rc;
+       busreg_rc = bus_register(&visorbus_type);
+       return busreg_rc;
 }
 
 /** Remove the one-and-only one instance of the visor bus type (visorbus_type).
index 8c9da7ea7845a1affc64931faf10d9dfcfe16452..9d3c1e28206240705b74d3913f653be01c4ef6f1 100644 (file)
@@ -1189,16 +1189,16 @@ visornic_rx(struct uiscmdrsp *cmdrsp)
        spin_lock_irqsave(&devdata->priv_lock, flags);
        atomic_dec(&devdata->num_rcvbuf_in_iovm);
 
-       /* update rcv stats - call it with priv_lock held */
-       devdata->net_stats.rx_packets++;
-       devdata->net_stats.rx_bytes = skb->len;
-
        /* set length to how much was ACTUALLY received -
         * NOTE: rcv_done_len includes actual length of data rcvd
         * including ethhdr
         */
        skb->len = cmdrsp->net.rcv.rcv_done_len;
 
+       /* update rcv stats - call it with priv_lock held */
+       devdata->net_stats.rx_packets++;
+       devdata->net_stats.rx_bytes += skb->len;
+
        /* test enabled while holding lock */
        if (!(devdata->enabled && devdata->enab_dis_acked)) {
                /* don't process it unless we're in enable mode and until
@@ -1924,13 +1924,16 @@ static int visornic_probe(struct visor_device *dev)
                        "%s debugfs_create_dir %s failed\n",
                        __func__, netdev->name);
                err = -ENOMEM;
-               goto cleanup_xmit_cmdrsp;
+               goto cleanup_register_netdev;
        }
 
        dev_info(&dev->device, "%s success netdev=%s\n",
                 __func__, netdev->name);
        return 0;
 
+cleanup_register_netdev:
+       unregister_netdev(netdev);
+
 cleanup_napi_add:
        del_timer_sync(&devdata->irq_poll_timer);
        netif_napi_del(&devdata->napi);
@@ -2128,8 +2131,9 @@ static int visornic_init(void)
        if (!dev_num_pool)
                goto cleanup_workqueue;
 
-       visorbus_register_visor_driver(&visornic_driver);
-       return 0;
+       err = visorbus_register_visor_driver(&visornic_driver);
+       if (!err)
+               return 0;
 
 cleanup_workqueue:
        if (visornic_timeout_reset_workqueue) {
index e8a52f7d6204fc7c3e68fe5ad24f8e393ed0e16b..51d1734d5390409e2c98a34c4ad9fc787c1fc362 100644 (file)
@@ -407,6 +407,7 @@ int iscsi_create_default_params(struct iscsi_param_list **param_list_ptr)
                        TYPERANGE_UTF8, USE_INITIAL_ONLY);
        if (!param)
                goto out;
+
        /*
         * Extra parameters for ISER from RFC-5046
         */
@@ -496,9 +497,9 @@ int iscsi_set_keys_to_negotiate(
                } else if (!strcmp(param->name, SESSIONTYPE)) {
                        SET_PSTATE_NEGOTIATE(param);
                } else if (!strcmp(param->name, IFMARKER)) {
-                       SET_PSTATE_NEGOTIATE(param);
+                       SET_PSTATE_REJECT(param);
                } else if (!strcmp(param->name, OFMARKER)) {
-                       SET_PSTATE_NEGOTIATE(param);
+                       SET_PSTATE_REJECT(param);
                } else if (!strcmp(param->name, IFMARKINT)) {
                        SET_PSTATE_REJECT(param);
                } else if (!strcmp(param->name, OFMARKINT)) {
index dcc424ac35d45bfd2cc38bb348c851fc4336796d..88ea4e4f124b2113cf686f470aed171706304a94 100644 (file)
@@ -62,22 +62,13 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u64 unpacked_lun)
        struct se_session *se_sess = se_cmd->se_sess;
        struct se_node_acl *nacl = se_sess->se_node_acl;
        struct se_dev_entry *deve;
+       sense_reason_t ret = TCM_NO_SENSE;
 
        rcu_read_lock();
        deve = target_nacl_find_deve(nacl, unpacked_lun);
        if (deve) {
                atomic_long_inc(&deve->total_cmds);
 
-               if ((se_cmd->data_direction == DMA_TO_DEVICE) &&
-                   (deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY)) {
-                       pr_err("TARGET_CORE[%s]: Detected WRITE_PROTECTED LUN"
-                               " Access for 0x%08llx\n",
-                               se_cmd->se_tfo->get_fabric_name(),
-                               unpacked_lun);
-                       rcu_read_unlock();
-                       return TCM_WRITE_PROTECTED;
-               }
-
                if (se_cmd->data_direction == DMA_TO_DEVICE)
                        atomic_long_add(se_cmd->data_length,
                                        &deve->write_bytes);
@@ -93,6 +84,17 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u64 unpacked_lun)
 
                percpu_ref_get(&se_lun->lun_ref);
                se_cmd->lun_ref_active = true;
+
+               if ((se_cmd->data_direction == DMA_TO_DEVICE) &&
+                   (deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY)) {
+                       pr_err("TARGET_CORE[%s]: Detected WRITE_PROTECTED LUN"
+                               " Access for 0x%08llx\n",
+                               se_cmd->se_tfo->get_fabric_name(),
+                               unpacked_lun);
+                       rcu_read_unlock();
+                       ret = TCM_WRITE_PROTECTED;
+                       goto ref_dev;
+               }
        }
        rcu_read_unlock();
 
@@ -109,12 +111,6 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u64 unpacked_lun)
                                unpacked_lun);
                        return TCM_NON_EXISTENT_LUN;
                }
-               /*
-                * Force WRITE PROTECT for virtual LUN 0
-                */
-               if ((se_cmd->data_direction != DMA_FROM_DEVICE) &&
-                   (se_cmd->data_direction != DMA_NONE))
-                       return TCM_WRITE_PROTECTED;
 
                se_lun = se_sess->se_tpg->tpg_virt_lun0;
                se_cmd->se_lun = se_sess->se_tpg->tpg_virt_lun0;
@@ -123,6 +119,15 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u64 unpacked_lun)
 
                percpu_ref_get(&se_lun->lun_ref);
                se_cmd->lun_ref_active = true;
+
+               /*
+                * Force WRITE PROTECT for virtual LUN 0
+                */
+               if ((se_cmd->data_direction != DMA_FROM_DEVICE) &&
+                   (se_cmd->data_direction != DMA_NONE)) {
+                       ret = TCM_WRITE_PROTECTED;
+                       goto ref_dev;
+               }
        }
        /*
         * RCU reference protected by percpu se_lun->lun_ref taken above that
@@ -130,6 +135,7 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u64 unpacked_lun)
         * pointer can be kfree_rcu() by the final se_lun->lun_group put via
         * target_core_fabric_configfs.c:target_fabric_port_release
         */
+ref_dev:
        se_cmd->se_dev = rcu_dereference_raw(se_lun->lun_se_dev);
        atomic_long_inc(&se_cmd->se_dev->num_cmds);
 
@@ -140,7 +146,7 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd, u64 unpacked_lun)
                atomic_long_add(se_cmd->data_length,
                                &se_cmd->se_dev->read_bytes);
 
-       return 0;
+       return ret;
 }
 EXPORT_SYMBOL(transport_lookup_cmd_lun);
 
@@ -427,8 +433,6 @@ void core_disable_device_list_for_node(
 
        hlist_del_rcu(&orig->link);
        clear_bit(DEF_PR_REG_ACTIVE, &orig->deve_flags);
-       rcu_assign_pointer(orig->se_lun, NULL);
-       rcu_assign_pointer(orig->se_lun_acl, NULL);
        orig->lun_flags = 0;
        orig->creation_time = 0;
        orig->attach_count--;
@@ -439,6 +443,9 @@ void core_disable_device_list_for_node(
        kref_put(&orig->pr_kref, target_pr_kref_release);
        wait_for_completion(&orig->pr_comp);
 
+       rcu_assign_pointer(orig->se_lun, NULL);
+       rcu_assign_pointer(orig->se_lun_acl, NULL);
+
        kfree_rcu(orig, rcu_head);
 
        core_scsi3_free_pr_reg_from_nacl(dev, nacl);
index 9522960c7fddacf70c682326a38586f8562c4487..22390e0e046ca266c2173ab50abf695f0cc2aaa2 100644 (file)
@@ -187,5 +187,5 @@ core_delete_hba(struct se_hba *hba)
 
 bool target_sense_desc_format(struct se_device *dev)
 {
-       return dev->transport->get_blocks(dev) > U32_MAX;
+       return (dev) ? dev->transport->get_blocks(dev) > U32_MAX : false;
 }
index 5a9982f5d5d642ca1080e2237d5f2cab2dec7a18..0f19e11acac2197806eba0a42290b5067b560d73 100644 (file)
@@ -105,6 +105,8 @@ static int iblock_configure_device(struct se_device *dev)
        mode = FMODE_READ|FMODE_EXCL;
        if (!ib_dev->ibd_readonly)
                mode |= FMODE_WRITE;
+       else
+               dev->dev_flags |= DF_READ_ONLY;
 
        bd = blkdev_get_by_path(ib_dev->ibd_udev_path, mode, ib_dev);
        if (IS_ERR(bd)) {
index 5ab7100de17eb5694b162403ef43585c4bbceaf1..e7933115087ab2fab461ee4b10c2012398eb73e0 100644 (file)
@@ -618,7 +618,7 @@ static struct t10_pr_registration *__core_scsi3_do_alloc_registration(
        struct se_device *dev,
        struct se_node_acl *nacl,
        struct se_lun *lun,
-       struct se_dev_entry *deve,
+       struct se_dev_entry *dest_deve,
        u64 mapped_lun,
        unsigned char *isid,
        u64 sa_res_key,
@@ -640,7 +640,29 @@ static struct t10_pr_registration *__core_scsi3_do_alloc_registration(
        INIT_LIST_HEAD(&pr_reg->pr_reg_atp_mem_list);
        atomic_set(&pr_reg->pr_res_holders, 0);
        pr_reg->pr_reg_nacl = nacl;
-       pr_reg->pr_reg_deve = deve;
+       /*
+        * For destination registrations for ALL_TG_PT=1 and SPEC_I_PT=1,
+        * the se_dev_entry->pr_ref will have been already obtained by
+        * core_get_se_deve_from_rtpi() or __core_scsi3_alloc_registration().
+        *
+        * Otherwise, locate se_dev_entry now and obtain a reference until
+        * registration completes in __core_scsi3_add_registration().
+        */
+       if (dest_deve) {
+               pr_reg->pr_reg_deve = dest_deve;
+       } else {
+               rcu_read_lock();
+               pr_reg->pr_reg_deve = target_nacl_find_deve(nacl, mapped_lun);
+               if (!pr_reg->pr_reg_deve) {
+                       rcu_read_unlock();
+                       pr_err("Unable to locate PR deve %s mapped_lun: %llu\n",
+                               nacl->initiatorname, mapped_lun);
+                       kmem_cache_free(t10_pr_reg_cache, pr_reg);
+                       return NULL;
+               }
+               kref_get(&pr_reg->pr_reg_deve->pr_kref);
+               rcu_read_unlock();
+       }
        pr_reg->pr_res_mapped_lun = mapped_lun;
        pr_reg->pr_aptpl_target_lun = lun->unpacked_lun;
        pr_reg->tg_pt_sep_rtpi = lun->lun_rtpi;
@@ -936,17 +958,29 @@ static int __core_scsi3_check_aptpl_registration(
                    !(strcmp(pr_reg->pr_tport, t_port)) &&
                     (pr_reg->pr_reg_tpgt == tpgt) &&
                     (pr_reg->pr_aptpl_target_lun == target_lun)) {
+                       /*
+                        * Obtain the ->pr_reg_deve pointer + reference, that
+                        * is released by __core_scsi3_add_registration() below.
+                        */
+                       rcu_read_lock();
+                       pr_reg->pr_reg_deve = target_nacl_find_deve(nacl, mapped_lun);
+                       if (!pr_reg->pr_reg_deve) {
+                               pr_err("Unable to locate PR APTPL %s mapped_lun:"
+                                       " %llu\n", nacl->initiatorname, mapped_lun);
+                               rcu_read_unlock();
+                               continue;
+                       }
+                       kref_get(&pr_reg->pr_reg_deve->pr_kref);
+                       rcu_read_unlock();
 
                        pr_reg->pr_reg_nacl = nacl;
                        pr_reg->tg_pt_sep_rtpi = lun->lun_rtpi;
-
                        list_del(&pr_reg->pr_reg_aptpl_list);
                        spin_unlock(&pr_tmpl->aptpl_reg_lock);
                        /*
                         * At this point all of the pointers in *pr_reg will
                         * be setup, so go ahead and add the registration.
                         */
-
                        __core_scsi3_add_registration(dev, nacl, pr_reg, 0, 0);
                        /*
                         * If this registration is the reservation holder,
@@ -1044,18 +1078,11 @@ static void __core_scsi3_add_registration(
 
        __core_scsi3_dump_registration(tfo, dev, nacl, pr_reg, register_type);
        spin_unlock(&pr_tmpl->registration_lock);
-
-       rcu_read_lock();
-       deve = pr_reg->pr_reg_deve;
-       if (deve)
-               set_bit(DEF_PR_REG_ACTIVE, &deve->deve_flags);
-       rcu_read_unlock();
-
        /*
         * Skip extra processing for ALL_TG_PT=0 or REGISTER_AND_MOVE.
         */
        if (!pr_reg->pr_reg_all_tg_pt || register_move)
-               return;
+               goto out;
        /*
         * Walk pr_reg->pr_reg_atp_list and add registrations for ALL_TG_PT=1
         * allocated in __core_scsi3_alloc_registration()
@@ -1075,19 +1102,31 @@ static void __core_scsi3_add_registration(
                __core_scsi3_dump_registration(tfo, dev, nacl_tmp, pr_reg_tmp,
                                               register_type);
                spin_unlock(&pr_tmpl->registration_lock);
-
+               /*
+                * Drop configfs group dependency reference and deve->pr_kref
+                * obtained from  __core_scsi3_alloc_registration() code.
+                */
                rcu_read_lock();
                deve = pr_reg_tmp->pr_reg_deve;
-               if (deve)
+               if (deve) {
                        set_bit(DEF_PR_REG_ACTIVE, &deve->deve_flags);
+                       core_scsi3_lunacl_undepend_item(deve);
+                       pr_reg_tmp->pr_reg_deve = NULL;
+               }
                rcu_read_unlock();
-
-               /*
-                * Drop configfs group dependency reference from
-                * __core_scsi3_alloc_registration()
-                */
-               core_scsi3_lunacl_undepend_item(pr_reg_tmp->pr_reg_deve);
        }
+out:
+       /*
+        * Drop deve->pr_kref obtained in __core_scsi3_do_alloc_registration()
+        */
+       rcu_read_lock();
+       deve = pr_reg->pr_reg_deve;
+       if (deve) {
+               set_bit(DEF_PR_REG_ACTIVE, &deve->deve_flags);
+               kref_put(&deve->pr_kref, target_pr_kref_release);
+               pr_reg->pr_reg_deve = NULL;
+       }
+       rcu_read_unlock();
 }
 
 static int core_scsi3_alloc_registration(
@@ -1785,9 +1824,11 @@ core_scsi3_decode_spec_i_port(
                        dest_node_acl->initiatorname, i_buf, (dest_se_deve) ?
                        dest_se_deve->mapped_lun : 0);
 
-               if (!dest_se_deve)
+               if (!dest_se_deve) {
+                       kref_put(&local_pr_reg->pr_reg_deve->pr_kref,
+                                target_pr_kref_release);
                        continue;
-
+               }
                core_scsi3_lunacl_undepend_item(dest_se_deve);
                core_scsi3_nodeacl_undepend_item(dest_node_acl);
                core_scsi3_tpg_undepend_item(dest_tpg);
@@ -1823,9 +1864,11 @@ out:
 
                kmem_cache_free(t10_pr_reg_cache, dest_pr_reg);
 
-               if (!dest_se_deve)
+               if (!dest_se_deve) {
+                       kref_put(&local_pr_reg->pr_reg_deve->pr_kref,
+                                target_pr_kref_release);
                        continue;
-
+               }
                core_scsi3_lunacl_undepend_item(dest_se_deve);
                core_scsi3_nodeacl_undepend_item(dest_node_acl);
                core_scsi3_tpg_undepend_item(dest_tpg);
index 2d0381dd105c4998f225603e80bc22e2a6245c08..5fb9dd7f08bb030d6970f05a5600af41b37257a6 100644 (file)
@@ -668,7 +668,10 @@ int core_tpg_add_lun(
        list_add_tail(&lun->lun_dev_link, &dev->dev_sep_list);
        spin_unlock(&dev->se_port_lock);
 
-       lun->lun_access = lun_access;
+       if (dev->dev_flags & DF_READ_ONLY)
+               lun->lun_access = TRANSPORT_LUNFLAGS_READ_ONLY;
+       else
+               lun->lun_access = lun_access;
        if (!(dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE))
                hlist_add_head_rcu(&lun->link, &tpg->tpg_lun_hlist);
        mutex_unlock(&tpg->tpg_lun_mutex);
index 039004400987366b876be8ce58bc1290844f4e08..5aabc4bc0d757fb0d7f423663867c8b634797a97 100644 (file)
@@ -163,7 +163,7 @@ config THERMAL_EMULATION
 
 config HISI_THERMAL
        tristate "Hisilicon thermal driver"
-       depends on ARCH_HISI && CPU_THERMAL && OF
+       depends on (ARCH_HISI && CPU_THERMAL && OF) || COMPILE_TEST
        help
          Enable this to plug hisilicon's thermal sensor driver into the Linux
          thermal framework. cpufreq is used as the cooling device to throttle
@@ -182,7 +182,7 @@ config IMX_THERMAL
 
 config SPEAR_THERMAL
        bool "SPEAr thermal sensor driver"
-       depends on PLAT_SPEAR
+       depends on PLAT_SPEAR || COMPILE_TEST
        depends on OF
        help
          Enable this to plug the SPEAr thermal sensor driver into the Linux
@@ -190,7 +190,7 @@ config SPEAR_THERMAL
 
 config ROCKCHIP_THERMAL
        tristate "Rockchip thermal driver"
-       depends on ARCH_ROCKCHIP
+       depends on ARCH_ROCKCHIP || COMPILE_TEST
        depends on RESET_CONTROLLER
        help
          Rockchip thermal driver provides support for Temperature sensor
@@ -208,7 +208,7 @@ config RCAR_THERMAL
 
 config KIRKWOOD_THERMAL
        tristate "Temperature sensor on Marvell Kirkwood SoCs"
-       depends on MACH_KIRKWOOD
+       depends on MACH_KIRKWOOD || COMPILE_TEST
        depends on OF
        help
          Support for the Kirkwood thermal sensor driver into the Linux thermal
@@ -216,7 +216,7 @@ config KIRKWOOD_THERMAL
 
 config DOVE_THERMAL
        tristate "Temperature sensor on Marvell Dove SoCs"
-       depends on ARCH_DOVE || MACH_DOVE
+       depends on ARCH_DOVE || MACH_DOVE || COMPILE_TEST
        depends on OF
        help
          Support for the Dove thermal sensor driver in the Linux thermal
@@ -234,7 +234,7 @@ config DB8500_THERMAL
 
 config ARMADA_THERMAL
        tristate "Armada 370/XP thermal management"
-       depends on ARCH_MVEBU
+       depends on ARCH_MVEBU || COMPILE_TEST
        depends on OF
        help
          Enable this option if you want to have support for thermal management
@@ -349,11 +349,12 @@ config INTEL_PCH_THERMAL
          programmable trip points and other information.
 
 menu "Texas Instruments thermal drivers"
+depends on ARCH_HAS_BANDGAP || COMPILE_TEST
 source "drivers/thermal/ti-soc-thermal/Kconfig"
 endmenu
 
 menu "Samsung thermal drivers"
-depends on ARCH_EXYNOS
+depends on ARCH_EXYNOS || COMPILE_TEST
 source "drivers/thermal/samsung/Kconfig"
 endmenu
 
@@ -364,7 +365,7 @@ endmenu
 
 config QCOM_SPMI_TEMP_ALARM
        tristate "Qualcomm SPMI PMIC Temperature Alarm"
-       depends on OF && SPMI && IIO
+       depends on OF && (SPMI || COMPILE_TEST) && IIO
        select REGMAP_SPMI
        help
          This enables a thermal sysfs driver for Qualcomm plug-and-play (QPNP)
index 620dcd405ff6eec9ae65b0af8e93c25daae15d1f..42c6f71bdcc16e96d956ebed4ed808c5701d8afd 100644 (file)
@@ -262,7 +262,9 @@ static int cpufreq_thermal_notifier(struct notifier_block *nb,
  * efficiently.  Power is stored in mW, frequency in KHz.  The
  * resulting table is in ascending order.
  *
- * Return: 0 on success, -E* on error.
+ * Return: 0 on success, -EINVAL if there are no OPPs for any CPUs,
+ * -ENOMEM if we run out of memory or -EAGAIN if an OPP was
+ * added/enabled while the function was executing.
  */
 static int build_dyn_power_table(struct cpufreq_cooling_device *cpufreq_device,
                                 u32 capacitance)
@@ -273,8 +275,6 @@ static int build_dyn_power_table(struct cpufreq_cooling_device *cpufreq_device,
        int num_opps = 0, cpu, i, ret = 0;
        unsigned long freq;
 
-       rcu_read_lock();
-
        for_each_cpu(cpu, &cpufreq_device->allowed_cpus) {
                dev = get_cpu_device(cpu);
                if (!dev) {
@@ -284,24 +284,20 @@ static int build_dyn_power_table(struct cpufreq_cooling_device *cpufreq_device,
                }
 
                num_opps = dev_pm_opp_get_opp_count(dev);
-               if (num_opps > 0) {
+               if (num_opps > 0)
                        break;
-               } else if (num_opps < 0) {
-                       ret = num_opps;
-                       goto unlock;
-               }
+               else if (num_opps < 0)
+                       return num_opps;
        }
 
-       if (num_opps == 0) {
-               ret = -EINVAL;
-               goto unlock;
-       }
+       if (num_opps == 0)
+               return -EINVAL;
 
        power_table = kcalloc(num_opps, sizeof(*power_table), GFP_KERNEL);
-       if (!power_table) {
-               ret = -ENOMEM;
-               goto unlock;
-       }
+       if (!power_table)
+               return -ENOMEM;
+
+       rcu_read_lock();
 
        for (freq = 0, i = 0;
             opp = dev_pm_opp_find_freq_ceil(dev, &freq), !IS_ERR(opp);
@@ -309,6 +305,12 @@ static int build_dyn_power_table(struct cpufreq_cooling_device *cpufreq_device,
                u32 freq_mhz, voltage_mv;
                u64 power;
 
+               if (i >= num_opps) {
+                       rcu_read_unlock();
+                       ret = -EAGAIN;
+                       goto free_power_table;
+               }
+
                freq_mhz = freq / 1000000;
                voltage_mv = dev_pm_opp_get_voltage(opp) / 1000;
 
@@ -326,17 +328,22 @@ static int build_dyn_power_table(struct cpufreq_cooling_device *cpufreq_device,
                power_table[i].power = power;
        }
 
-       if (i == 0) {
+       rcu_read_unlock();
+
+       if (i != num_opps) {
                ret = PTR_ERR(opp);
-               goto unlock;
+               goto free_power_table;
        }
 
        cpufreq_device->cpu_dev = dev;
        cpufreq_device->dyn_power_table = power_table;
        cpufreq_device->dyn_power_table_entries = i;
 
-unlock:
-       rcu_read_unlock();
+       return 0;
+
+free_power_table:
+       kfree(power_table);
+
        return ret;
 }
 
@@ -847,7 +854,7 @@ __cpufreq_cooling_register(struct device_node *np,
        ret = get_idr(&cpufreq_idr, &cpufreq_dev->id);
        if (ret) {
                cool_dev = ERR_PTR(ret);
-               goto free_table;
+               goto free_power_table;
        }
 
        snprintf(dev_name, sizeof(dev_name), "thermal-cpufreq-%d",
@@ -889,6 +896,8 @@ __cpufreq_cooling_register(struct device_node *np,
 
 remove_idr:
        release_idr(&cpufreq_idr, cpufreq_dev->id);
+free_power_table:
+       kfree(cpufreq_dev->dyn_power_table);
 free_table:
        kfree(cpufreq_dev->freq_table);
 free_time_in_idle_timestamp:
@@ -1039,6 +1048,7 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
 
        thermal_cooling_device_unregister(cpufreq_dev->cool_dev);
        release_idr(&cpufreq_idr, cpufreq_dev->id);
+       kfree(cpufreq_dev->dyn_power_table);
        kfree(cpufreq_dev->time_in_idle_timestamp);
        kfree(cpufreq_dev->time_in_idle);
        kfree(cpufreq_dev->freq_table);
index 607b62c7e6114cc005ccf597e4f0ccb804e0e99b..e58bd0b658b555e21331b8d836b5eeab859862ae 100644 (file)
@@ -72,6 +72,7 @@ static const struct of_device_id db8500_cpufreq_cooling_match[] = {
        { .compatible = "stericsson,db8500-cpufreq-cooling" },
        {},
 };
+MODULE_DEVICE_TABLE(of, db8500_cpufreq_cooling_match);
 #endif
 
 static struct platform_driver db8500_cpufreq_cooling_driver = {
index 9c8a7aad0252e5de75c862213db2f001f06bf9dd..e570ff084add5b0596cbac05d07bca560d350b01 100644 (file)
@@ -24,6 +24,8 @@
 
 #include "thermal_core.h"
 
+#define INVALID_TRIP -1
+
 #define FRAC_BITS 10
 #define int_to_frac(x) ((x) << FRAC_BITS)
 #define frac_to_int(x) ((x) >> FRAC_BITS)
@@ -56,22 +58,119 @@ static inline s64 div_frac(s64 x, s64 y)
 
 /**
  * struct power_allocator_params - parameters for the power allocator governor
+ * @allocated_tzp:     whether we have allocated tzp for this thermal zone and
+ *                     it needs to be freed on unbind
  * @err_integral:      accumulated error in the PID controller.
  * @prev_err:  error in the previous iteration of the PID controller.
  *             Used to calculate the derivative term.
  * @trip_switch_on:    first passive trip point of the thermal zone.  The
  *                     governor switches on when this trip point is crossed.
+ *                     If the thermal zone only has one passive trip point,
+ *                     @trip_switch_on should be INVALID_TRIP.
  * @trip_max_desired_temperature:      last passive trip point of the thermal
  *                                     zone.  The temperature we are
  *                                     controlling for.
  */
 struct power_allocator_params {
+       bool allocated_tzp;
        s64 err_integral;
        s32 prev_err;
        int trip_switch_on;
        int trip_max_desired_temperature;
 };
 
+/**
+ * estimate_sustainable_power() - Estimate the sustainable power of a thermal zone
+ * @tz: thermal zone we are operating in
+ *
+ * For thermal zones that don't provide a sustainable_power in their
+ * thermal_zone_params, estimate one.  Calculate it using the minimum
+ * power of all the cooling devices as that gives a valid value that
+ * can give some degree of functionality.  For optimal performance of
+ * this governor, provide a sustainable_power in the thermal zone's
+ * thermal_zone_params.
+ */
+static u32 estimate_sustainable_power(struct thermal_zone_device *tz)
+{
+       u32 sustainable_power = 0;
+       struct thermal_instance *instance;
+       struct power_allocator_params *params = tz->governor_data;
+
+       list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
+               struct thermal_cooling_device *cdev = instance->cdev;
+               u32 min_power;
+
+               if (instance->trip != params->trip_max_desired_temperature)
+                       continue;
+
+               if (power_actor_get_min_power(cdev, tz, &min_power))
+                       continue;
+
+               sustainable_power += min_power;
+       }
+
+       return sustainable_power;
+}
+
+/**
+ * estimate_pid_constants() - Estimate the constants for the PID controller
+ * @tz:                thermal zone for which to estimate the constants
+ * @sustainable_power: sustainable power for the thermal zone
+ * @trip_switch_on:    trip point number for the switch on temperature
+ * @control_temp:      target temperature for the power allocator governor
+ * @force:     whether to force the update of the constants
+ *
+ * This function is used to update the estimation of the PID
+ * controller constants in struct thermal_zone_parameters.
+ * Sustainable power is provided in case it was estimated.  The
+ * estimated sustainable_power should not be stored in the
+ * thermal_zone_parameters so it has to be passed explicitly to this
+ * function.
+ *
+ * If @force is not set, the values in the thermal zone's parameters
+ * are preserved if they are not zero.  If @force is set, the values
+ * in thermal zone's parameters are overwritten.
+ */
+static void estimate_pid_constants(struct thermal_zone_device *tz,
+                                  u32 sustainable_power, int trip_switch_on,
+                                  int control_temp, bool force)
+{
+       int ret;
+       int switch_on_temp;
+       u32 temperature_threshold;
+
+       ret = tz->ops->get_trip_temp(tz, trip_switch_on, &switch_on_temp);
+       if (ret)
+               switch_on_temp = 0;
+
+       temperature_threshold = control_temp - switch_on_temp;
+       /*
+        * estimate_pid_constants() tries to find appropriate default
+        * values for thermal zones that don't provide them. If a
+        * system integrator has configured a thermal zone with two
+        * passive trip points at the same temperature, that person
+        * hasn't put any effort to set up the thermal zone properly
+        * so just give up.
+        */
+       if (!temperature_threshold)
+               return;
+
+       if (!tz->tzp->k_po || force)
+               tz->tzp->k_po = int_to_frac(sustainable_power) /
+                       temperature_threshold;
+
+       if (!tz->tzp->k_pu || force)
+               tz->tzp->k_pu = int_to_frac(2 * sustainable_power) /
+                       temperature_threshold;
+
+       if (!tz->tzp->k_i || force)
+               tz->tzp->k_i = int_to_frac(10) / 1000;
+       /*
+        * The default for k_d and integral_cutoff is 0, so we can
+        * leave them as they are.
+        */
+}
+
 /**
  * pid_controller() - PID controller
  * @tz:        thermal zone we are operating in
@@ -98,10 +197,20 @@ static u32 pid_controller(struct thermal_zone_device *tz,
 {
        s64 p, i, d, power_range;
        s32 err, max_power_frac;
+       u32 sustainable_power;
        struct power_allocator_params *params = tz->governor_data;
 
        max_power_frac = int_to_frac(max_allocatable_power);
 
+       if (tz->tzp->sustainable_power) {
+               sustainable_power = tz->tzp->sustainable_power;
+       } else {
+               sustainable_power = estimate_sustainable_power(tz);
+               estimate_pid_constants(tz, sustainable_power,
+                                      params->trip_switch_on, control_temp,
+                                      true);
+       }
+
        err = control_temp - current_temp;
        err = int_to_frac(err);
 
@@ -139,7 +248,7 @@ static u32 pid_controller(struct thermal_zone_device *tz,
        power_range = p + i + d;
 
        /* feed-forward the known sustainable dissipatable power */
-       power_range = tz->tzp->sustainable_power + frac_to_int(power_range);
+       power_range = sustainable_power + frac_to_int(power_range);
 
        power_range = clamp(power_range, (s64)0, (s64)max_allocatable_power);
 
@@ -247,6 +356,11 @@ static int allocate_power(struct thermal_zone_device *tz,
                }
        }
 
+       if (!num_actors) {
+               ret = -ENODEV;
+               goto unlock;
+       }
+
        /*
         * We need to allocate five arrays of the same size:
         * req_power, max_power, granted_power, extra_actor_power and
@@ -340,43 +454,66 @@ unlock:
        return ret;
 }
 
-static int get_governor_trips(struct thermal_zone_device *tz,
-                             struct power_allocator_params *params)
+/**
+ * get_governor_trips() - get the number of the two trip points that are key for this governor
+ * @tz:        thermal zone to operate on
+ * @params:    pointer to private data for this governor
+ *
+ * The power allocator governor works optimally with two trips points:
+ * a "switch on" trip point and a "maximum desired temperature".  These
+ * are defined as the first and last passive trip points.
+ *
+ * If there is only one trip point, then that's considered to be the
+ * "maximum desired temperature" trip point and the governor is always
+ * on.  If there are no passive or active trip points, then the
+ * governor won't do anything.  In fact, its throttle function
+ * won't be called at all.
+ */
+static void get_governor_trips(struct thermal_zone_device *tz,
+                              struct power_allocator_params *params)
 {
-       int i, ret, last_passive;
+       int i, last_active, last_passive;
        bool found_first_passive;
 
        found_first_passive = false;
-       last_passive = -1;
-       ret = -EINVAL;
+       last_active = INVALID_TRIP;
+       last_passive = INVALID_TRIP;
 
        for (i = 0; i < tz->trips; i++) {
                enum thermal_trip_type type;
+               int ret;
 
                ret = tz->ops->get_trip_type(tz, i, &type);
-               if (ret)
-                       return ret;
+               if (ret) {
+                       dev_warn(&tz->device,
+                                "Failed to get trip point %d type: %d\n", i,
+                                ret);
+                       continue;
+               }
 
-               if (!found_first_passive) {
-                       if (type == THERMAL_TRIP_PASSIVE) {
+               if (type == THERMAL_TRIP_PASSIVE) {
+                       if (!found_first_passive) {
                                params->trip_switch_on = i;
                                found_first_passive = true;
+                       } else  {
+                               last_passive = i;
                        }
-               } else if (type == THERMAL_TRIP_PASSIVE) {
-                       last_passive = i;
+               } else if (type == THERMAL_TRIP_ACTIVE) {
+                       last_active = i;
                } else {
                        break;
                }
        }
 
-       if (last_passive != -1) {
+       if (last_passive != INVALID_TRIP) {
                params->trip_max_desired_temperature = last_passive;
-               ret = 0;
+       } else if (found_first_passive) {
+               params->trip_max_desired_temperature = params->trip_switch_on;
+               params->trip_switch_on = INVALID_TRIP;
        } else {
-               ret = -EINVAL;
+               params->trip_switch_on = INVALID_TRIP;
+               params->trip_max_desired_temperature = last_active;
        }
-
-       return ret;
 }
 
 static void reset_pid_controller(struct power_allocator_params *params)
@@ -405,60 +542,45 @@ static void allow_maximum_power(struct thermal_zone_device *tz)
  * power_allocator_bind() - bind the power_allocator governor to a thermal zone
  * @tz:        thermal zone to bind it to
  *
- * Check that the thermal zone is valid for this governor, that is, it
- * has two thermal trips.  If so, initialize the PID controller
- * parameters and bind it to the thermal zone.
+ * Initialize the PID controller parameters and bind it to the thermal
+ * zone.
  *
- * Return: 0 on success, -EINVAL if the trips were invalid or -ENOMEM
- * if we ran out of memory.
+ * Return: 0 on success, or -ENOMEM if we ran out of memory.
  */
 static int power_allocator_bind(struct thermal_zone_device *tz)
 {
        int ret;
        struct power_allocator_params *params;
-       int switch_on_temp, control_temp;
-       u32 temperature_threshold;
-
-       if (!tz->tzp || !tz->tzp->sustainable_power) {
-               dev_err(&tz->device,
-                       "power_allocator: missing sustainable_power\n");
-               return -EINVAL;
-       }
+       int control_temp;
 
        params = kzalloc(sizeof(*params), GFP_KERNEL);
        if (!params)
                return -ENOMEM;
 
-       ret = get_governor_trips(tz, params);
-       if (ret) {
-               dev_err(&tz->device,
-                       "thermal zone %s has wrong trip setup for power allocator\n",
-                       tz->type);
-               goto free;
-       }
+       if (!tz->tzp) {
+               tz->tzp = kzalloc(sizeof(*tz->tzp), GFP_KERNEL);
+               if (!tz->tzp) {
+                       ret = -ENOMEM;
+                       goto free_params;
+               }
 
-       ret = tz->ops->get_trip_temp(tz, params->trip_switch_on,
-                                    &switch_on_temp);
-       if (ret)
-               goto free;
+               params->allocated_tzp = true;
+       }
 
-       ret = tz->ops->get_trip_temp(tz, params->trip_max_desired_temperature,
-                                    &control_temp);
-       if (ret)
-               goto free;
+       if (!tz->tzp->sustainable_power)
+               dev_warn(&tz->device, "power_allocator: sustainable_power will be estimated\n");
 
-       temperature_threshold = control_temp - switch_on_temp;
+       get_governor_trips(tz, params);
 
-       tz->tzp->k_po = tz->tzp->k_po ?:
-               int_to_frac(tz->tzp->sustainable_power) / temperature_threshold;
-       tz->tzp->k_pu = tz->tzp->k_pu ?:
-               int_to_frac(2 * tz->tzp->sustainable_power) /
-               temperature_threshold;
-       tz->tzp->k_i = tz->tzp->k_i ?: int_to_frac(10) / 1000;
-       /*
-        * The default for k_d and integral_cutoff is 0, so we can
-        * leave them as they are.
-        */
+       if (tz->trips > 0) {
+               ret = tz->ops->get_trip_temp(tz,
+                                       params->trip_max_desired_temperature,
+                                       &control_temp);
+               if (!ret)
+                       estimate_pid_constants(tz, tz->tzp->sustainable_power,
+                                              params->trip_switch_on,
+                                              control_temp, false);
+       }
 
        reset_pid_controller(params);
 
@@ -466,14 +588,23 @@ static int power_allocator_bind(struct thermal_zone_device *tz)
 
        return 0;
 
-free:
+free_params:
        kfree(params);
+
        return ret;
 }
 
 static void power_allocator_unbind(struct thermal_zone_device *tz)
 {
+       struct power_allocator_params *params = tz->governor_data;
+
        dev_dbg(&tz->device, "Unbinding from thermal zone %d\n", tz->id);
+
+       if (params->allocated_tzp) {
+               kfree(tz->tzp);
+               tz->tzp = NULL;
+       }
+
        kfree(tz->governor_data);
        tz->governor_data = NULL;
 }
@@ -499,13 +630,7 @@ static int power_allocator_throttle(struct thermal_zone_device *tz, int trip)
 
        ret = tz->ops->get_trip_temp(tz, params->trip_switch_on,
                                     &switch_on_temp);
-       if (ret) {
-               dev_warn(&tz->device,
-                        "Failed to get switch on temperature: %d\n", ret);
-               return ret;
-       }
-
-       if (current_temp < switch_on_temp) {
+       if (!ret && (current_temp < switch_on_temp)) {
                tz->passive = 0;
                reset_pid_controller(params);
                allow_maximum_power(tz);
index 0bae8cc6c23a0be622b2addf1479830e838cb243..ca920b0ecf8f8688763426ba2d6b253a3620a1b6 100644 (file)
@@ -932,7 +932,7 @@ static void exynos4412_tmu_set_emulation(struct exynos_tmu_data *data,
 
        if (data->soc == SOC_ARCH_EXYNOS5260)
                emul_con = EXYNOS5260_EMUL_CON;
-       if (data->soc == SOC_ARCH_EXYNOS5433)
+       else if (data->soc == SOC_ARCH_EXYNOS5433)
                emul_con = EXYNOS5433_TMU_EMUL_CON;
        else if (data->soc == SOC_ARCH_EXYNOS7)
                emul_con = EXYNOS7_TMU_REG_EMUL_CON;
index 5e5fc7015c7f8da4ba283287acdae8269733b373..d9e525cc9c1ce24bcd9d55dd59730f375b15d552 100644 (file)
@@ -1012,6 +1012,34 @@ int power_actor_get_max_power(struct thermal_cooling_device *cdev,
        return cdev->ops->state2power(cdev, tz, 0, max_power);
 }
 
+/**
+ * power_actor_get_min_power() - get the mainimum power that a cdev can consume
+ * @cdev:      pointer to &thermal_cooling_device
+ * @tz:                a valid thermal zone device pointer
+ * @min_power: pointer in which to store the minimum power
+ *
+ * Calculate the minimum power consumption in milliwatts that the
+ * cooling device can currently consume and store it in @min_power.
+ *
+ * Return: 0 on success, -EINVAL if @cdev doesn't support the
+ * power_actor API or -E* on other error.
+ */
+int power_actor_get_min_power(struct thermal_cooling_device *cdev,
+                             struct thermal_zone_device *tz, u32 *min_power)
+{
+       unsigned long max_state;
+       int ret;
+
+       if (!cdev_is_power_actor(cdev))
+               return -EINVAL;
+
+       ret = cdev->ops->get_max_state(cdev, &max_state);
+       if (ret)
+               return ret;
+
+       return cdev->ops->state2power(cdev, tz, max_state, min_power);
+}
+
 /**
  * power_actor_set_power() - limit the maximum power that a cooling device can consume
  * @cdev:      pointer to &thermal_cooling_device
index bd4c7beba67915200d6e44c505a49f44a3442978..cb6686ff09ae9d64b18f68c7a1854f7694ee3ce4 100644 (file)
@@ -1,7 +1,5 @@
 config TI_SOC_THERMAL
        tristate "Texas Instruments SoCs temperature sensor driver"
-       depends on THERMAL
-       depends on ARCH_HAS_BANDGAP
        help
          If you say yes here you get support for the Texas Instruments
          OMAP4460+ on die bandgap temperature sensor support. The register
@@ -24,7 +22,7 @@ config TI_THERMAL
 config OMAP4_THERMAL
        bool "Texas Instruments OMAP4 thermal support"
        depends on TI_SOC_THERMAL
-       depends on ARCH_OMAP4
+       depends on ARCH_OMAP4 || COMPILE_TEST
        help
          If you say yes here you get thermal support for the Texas Instruments
          OMAP4 SoC family. The current chip supported are:
@@ -38,7 +36,7 @@ config OMAP4_THERMAL
 config OMAP5_THERMAL
        bool "Texas Instruments OMAP5 thermal support"
        depends on TI_SOC_THERMAL
-       depends on SOC_OMAP5
+       depends on SOC_OMAP5 || COMPILE_TEST
        help
          If you say yes here you get thermal support for the Texas Instruments
          OMAP5 SoC family. The current chip supported are:
@@ -50,7 +48,7 @@ config OMAP5_THERMAL
 config DRA752_THERMAL
        bool "Texas Instruments DRA752 thermal support"
        depends on TI_SOC_THERMAL
-       depends on SOC_DRA7XX
+       depends on SOC_DRA7XX || COMPILE_TEST
        help
          If you say yes here you get thermal support for the Texas Instruments
          DRA752 SoC family. The current chip supported are:
index c68fe1222c16aa111e6734c6aa21432461f47c76..20a41f7de76f687d39329c2f4ea58ae30dc8fc6d 100644 (file)
@@ -643,7 +643,7 @@ static struct pci_device_id nhi_ids[] = {
        {
                .class = PCI_CLASS_SYSTEM_OTHER << 8, .class_mask = ~0,
                .vendor = PCI_VENDOR_ID_INTEL, .device = 0x156c,
-               .subvendor = 0x2222, .subdevice = 0x1111,
+               .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
        },
        { 0,}
 };
index 20932cc9c8f71681038bf5e505fec87d9c402280..b09023b071696c2a5d25e003dcff798b42235602 100644 (file)
@@ -343,8 +343,7 @@ static void n_tty_packet_mode_flush(struct tty_struct *tty)
                spin_lock_irqsave(&tty->ctrl_lock, flags);
                tty->ctrl_status |= TIOCPKT_FLUSHREAD;
                spin_unlock_irqrestore(&tty->ctrl_lock, flags);
-               if (waitqueue_active(&tty->link->read_wait))
-                       wake_up_interruptible(&tty->link->read_wait);
+               wake_up_interruptible(&tty->link->read_wait);
        }
 }
 
@@ -1382,8 +1381,7 @@ handle_newline:
                        put_tty_queue(c, ldata);
                        smp_store_release(&ldata->canon_head, ldata->read_head);
                        kill_fasync(&tty->fasync, SIGIO, POLL_IN);
-                       if (waitqueue_active(&tty->read_wait))
-                               wake_up_interruptible_poll(&tty->read_wait, POLLIN);
+                       wake_up_interruptible_poll(&tty->read_wait, POLLIN);
                        return 0;
                }
        }
@@ -1667,8 +1665,7 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp,
 
        if ((read_cnt(ldata) >= ldata->minimum_to_wake) || L_EXTPROC(tty)) {
                kill_fasync(&tty->fasync, SIGIO, POLL_IN);
-               if (waitqueue_active(&tty->read_wait))
-                       wake_up_interruptible_poll(&tty->read_wait, POLLIN);
+               wake_up_interruptible_poll(&tty->read_wait, POLLIN);
        }
 }
 
@@ -1887,10 +1884,8 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
        }
 
        /* The termios change make the tty ready for I/O */
-       if (waitqueue_active(&tty->write_wait))
-               wake_up_interruptible(&tty->write_wait);
-       if (waitqueue_active(&tty->read_wait))
-               wake_up_interruptible(&tty->read_wait);
+       wake_up_interruptible(&tty->write_wait);
+       wake_up_interruptible(&tty->read_wait);
 }
 
 /**
index 21d01a491405a2c52cd1ec02f3198fa4c6b8f10c..e508939daea3f3128a2ada1e696a5f751d212077 100644 (file)
@@ -80,10 +80,6 @@ int serial8250_tx_dma(struct uart_8250_port *p)
                return 0;
 
        dma->tx_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
-       if (dma->tx_size < p->port.fifosize) {
-               ret = -EINVAL;
-               goto err;
-       }
 
        desc = dmaengine_prep_slave_single(dma->txchan,
                                           dma->tx_addr + xmit->tail,
index 54e6c8ddef5d1361fa91170d1ac78918cf823303..0bbf34035d6a51edb267d2f53c66fc13d7b54260 100644 (file)
@@ -261,6 +261,14 @@ configured less than Maximum supported fifo bytes */
                                  UART_FCR7_64BYTE,
                .flags          = UART_CAP_FIFO,
        },
+       [PORT_RT2880] = {
+               .name           = "Palmchip BK-3103",
+               .fifo_size      = 16,
+               .tx_loadsz      = 16,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+               .rxtrig_bytes   = {1, 4, 8, 14},
+               .flags          = UART_CAP_FIFO,
+       },
 };
 
 /* Uart divisor latch read */
@@ -2910,3 +2918,5 @@ int serial8250_console_setup(struct uart_port *port, char *options, bool probe)
 }
 
 #endif /* CONFIG_SERIAL_8250_CONSOLE */
+
+MODULE_LICENSE("GPL");
index 5ca5cf3e9359cf17f9a3aaebbff028ecada3a910..538ea03bc101a2994324d2ce33b8f7b237c12c78 100644 (file)
@@ -2786,7 +2786,7 @@ static int atmel_serial_probe(struct platform_device *pdev)
        ret = atmel_init_gpios(port, &pdev->dev);
        if (ret < 0) {
                dev_err(&pdev->dev, "Failed to initialize GPIOs.");
-               goto err;
+               goto err_clear_bit;
        }
 
        ret = atmel_init_port(port, pdev);
index fe3d41cc841632134fd907b1fb7af08f0e9d6e81..d0388a071ba1d474025a74fec8cfb80f5a1ed4a0 100644 (file)
@@ -1631,12 +1631,12 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
        int locked = 1;
        int retval;
 
-       retval = clk_prepare_enable(sport->clk_per);
+       retval = clk_enable(sport->clk_per);
        if (retval)
                return;
-       retval = clk_prepare_enable(sport->clk_ipg);
+       retval = clk_enable(sport->clk_ipg);
        if (retval) {
-               clk_disable_unprepare(sport->clk_per);
+               clk_disable(sport->clk_per);
                return;
        }
 
@@ -1675,8 +1675,8 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
        if (locked)
                spin_unlock_irqrestore(&sport->port.lock, flags);
 
-       clk_disable_unprepare(sport->clk_ipg);
-       clk_disable_unprepare(sport->clk_per);
+       clk_disable(sport->clk_ipg);
+       clk_disable(sport->clk_per);
 }
 
 /*
@@ -1777,7 +1777,15 @@ imx_console_setup(struct console *co, char *options)
 
        retval = uart_set_options(&sport->port, co, baud, parity, bits, flow);
 
-       clk_disable_unprepare(sport->clk_ipg);
+       clk_disable(sport->clk_ipg);
+       if (retval) {
+               clk_unprepare(sport->clk_ipg);
+               goto error_console;
+       }
+
+       retval = clk_prepare(sport->clk_per);
+       if (retval)
+               clk_disable_unprepare(sport->clk_ipg);
 
 error_console:
        return retval;
index 5a3fa89138801ea63907ec102fbb589b36d7201c..a660ab181cca7357c59c7256303628eb8bb929a9 100644 (file)
@@ -242,7 +242,10 @@ void tty_buffer_flush(struct tty_struct *tty, struct tty_ldisc *ld)
        atomic_inc(&buf->priority);
 
        mutex_lock(&buf->lock);
-       while ((next = buf->head->next) != NULL) {
+       /* paired w/ release in __tty_buffer_request_room; ensures there are
+        * no pending memory accesses to the freed buffer
+        */
+       while ((next = smp_load_acquire(&buf->head->next)) != NULL) {
                tty_buffer_free(port, buf->head);
                buf->head = next;
        }
@@ -290,7 +293,10 @@ static int __tty_buffer_request_room(struct tty_port *port, size_t size,
                if (n != NULL) {
                        n->flags = flags;
                        buf->tail = n;
-                       b->commit = b->used;
+                       /* paired w/ acquire in flush_to_ldisc(); ensures
+                        * flush_to_ldisc() sees buffer data.
+                        */
+                       smp_store_release(&b->commit, b->used);
                        /* paired w/ acquire in flush_to_ldisc(); ensures the
                         * latest commit value can be read before the head is
                         * advanced to the next buffer
@@ -393,7 +399,10 @@ void tty_schedule_flip(struct tty_port *port)
 {
        struct tty_bufhead *buf = &port->buf;
 
-       buf->tail->commit = buf->tail->used;
+       /* paired w/ acquire in flush_to_ldisc(); ensures
+        * flush_to_ldisc() sees buffer data.
+        */
+       smp_store_release(&buf->tail->commit, buf->tail->used);
        schedule_work(&buf->work);
 }
 EXPORT_SYMBOL(tty_schedule_flip);
@@ -467,7 +476,7 @@ static void flush_to_ldisc(struct work_struct *work)
        struct tty_struct *tty;
        struct tty_ldisc *disc;
 
-       tty = port->itty;
+       tty = READ_ONCE(port->itty);
        if (tty == NULL)
                return;
 
@@ -491,7 +500,10 @@ static void flush_to_ldisc(struct work_struct *work)
                 * is advancing to the next buffer
                 */
                next = smp_load_acquire(&head->next);
-               count = head->commit - head->read;
+               /* paired w/ release in __tty_buffer_request_room() or in
+                * tty_buffer_flush(); ensures we see the committed buffer data
+                */
+               count = smp_load_acquire(&head->commit) - head->read;
                if (!count) {
                        if (next == NULL) {
                                check_other_closed(tty);
index 02785d844354be01b9774ad10e70ab398297c6da..2eefaa6e3e3a4af9a5ab2b03cf03f9e75a04ca1d 100644 (file)
@@ -2128,8 +2128,24 @@ retry_open:
        if (!noctty &&
            current->signal->leader &&
            !current->signal->tty &&
-           tty->session == NULL)
-               __proc_set_tty(tty);
+           tty->session == NULL) {
+               /*
+                * Don't let a process that only has write access to the tty
+                * obtain the privileges associated with having a tty as
+                * controlling terminal (being able to reopen it with full
+                * access through /dev/tty, being able to perform pushback).
+                * Many distributions set the group of all ttys to "tty" and
+                * grant write-only access to all terminals for setgid tty
+                * binaries, which should not imply full privileges on all ttys.
+                *
+                * This could theoretically break old code that performs open()
+                * on a write-only file descriptor. In that case, it might be
+                * necessary to also permit this if
+                * inode_permission(inode, MAY_READ) == 0.
+                */
+               if (filp->f_mode & FMODE_READ)
+                       __proc_set_tty(tty);
+       }
        spin_unlock_irq(&current->sighand->siglock);
        read_unlock(&tasklist_lock);
        tty_unlock(tty);
@@ -2418,7 +2434,7 @@ static int fionbio(struct file *file, int __user *p)
  *             Takes ->siglock() when updating signal->tty
  */
 
-static int tiocsctty(struct tty_struct *tty, int arg)
+static int tiocsctty(struct tty_struct *tty, struct file *file, int arg)
 {
        int ret = 0;
 
@@ -2452,6 +2468,13 @@ static int tiocsctty(struct tty_struct *tty, int arg)
                        goto unlock;
                }
        }
+
+       /* See the comment in tty_open(). */
+       if ((file->f_mode & FMODE_READ) == 0 && !capable(CAP_SYS_ADMIN)) {
+               ret = -EPERM;
+               goto unlock;
+       }
+
        proc_set_tty(tty);
 unlock:
        read_unlock(&tasklist_lock);
@@ -2844,7 +2867,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                no_tty();
                return 0;
        case TIOCSCTTY:
-               return tiocsctty(tty, arg);
+               return tiocsctty(tty, file, arg);
        case TIOCGPGRP:
                return tiocgpgrp(tty, real_tty, p);
        case TIOCSPGRP:
@@ -3151,13 +3174,18 @@ struct class *tty_class;
 static int tty_cdev_add(struct tty_driver *driver, dev_t dev,
                unsigned int index, unsigned int count)
 {
+       int err;
+
        /* init here, since reused cdevs cause crashes */
        driver->cdevs[index] = cdev_alloc();
        if (!driver->cdevs[index])
                return -ENOMEM;
-       cdev_init(driver->cdevs[index], &tty_fops);
+       driver->cdevs[index]->ops = &tty_fops;
        driver->cdevs[index]->owner = driver->owner;
-       return cdev_add(driver->cdevs[index], dev, count);
+       err = cdev_add(driver->cdevs[index], dev, count);
+       if (err)
+               kobject_put(&driver->cdevs[index]->kobj);
+       return err;
 }
 
 /**
index 867e9f3f385959b5add2aad6b9c831f82949c809..dcc50c878159e5aa7e3bb5e7c79051e483e655ac 100644 (file)
@@ -61,7 +61,7 @@ static const struct of_device_id ci_hdrc_imx_dt_ids[] = {
        { .compatible = "fsl,imx27-usb", .data = &imx27_usb_data},
        { .compatible = "fsl,imx6q-usb", .data = &imx6q_usb_data},
        { .compatible = "fsl,imx6sl-usb", .data = &imx6sl_usb_data},
-       { .compatible = "fsl,imx6sx-usb", .data = &imx6sl_usb_data},
+       { .compatible = "fsl,imx6sx-usb", .data = &imx6sx_usb_data},
        { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, ci_hdrc_imx_dt_ids);
index 9eae1a16cef9c7aa7f7aa8eaec602af7e75a46cd..4456d2cf80ffb6f844a94815d43b184de6b3b6f4 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_platform.h>
 #include <linux/phy/phy.h>
 #include <linux/platform_device.h>
 #include <linux/usb/chipidea.h>
@@ -30,18 +31,36 @@ static const struct ci_hdrc_platform_data ci_default_pdata = {
        .flags          = CI_HDRC_DISABLE_STREAMING,
 };
 
+static struct ci_hdrc_platform_data ci_zynq_pdata = {
+       .capoffset      = DEF_CAPOFFSET,
+};
+
+static const struct of_device_id ci_hdrc_usb2_of_match[] = {
+       { .compatible = "chipidea,usb2"},
+       { .compatible = "xlnx,zynq-usb-2.20a", .data = &ci_zynq_pdata},
+       { }
+};
+MODULE_DEVICE_TABLE(of, ci_hdrc_usb2_of_match);
+
 static int ci_hdrc_usb2_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct ci_hdrc_usb2_priv *priv;
        struct ci_hdrc_platform_data *ci_pdata = dev_get_platdata(dev);
        int ret;
+       const struct of_device_id *match;
 
        if (!ci_pdata) {
                ci_pdata = devm_kmalloc(dev, sizeof(*ci_pdata), GFP_KERNEL);
                *ci_pdata = ci_default_pdata;   /* struct copy */
        }
 
+       match = of_match_device(ci_hdrc_usb2_of_match, &pdev->dev);
+       if (match && match->data) {
+               /* struct copy */
+               *ci_pdata = *(struct ci_hdrc_platform_data *)match->data;
+       }
+
        priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
@@ -96,12 +115,6 @@ static int ci_hdrc_usb2_remove(struct platform_device *pdev)
        return 0;
 }
 
-static const struct of_device_id ci_hdrc_usb2_of_match[] = {
-       { .compatible = "chipidea,usb2" },
-       { }
-};
-MODULE_DEVICE_TABLE(of, ci_hdrc_usb2_of_match);
-
 static struct platform_driver ci_hdrc_usb2_driver = {
        .probe  = ci_hdrc_usb2_probe,
        .remove = ci_hdrc_usb2_remove,
index a637da25dda0204d4b5d991903412fbf8fe0497b..8223fe73ea85926477cf710227fc3907b5ad9ff1 100644 (file)
@@ -656,6 +656,44 @@ __acquires(hwep->lock)
        return 0;
 }
 
+static int _ep_set_halt(struct usb_ep *ep, int value, bool check_transfer)
+{
+       struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep);
+       int direction, retval = 0;
+       unsigned long flags;
+
+       if (ep == NULL || hwep->ep.desc == NULL)
+               return -EINVAL;
+
+       if (usb_endpoint_xfer_isoc(hwep->ep.desc))
+               return -EOPNOTSUPP;
+
+       spin_lock_irqsave(hwep->lock, flags);
+
+       if (value && hwep->dir == TX && check_transfer &&
+               !list_empty(&hwep->qh.queue) &&
+                       !usb_endpoint_xfer_control(hwep->ep.desc)) {
+               spin_unlock_irqrestore(hwep->lock, flags);
+               return -EAGAIN;
+       }
+
+       direction = hwep->dir;
+       do {
+               retval |= hw_ep_set_halt(hwep->ci, hwep->num, hwep->dir, value);
+
+               if (!value)
+                       hwep->wedge = 0;
+
+               if (hwep->type == USB_ENDPOINT_XFER_CONTROL)
+                       hwep->dir = (hwep->dir == TX) ? RX : TX;
+
+       } while (hwep->dir != direction);
+
+       spin_unlock_irqrestore(hwep->lock, flags);
+       return retval;
+}
+
+
 /**
  * _gadget_stop_activity: stops all USB activity, flushes & disables all endpts
  * @gadget: gadget
@@ -1051,7 +1089,7 @@ __acquires(ci->lock)
                                num += ci->hw_ep_max / 2;
 
                        spin_unlock(&ci->lock);
-                       err = usb_ep_set_halt(&ci->ci_hw_ep[num].ep);
+                       err = _ep_set_halt(&ci->ci_hw_ep[num].ep, 1, false);
                        spin_lock(&ci->lock);
                        if (!err)
                                isr_setup_status_phase(ci);
@@ -1117,8 +1155,8 @@ delegate:
 
        if (err < 0) {
                spin_unlock(&ci->lock);
-               if (usb_ep_set_halt(&hwep->ep))
-                       dev_err(ci->dev, "error: ep_set_halt\n");
+               if (_ep_set_halt(&hwep->ep, 1, false))
+                       dev_err(ci->dev, "error: _ep_set_halt\n");
                spin_lock(&ci->lock);
        }
 }
@@ -1149,9 +1187,9 @@ __acquires(ci->lock)
                                        err = isr_setup_status_phase(ci);
                                if (err < 0) {
                                        spin_unlock(&ci->lock);
-                                       if (usb_ep_set_halt(&hwep->ep))
+                                       if (_ep_set_halt(&hwep->ep, 1, false))
                                                dev_err(ci->dev,
-                                                       "error: ep_set_halt\n");
+                                               "error: _ep_set_halt\n");
                                        spin_lock(&ci->lock);
                                }
                        }
@@ -1397,41 +1435,7 @@ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req)
  */
 static int ep_set_halt(struct usb_ep *ep, int value)
 {
-       struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep);
-       int direction, retval = 0;
-       unsigned long flags;
-
-       if (ep == NULL || hwep->ep.desc == NULL)
-               return -EINVAL;
-
-       if (usb_endpoint_xfer_isoc(hwep->ep.desc))
-               return -EOPNOTSUPP;
-
-       spin_lock_irqsave(hwep->lock, flags);
-
-#ifndef STALL_IN
-       /* g_file_storage MS compliant but g_zero fails chapter 9 compliance */
-       if (value && hwep->type == USB_ENDPOINT_XFER_BULK && hwep->dir == TX &&
-           !list_empty(&hwep->qh.queue)) {
-               spin_unlock_irqrestore(hwep->lock, flags);
-               return -EAGAIN;
-       }
-#endif
-
-       direction = hwep->dir;
-       do {
-               retval |= hw_ep_set_halt(hwep->ci, hwep->num, hwep->dir, value);
-
-               if (!value)
-                       hwep->wedge = 0;
-
-               if (hwep->type == USB_ENDPOINT_XFER_CONTROL)
-                       hwep->dir = (hwep->dir == TX) ? RX : TX;
-
-       } while (hwep->dir != direction);
-
-       spin_unlock_irqrestore(hwep->lock, flags);
-       return retval;
+       return _ep_set_halt(ep, value, true);
 }
 
 /**
index b2a540b43f97c3bb8c045725fe68fed1a0601ae6..b9ddf0c1ffe5993893d5bd0d4f3ffe3f313ed435 100644 (file)
@@ -112,7 +112,7 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
                                cfgno, inum, asnum, ep->desc.bEndpointAddress);
                ep->ss_ep_comp.bmAttributes = 16;
        } else if (usb_endpoint_xfer_isoc(&ep->desc) &&
-                       desc->bmAttributes > 2) {
+                  USB_SS_MULT(desc->bmAttributes) > 3) {
                dev_warn(ddev, "Isoc endpoint has Mult of %d in "
                                "config %d interface %d altsetting %d ep %d: "
                                "setting to 3\n", desc->bmAttributes + 1,
@@ -121,7 +121,8 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
        }
 
        if (usb_endpoint_xfer_isoc(&ep->desc))
-               max_tx = (desc->bMaxBurst + 1) * (desc->bmAttributes + 1) *
+               max_tx = (desc->bMaxBurst + 1) *
+                       (USB_SS_MULT(desc->bmAttributes)) *
                        usb_endpoint_maxp(&ep->desc);
        else if (usb_endpoint_xfer_int(&ep->desc))
                max_tx = usb_endpoint_maxp(&ep->desc) *
index d85abfed84ccaa2327820f1b35cabac11422d647..f5a381945db2886a77e23a8fcf40ba9a34bb7fe7 100644 (file)
@@ -54,6 +54,13 @@ static const struct usb_device_id usb_quirk_list[] = {
        { USB_DEVICE(0x046d, 0x082d), .driver_info = USB_QUIRK_DELAY_INIT },
        { USB_DEVICE(0x046d, 0x0843), .driver_info = USB_QUIRK_DELAY_INIT },
 
+       /* Logitech ConferenceCam CC3000e */
+       { USB_DEVICE(0x046d, 0x0847), .driver_info = USB_QUIRK_DELAY_INIT },
+       { USB_DEVICE(0x046d, 0x0848), .driver_info = USB_QUIRK_DELAY_INIT },
+
+       /* Logitech PTZ Pro Camera */
+       { USB_DEVICE(0x046d, 0x0853), .driver_info = USB_QUIRK_DELAY_INIT },
+
        /* Logitech Quickcam Fusion */
        { USB_DEVICE(0x046d, 0x08c1), .driver_info = USB_QUIRK_RESET_RESUME },
 
@@ -78,6 +85,12 @@ static const struct usb_device_id usb_quirk_list[] = {
        /* Philips PSC805 audio device */
        { USB_DEVICE(0x0471, 0x0155), .driver_info = USB_QUIRK_RESET_RESUME },
 
+       /* Plantronic Audio 655 DSP */
+       { USB_DEVICE(0x047f, 0xc008), .driver_info = USB_QUIRK_RESET_RESUME },
+
+       /* Plantronic Audio 648 USB */
+       { USB_DEVICE(0x047f, 0xc013), .driver_info = USB_QUIRK_RESET_RESUME },
+
        /* Artisman Watchdog Dongle */
        { USB_DEVICE(0x04b4, 0x0526), .driver_info =
                        USB_QUIRK_CONFIG_INTF_STRINGS },
index a5a1b7c45743302b5ce9ae78bee9fead19b45de9..22e9606d8e081c3ece06c3cf52f0e735ab44207c 100644 (file)
@@ -514,8 +514,6 @@ static int dwc3_omap_probe(struct platform_device *pdev)
                goto err1;
        }
 
-       dwc3_omap_enable_irqs(omap);
-
        ret = dwc3_omap_extcon_register(omap);
        if (ret < 0)
                goto err2;
@@ -526,6 +524,8 @@ static int dwc3_omap_probe(struct platform_device *pdev)
                goto err3;
        }
 
+       dwc3_omap_enable_irqs(omap);
+
        return 0;
 
 err3:
index 0c25704dcb6ba398a98012cf0d9480c9de4f44e2..1e8bdf8178113af9db2c556488224acf6504e853 100644 (file)
@@ -2665,8 +2665,6 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc)
        int                             i;
        irqreturn_t                     ret = IRQ_NONE;
 
-       spin_lock(&dwc->lock);
-
        for (i = 0; i < dwc->num_event_buffers; i++) {
                irqreturn_t status;
 
@@ -2675,8 +2673,6 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc)
                        ret = status;
        }
 
-       spin_unlock(&dwc->lock);
-
        return ret;
 }
 
index 978435a5103875cf29890cbec24f5884ce3448a4..6399c106a3a55d2a380829af2dcc932c02193094 100644 (file)
@@ -186,6 +186,7 @@ void usb_ep_autoconfig_reset (struct usb_gadget *gadget)
 
        list_for_each_entry (ep, &gadget->ep_list, ep_list) {
                ep->claimed = false;
+               ep->driver_data = NULL;
        }
        gadget->in_epnum = 0;
        gadget->out_epnum = 0;
index fdacddb18c006c6d0cdaaf6b51ce3b962675275e..175ca93fe5e2d5159804301e99d12e6f048a47da 100644 (file)
@@ -3138,8 +3138,8 @@ static void udc_pci_remove(struct pci_dev *pdev)
        writel(AMD_BIT(UDC_DEVCFG_SOFTRESET), &dev->regs->cfg);
        if (dev->irq_registered)
                free_irq(pdev->irq, dev);
-       if (dev->regs)
-               iounmap(dev->regs);
+       if (dev->virt_addr)
+               iounmap(dev->virt_addr);
        if (dev->mem_region)
                release_mem_region(pci_resource_start(pdev, 0),
                                pci_resource_len(pdev, 0));
@@ -3226,17 +3226,13 @@ static int udc_pci_probe(
 
        /* init */
        dev = kzalloc(sizeof(struct udc), GFP_KERNEL);
-       if (!dev) {
-               retval = -ENOMEM;
-               goto finished;
-       }
+       if (!dev)
+               return -ENOMEM;
 
        /* pci setup */
        if (pci_enable_device(pdev) < 0) {
-               kfree(dev);
-               dev = NULL;
                retval = -ENODEV;
-               goto finished;
+               goto err_pcidev;
        }
        dev->active = 1;
 
@@ -3246,28 +3242,22 @@ static int udc_pci_probe(
 
        if (!request_mem_region(resource, len, name)) {
                dev_dbg(&pdev->dev, "pci device used already\n");
-               kfree(dev);
-               dev = NULL;
                retval = -EBUSY;
-               goto finished;
+               goto err_memreg;
        }
        dev->mem_region = 1;
 
        dev->virt_addr = ioremap_nocache(resource, len);
        if (dev->virt_addr == NULL) {
                dev_dbg(&pdev->dev, "start address cannot be mapped\n");
-               kfree(dev);
-               dev = NULL;
                retval = -EFAULT;
-               goto finished;
+               goto err_ioremap;
        }
 
        if (!pdev->irq) {
                dev_err(&pdev->dev, "irq not set\n");
-               kfree(dev);
-               dev = NULL;
                retval = -ENODEV;
-               goto finished;
+               goto err_irq;
        }
 
        spin_lock_init(&dev->lock);
@@ -3283,10 +3273,8 @@ static int udc_pci_probe(
 
        if (request_irq(pdev->irq, udc_irq, IRQF_SHARED, name, dev) != 0) {
                dev_dbg(&pdev->dev, "request_irq(%d) fail\n", pdev->irq);
-               kfree(dev);
-               dev = NULL;
                retval = -EBUSY;
-               goto finished;
+               goto err_irq;
        }
        dev->irq_registered = 1;
 
@@ -3314,8 +3302,17 @@ static int udc_pci_probe(
                return 0;
 
 finished:
-       if (dev)
-               udc_pci_remove(pdev);
+       udc_pci_remove(pdev);
+       return retval;
+
+err_irq:
+       iounmap(dev->virt_addr);
+err_ioremap:
+       release_mem_region(resource, len);
+err_memreg:
+       pci_disable_device(pdev);
+err_pcidev:
+       kfree(dev);
        return retval;
 }
 
index 3dfada8d60616fb89204ba2eee72d4bc6f2ef9c0..f0f2b066ac08366d353b046d3a3a193600977d1d 100644 (file)
@@ -2002,6 +2002,17 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
                ep->udc = udc;
                INIT_LIST_HEAD(&ep->queue);
 
+               if (ep->index == 0) {
+                       ep->ep.caps.type_control = true;
+               } else {
+                       ep->ep.caps.type_iso = ep->can_isoc;
+                       ep->ep.caps.type_bulk = true;
+                       ep->ep.caps.type_int = true;
+               }
+
+               ep->ep.caps.dir_in = true;
+               ep->ep.caps.dir_out = true;
+
                if (i)
                        list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
 
index 5c8f4effb62ac2ef09ae65e9fcddb707ff9d473c..ccb9c213cc9f7e5b1ba958b9451df218fe3334bc 100644 (file)
@@ -324,8 +324,7 @@ static void bdc_mem_free(struct bdc *bdc)
                                bdc->scratchpad.buff, bdc->scratchpad.sp_dma);
 
        /* Destroy the dma pools */
-       if (bdc->bd_table_pool)
-               dma_pool_destroy(bdc->bd_table_pool);
+       dma_pool_destroy(bdc->bd_table_pool);
 
        /* Free the bdc_ep array */
        kfree(bdc->bdc_ep_array);
index d1b81539d6320b3baed7c5bc9bc4cdde7440aee9..d6199507f86140b15439463f97f234aa7955d6fe 100644 (file)
@@ -159,8 +159,10 @@ static int ep_bd_list_alloc(struct bdc_ep *ep)
                bd_table->start_bd = dma_pool_alloc(bdc->bd_table_pool,
                                                        GFP_ATOMIC,
                                                        &dma);
-               if (!bd_table->start_bd)
+               if (!bd_table->start_bd) {
+                       kfree(bd_table);
                        goto fail;
+               }
 
                bd_table->dma = dma;
 
index 1379ad40d864bd42308f0c336fe931e8c757355e..27af0f008b57dd0999241c3e72919e6635fd9014 100644 (file)
@@ -1348,6 +1348,7 @@ static int transfer(struct dummy_hcd *dum_hcd, struct urb *urb,
 {
        struct dummy            *dum = dum_hcd->dum;
        struct dummy_request    *req;
+       int                     sent = 0;
 
 top:
        /* if there's no request queued, the device is NAKing; return */
@@ -1385,12 +1386,15 @@ top:
                        if (len == 0)
                                break;
 
-                       /* use an extra pass for the final short packet */
-                       if (len > ep->ep.maxpacket) {
-                               rescan = 1;
-                               len -= (len % ep->ep.maxpacket);
+                       /* send multiple of maxpacket first, then remainder */
+                       if (len >= ep->ep.maxpacket) {
+                               is_short = 0;
+                               if (len % ep->ep.maxpacket)
+                                       rescan = 1;
+                               len -= len % ep->ep.maxpacket;
+                       } else {
+                               is_short = 1;
                        }
-                       is_short = (len % ep->ep.maxpacket) != 0;
 
                        len = dummy_perform_transfer(urb, req, len);
 
@@ -1399,6 +1403,7 @@ top:
                                req->req.status = len;
                        } else {
                                limit -= len;
+                               sent += len;
                                urb->actual_length += len;
                                req->req.actual += len;
                        }
@@ -1421,7 +1426,7 @@ top:
                                        *status = -EOVERFLOW;
                                else
                                        *status = 0;
-                       } else if (!to_host) {
+                       } else {
                                *status = 0;
                                if (host_len > dev_len)
                                        req->req.status = -EOVERFLOW;
@@ -1429,15 +1434,24 @@ top:
                                        req->req.status = 0;
                        }
 
-               /* many requests terminate without a short packet */
+               /*
+                * many requests terminate without a short packet.
+                * send a zlp if demanded by flags.
+                */
                } else {
-                       if (req->req.length == req->req.actual
-                                       && !req->req.zero)
-                               req->req.status = 0;
-                       if (urb->transfer_buffer_length == urb->actual_length
-                                       && !(urb->transfer_flags
-                                               & URB_ZERO_PACKET))
-                               *status = 0;
+                       if (req->req.length == req->req.actual) {
+                               if (req->req.zero && to_host)
+                                       rescan = 1;
+                               else
+                                       req->req.status = 0;
+                       }
+                       if (urb->transfer_buffer_length == urb->actual_length) {
+                               if (urb->transfer_flags & URB_ZERO_PACKET &&
+                                   !to_host)
+                                       rescan = 1;
+                               else
+                                       *status = 0;
+                       }
                }
 
                /* device side completion --> continuable */
@@ -1460,7 +1474,7 @@ top:
                if (rescan)
                        goto top;
        }
-       return limit;
+       return sent;
 }
 
 static int periodic_bytes(struct dummy *dum, struct dummy_ep *ep)
@@ -1890,7 +1904,7 @@ restart:
                default:
 treat_control_like_bulk:
                        ep->last_io = jiffies;
-                       total = transfer(dum_hcd, urb, ep, limit, &status);
+                       total -= transfer(dum_hcd, urb, ep, limit, &status);
                        break;
                }
 
index 8aa2593c2c3633a7e9e81131f93a8c88f1ebb951..b9429bc4251161ac7407ab87168b97d31354e96f 100644 (file)
@@ -2117,8 +2117,7 @@ static int gr_remove(struct platform_device *pdev)
                return -EBUSY;
 
        gr_dfs_delete(dev);
-       if (dev->desc_pool)
-               dma_pool_destroy(dev->desc_pool);
+       dma_pool_destroy(dev->desc_pool);
        platform_set_drvdata(pdev, NULL);
 
        gr_free_request(&dev->epi[0].ep, &dev->ep0reqi->req);
index 4c489692745e0d9ee77209846ec0f63fc08e3608..dafe74eb9adeca207549ed71910d77b22ccd03b2 100644 (file)
@@ -1767,8 +1767,7 @@ static int mv_u3d_remove(struct platform_device *dev)
        usb_del_gadget_udc(&u3d->gadget);
 
        /* free memory allocated in probe */
-       if (u3d->trb_pool)
-               dma_pool_destroy(u3d->trb_pool);
+       dma_pool_destroy(u3d->trb_pool);
 
        if (u3d->ep_context)
                dma_free_coherent(&dev->dev, u3d->ep_context_size,
index 339af51df57df9532749deff77efe1fc0a7c1d7f..81b6229c780542e1a4e36888fbad329cb742b498 100644 (file)
@@ -2100,8 +2100,7 @@ static int mv_udc_remove(struct platform_device *pdev)
        }
 
        /* free memory allocated in probe */
-       if (udc->dtd_pool)
-               dma_pool_destroy(udc->dtd_pool);
+       dma_pool_destroy(udc->dtd_pool);
 
        if (udc->ep_dqh)
                dma_free_coherent(&pdev->dev, udc->ep_dqh_size,
index 9a8c936cd42c18ef72a695d45c7e4ce2e893f8b0..41f841fa6c4de6a57edb702c2875e4351a4cbff8 100644 (file)
@@ -1498,10 +1498,10 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
         * use Event Data TRBs, and we don't chain in a link TRB on short
         * transfers, we're basically dividing by 1.
         *
-        * xHCI 1.0 specification indicates that the Average TRB Length should
-        * be set to 8 for control endpoints.
+        * xHCI 1.0 and 1.1 specification indicates that the Average TRB Length
+        * should be set to 8 for control endpoints.
         */
-       if (usb_endpoint_xfer_control(&ep->desc) && xhci->hci_version == 0x100)
+       if (usb_endpoint_xfer_control(&ep->desc) && xhci->hci_version >= 0x100)
                ep_ctx->tx_info |= cpu_to_le32(AVG_TRB_LENGTH_FOR_EP(8));
        else
                ep_ctx->tx_info |=
@@ -1792,8 +1792,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
        int size;
        int i, j, num_ports;
 
-       if (timer_pending(&xhci->cmd_timer))
-               del_timer_sync(&xhci->cmd_timer);
+       del_timer_sync(&xhci->cmd_timer);
 
        /* Free the Event Ring Segment Table and the actual Event Ring */
        size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries);
@@ -2321,6 +2320,10 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
 
        INIT_LIST_HEAD(&xhci->cmd_list);
 
+       /* init command timeout timer */
+       setup_timer(&xhci->cmd_timer, xhci_handle_command_timeout,
+                   (unsigned long)xhci);
+
        page_size = readl(&xhci->op_regs->page_size);
        xhci_dbg_trace(xhci, trace_xhci_dbg_init,
                        "Supported page size register = 0x%x", page_size);
@@ -2505,10 +2508,6 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
                        "Wrote ERST address to ir_set 0.");
        xhci_print_ir_set(xhci, 0);
 
-       /* init command timeout timer */
-       setup_timer(&xhci->cmd_timer, xhci_handle_command_timeout,
-                   (unsigned long)xhci);
-
        /*
         * XXX: Might need to set the Interrupter Moderation Register to
         * something other than the default (~1ms minimum between interrupts).
index 5590eac2b22df26ea4150d7bb8a8e1eeb2406ae3..c47d3e48058659230e8d48ed342f9c163b08732d 100644 (file)
@@ -147,6 +147,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
        if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
                pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI) {
                xhci->quirks |= XHCI_SPURIOUS_REBOOT;
+               xhci->quirks |= XHCI_SPURIOUS_WAKEUP;
        }
        if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
                (pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI ||
@@ -180,51 +181,6 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
                                "QUIRK: Resetting on resume");
 }
 
-/*
- * In some Intel xHCI controllers, in order to get D3 working,
- * through a vendor specific SSIC CONFIG register at offset 0x883c,
- * SSIC PORT need to be marked as "unused" before putting xHCI
- * into D3. After D3 exit, the SSIC port need to be marked as "used".
- * Without this change, xHCI might not enter D3 state.
- * Make sure PME works on some Intel xHCI controllers by writing 1 to clear
- * the Internal PME flag bit in vendor specific PMCTRL register at offset 0x80a4
- */
-static void xhci_pme_quirk(struct usb_hcd *hcd, bool suspend)
-{
-       struct xhci_hcd *xhci = hcd_to_xhci(hcd);
-       struct pci_dev          *pdev = to_pci_dev(hcd->self.controller);
-       u32 val;
-       void __iomem *reg;
-
-       if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
-                pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI) {
-
-               reg = (void __iomem *) xhci->cap_regs + PORT2_SSIC_CONFIG_REG2;
-
-               /* Notify SSIC that SSIC profile programming is not done */
-               val = readl(reg) & ~PROG_DONE;
-               writel(val, reg);
-
-               /* Mark SSIC port as unused(suspend) or used(resume) */
-               val = readl(reg);
-               if (suspend)
-                       val |= SSIC_PORT_UNUSED;
-               else
-                       val &= ~SSIC_PORT_UNUSED;
-               writel(val, reg);
-
-               /* Notify SSIC that SSIC profile programming is done */
-               val = readl(reg) | PROG_DONE;
-               writel(val, reg);
-               readl(reg);
-       }
-
-       reg = (void __iomem *) xhci->cap_regs + 0x80a4;
-       val = readl(reg);
-       writel(val | BIT(28), reg);
-       readl(reg);
-}
-
 #ifdef CONFIG_ACPI
 static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev)
 {
@@ -345,6 +301,51 @@ static void xhci_pci_remove(struct pci_dev *dev)
 }
 
 #ifdef CONFIG_PM
+/*
+ * In some Intel xHCI controllers, in order to get D3 working,
+ * through a vendor specific SSIC CONFIG register at offset 0x883c,
+ * SSIC PORT need to be marked as "unused" before putting xHCI
+ * into D3. After D3 exit, the SSIC port need to be marked as "used".
+ * Without this change, xHCI might not enter D3 state.
+ * Make sure PME works on some Intel xHCI controllers by writing 1 to clear
+ * the Internal PME flag bit in vendor specific PMCTRL register at offset 0x80a4
+ */
+static void xhci_pme_quirk(struct usb_hcd *hcd, bool suspend)
+{
+       struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+       struct pci_dev          *pdev = to_pci_dev(hcd->self.controller);
+       u32 val;
+       void __iomem *reg;
+
+       if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
+                pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI) {
+
+               reg = (void __iomem *) xhci->cap_regs + PORT2_SSIC_CONFIG_REG2;
+
+               /* Notify SSIC that SSIC profile programming is not done */
+               val = readl(reg) & ~PROG_DONE;
+               writel(val, reg);
+
+               /* Mark SSIC port as unused(suspend) or used(resume) */
+               val = readl(reg);
+               if (suspend)
+                       val |= SSIC_PORT_UNUSED;
+               else
+                       val &= ~SSIC_PORT_UNUSED;
+               writel(val, reg);
+
+               /* Notify SSIC that SSIC profile programming is done */
+               val = readl(reg) | PROG_DONE;
+               writel(val, reg);
+               readl(reg);
+       }
+
+       reg = (void __iomem *) xhci->cap_regs + 0x80a4;
+       val = readl(reg);
+       writel(val | BIT(28), reg);
+       readl(reg);
+}
+
 static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
 {
        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
index a47a1e89708678e6d55dd6a13e4fbed229bedfe2..97ffe39972735109f1ca1f86e003fe2550e4f936 100644 (file)
@@ -302,6 +302,15 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci)
        ret = xhci_handshake(&xhci->op_regs->cmd_ring,
                        CMD_RING_RUNNING, 0, 5 * 1000 * 1000);
        if (ret < 0) {
+               /* we are about to kill xhci, give it one more chance */
+               xhci_write_64(xhci, temp_64 | CMD_RING_ABORT,
+                             &xhci->op_regs->cmd_ring);
+               udelay(1000);
+               ret = xhci_handshake(&xhci->op_regs->cmd_ring,
+                                    CMD_RING_RUNNING, 0, 3 * 1000 * 1000);
+               if (ret == 0)
+                       return 0;
+
                xhci_err(xhci, "Stopped the command ring failed, "
                                "maybe the host is dead\n");
                xhci->xhc_state |= XHCI_STATE_DYING;
@@ -2182,6 +2191,10 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
                }
        /* Fast path - was this the last TRB in the TD for this URB? */
        } else if (event_trb == td->last_trb) {
+               if (td->urb_length_set && trb_comp_code == COMP_SHORT_TX)
+                       return finish_td(xhci, td, event_trb, event, ep,
+                                        status, false);
+
                if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
                        td->urb->actual_length =
                                td->urb->transfer_buffer_length -
@@ -2233,6 +2246,12 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
                        td->urb->actual_length +=
                                TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) -
                                EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
+
+               if (trb_comp_code == COMP_SHORT_TX) {
+                       xhci_dbg(xhci, "mid bulk/intr SP, wait for last TRB event\n");
+                       td->urb_length_set = true;
+                       return 0;
+               }
        }
 
        return finish_td(xhci, td, event_trb, event, ep, status, false);
@@ -2265,6 +2284,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
        u32 trb_comp_code;
        int ret = 0;
        int td_num = 0;
+       bool handling_skipped_tds = false;
 
        slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags));
        xdev = xhci->devs[slot_id];
@@ -2401,6 +2421,10 @@ static int handle_tx_event(struct xhci_hcd *xhci,
                ep->skip = true;
                xhci_dbg(xhci, "Miss service interval error, set skip flag\n");
                goto cleanup;
+       case COMP_PING_ERR:
+               ep->skip = true;
+               xhci_dbg(xhci, "No Ping response error, Skip one Isoc TD\n");
+               goto cleanup;
        default:
                if (xhci_is_vendor_info_code(xhci, trb_comp_code)) {
                        status = 0;
@@ -2537,13 +2561,18 @@ static int handle_tx_event(struct xhci_hcd *xhci,
                                                 ep, &status);
 
 cleanup:
+
+
+               handling_skipped_tds = ep->skip &&
+                       trb_comp_code != COMP_MISSED_INT &&
+                       trb_comp_code != COMP_PING_ERR;
+
                /*
-                * Do not update event ring dequeue pointer if ep->skip is set.
-                * Will roll back to continue process missed tds.
+                * Do not update event ring dequeue pointer if we're in a loop
+                * processing missed tds.
                 */
-               if (trb_comp_code == COMP_MISSED_INT || !ep->skip) {
+               if (!handling_skipped_tds)
                        inc_deq(xhci, xhci->event_ring);
-               }
 
                if (ret) {
                        urb = td->urb;
@@ -2578,7 +2607,7 @@ cleanup:
         * Process them as short transfer until reach the td pointed by
         * the event.
         */
-       } while (ep->skip && trb_comp_code != COMP_MISSED_INT);
+       } while (handling_skipped_tds);
 
        return 0;
 }
@@ -3461,8 +3490,8 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
        if (start_cycle == 0)
                field |= 0x1;
 
-       /* xHCI 1.0 6.4.1.2.1: Transfer Type field */
-       if (xhci->hci_version == 0x100) {
+       /* xHCI 1.0/1.1 6.4.1.2.1: Transfer Type field */
+       if (xhci->hci_version >= 0x100) {
                if (urb->transfer_buffer_length > 0) {
                        if (setup->bRequestType & USB_DIR_IN)
                                field |= TRB_TX_TYPE(TRB_DATA_IN);
index 6b0f4a47e4021d83e01fb76a0a1aa18d6b3ca793..9957bd96d4bc383dd9f27a557af157c8d7343fc8 100644 (file)
@@ -146,7 +146,8 @@ static int xhci_start(struct xhci_hcd *xhci)
                                "waited %u microseconds.\n",
                                XHCI_MAX_HALT_USEC);
        if (!ret)
-               xhci->xhc_state &= ~XHCI_STATE_HALTED;
+               xhci->xhc_state &= ~(XHCI_STATE_HALTED | XHCI_STATE_DYING);
+
        return ret;
 }
 
@@ -654,15 +655,6 @@ int xhci_run(struct usb_hcd *hcd)
 }
 EXPORT_SYMBOL_GPL(xhci_run);
 
-static void xhci_only_stop_hcd(struct usb_hcd *hcd)
-{
-       struct xhci_hcd *xhci = hcd_to_xhci(hcd);
-
-       spin_lock_irq(&xhci->lock);
-       xhci_halt(xhci);
-       spin_unlock_irq(&xhci->lock);
-}
-
 /*
  * Stop xHCI driver.
  *
@@ -677,12 +669,14 @@ void xhci_stop(struct usb_hcd *hcd)
        u32 temp;
        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
 
-       if (!usb_hcd_is_primary_hcd(hcd)) {
-               xhci_only_stop_hcd(xhci->shared_hcd);
+       if (xhci->xhc_state & XHCI_STATE_HALTED)
                return;
-       }
 
+       mutex_lock(&xhci->mutex);
        spin_lock_irq(&xhci->lock);
+       xhci->xhc_state |= XHCI_STATE_HALTED;
+       xhci->cmd_ring_state = CMD_RING_STATE_STOPPED;
+
        /* Make sure the xHC is halted for a USB3 roothub
         * (xhci_stop() could be called as part of failed init).
         */
@@ -717,6 +711,7 @@ void xhci_stop(struct usb_hcd *hcd)
        xhci_dbg_trace(xhci, trace_xhci_dbg_init,
                        "xhci_stop completed - status = %x",
                        readl(&xhci->op_regs->status));
+       mutex_unlock(&xhci->mutex);
 }
 
 /*
@@ -3793,6 +3788,9 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
 
        mutex_lock(&xhci->mutex);
 
+       if (xhci->xhc_state)    /* dying or halted */
+               goto out;
+
        if (!udev->slot_id) {
                xhci_dbg_trace(xhci, trace_xhci_dbg_address,
                                "Bad Slot ID %d", udev->slot_id);
index 3ad5d19e4d04ede93fb8bc34debdbb9fcf2f4704..23c794813e6a923bff5b0a3719abbea860ee416d 100644 (file)
@@ -472,7 +472,7 @@ static int chaoskey_rng_read(struct hwrng *rng, void *data,
        if (this_time > max)
                this_time = max;
 
-       memcpy(data, dev->buf, this_time);
+       memcpy(data, dev->buf + dev->used, this_time);
 
        dev->used += this_time;
 
index 514a6cdaeff6117e03e040896089d777d0af0019..4a518ff123106b0931082bd51f0705c8e8ca0bb7 100644 (file)
@@ -1051,6 +1051,7 @@ void musb_start(struct musb *musb)
         * (c) peripheral initiates, using SRP
         */
        if (musb->port_mode != MUSB_PORT_MODE_HOST &&
+                       musb->xceiv->otg->state != OTG_STATE_A_WAIT_BCON &&
                        (devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) {
                musb->is_active = 1;
        } else {
@@ -2448,6 +2449,9 @@ static int musb_suspend(struct device *dev)
        struct musb     *musb = dev_to_musb(dev);
        unsigned long   flags;
 
+       musb_platform_disable(musb);
+       musb_generic_disable(musb);
+
        spin_lock_irqsave(&musb->lock, flags);
 
        if (is_peripheral_active(musb)) {
@@ -2501,6 +2505,9 @@ static int musb_resume(struct device *dev)
        pm_runtime_disable(dev);
        pm_runtime_set_active(dev);
        pm_runtime_enable(dev);
+
+       musb_start(musb);
+
        return 0;
 }
 
index d07cafb7d5f5a1d6c992d184dff22cd53b48b3de..e499b862a946f16ff8a8c7fc4694c4da93fd4c74 100644 (file)
@@ -551,6 +551,9 @@ static int cppi41_dma_channel_abort(struct dma_channel *channel)
        } else {
                cppi41_set_autoreq_mode(cppi41_channel, EP_MODE_AUTOREQ_NONE);
 
+               /* delay to drain to cppi dma pipeline for isoch */
+               udelay(250);
+
                csr = musb_readw(epio, MUSB_RXCSR);
                csr &= ~(MUSB_RXCSR_H_REQPKT | MUSB_RXCSR_DMAENAB);
                musb_writew(epio, MUSB_RXCSR, csr);
index a0cfead6150f13a58fc83d50fa0a0559b8bc8908..84512d1d5eee1583fb057d6f45613f25293dc25b 100644 (file)
@@ -225,8 +225,11 @@ static void dsps_musb_enable(struct musb *musb)
 
        dsps_writel(reg_base, wrp->epintr_set, epmask);
        dsps_writel(reg_base, wrp->coreintr_set, coremask);
-       /* start polling for ID change. */
-       mod_timer(&glue->timer, jiffies + msecs_to_jiffies(wrp->poll_timeout));
+       /* start polling for ID change in dual-role idle mode */
+       if (musb->xceiv->otg->state == OTG_STATE_B_IDLE &&
+                       musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE)
+               mod_timer(&glue->timer, jiffies +
+                               msecs_to_jiffies(wrp->poll_timeout));
        dsps_musb_try_idle(musb, 0);
 }
 
index 70f2b8a2e6cfe5d62d6509c507670aee8c981dd7..1bd9232ff76fcb774e6b1e9e1fb8acdb62ef267d 100644 (file)
@@ -391,9 +391,20 @@ static int omap2430_musb_init(struct musb *musb)
        }
        musb->isr = omap2430_musb_interrupt;
 
+       /*
+        * Enable runtime PM for musb parent (this driver). We can't
+        * do it earlier as struct musb is not yet allocated and we
+        * need to touch the musb registers for runtime PM.
+        */
+       pm_runtime_enable(glue->dev);
+       status = pm_runtime_get_sync(glue->dev);
+       if (status < 0)
+               goto err1;
+
        status = pm_runtime_get_sync(dev);
        if (status < 0) {
                dev_err(dev, "pm_runtime_get_sync FAILED %d\n", status);
+               pm_runtime_put_sync(glue->dev);
                goto err1;
        }
 
@@ -426,6 +437,7 @@ static int omap2430_musb_init(struct musb *musb)
        phy_power_on(musb->phy);
 
        pm_runtime_put_noidle(musb->controller);
+       pm_runtime_put_noidle(glue->dev);
        return 0;
 
 err1:
@@ -626,7 +638,11 @@ static int omap2430_probe(struct platform_device *pdev)
                goto err2;
        }
 
-       pm_runtime_enable(&pdev->dev);
+       /*
+        * Note that we cannot enable PM runtime yet for this
+        * driver as we need struct musb initialized first.
+        * See omap2430_musb_init above.
+        */
 
        ret = platform_device_add(musb);
        if (ret) {
@@ -675,11 +691,12 @@ static int omap2430_runtime_resume(struct device *dev)
        struct omap2430_glue            *glue = dev_get_drvdata(dev);
        struct musb                     *musb = glue_to_musb(glue);
 
-       if (musb) {
-               omap2430_low_level_init(musb);
-               musb_writel(musb->mregs, OTG_INTERFSEL,
-                               musb->context.otg_interfsel);
-       }
+       if (!musb)
+               return -EPROBE_DEFER;
+
+       omap2430_low_level_init(musb);
+       musb_writel(musb->mregs, OTG_INTERFSEL,
+                   musb->context.otg_interfsel);
 
        return 0;
 }
index 39168fe9b406b2aba30791b2af29311b004a468d..b2685e75a6835fe2b4615b3f86f7aef378fedcae 100644 (file)
@@ -379,6 +379,8 @@ static const struct of_device_id ux500_match[] = {
         {}
 };
 
+MODULE_DEVICE_TABLE(of, ux500_match);
+
 static struct platform_driver ux500_driver = {
        .probe          = ux500_probe,
        .remove         = ux500_remove,
index 7d3beee2a587d84e60ecffab4b4703dee4cd6976..173132416170108b6a156568f53f3c51224a86c2 100644 (file)
@@ -155,7 +155,7 @@ config USB_MSM_OTG
 config USB_QCOM_8X16_PHY
        tristate "Qualcomm APQ8016/MSM8916 on-chip USB PHY controller support"
        depends on ARCH_QCOM || COMPILE_TEST
-       depends on RESET_CONTROLLER
+       depends on RESET_CONTROLLER && EXTCON
        select USB_PHY
        select USB_ULPI_VIEWPORT
        help
index ec6ecd03269cc90a3aa113e8070cfba14c8aa6c3..5320cb8642cb5fb8edec2147da2d72c8da619167 100644 (file)
@@ -232,7 +232,8 @@ int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_generic *nop,
                clk_rate = pdata->clk_rate;
                needs_vcc = pdata->needs_vcc;
                if (gpio_is_valid(pdata->gpio_reset)) {
-                       err = devm_gpio_request_one(dev, pdata->gpio_reset, 0,
+                       err = devm_gpio_request_one(dev, pdata->gpio_reset,
+                                                   GPIOF_ACTIVE_LOW,
                                                    dev_name(dev));
                        if (!err)
                                nop->gpiod_reset =
index 8a55b37d1a024687f6be8078ef4f54f60cdc5111..db68156568e6e7bc209eaf942eaa9c51bd4e15ad 100644 (file)
@@ -31,6 +31,7 @@ static const struct i2c_device_id isp1301_id[] = {
        { "isp1301", 0 },
        { }
 };
+MODULE_DEVICE_TABLE(i2c, isp1301_id);
 
 static struct i2c_client *isp1301_i2c_client;
 
index 7b98e1d9194cb3571452c7143603f4e9d9966244..d82fa36c346503985867cc55b0e40dfd724ebf12 100644 (file)
@@ -476,6 +476,11 @@ static const struct of_device_id usbhs_of_match[] = {
                .compatible = "renesas,usbhs-r8a7794",
                .data = (void *)USBHS_TYPE_RCAR_GEN2,
        },
+       {
+               /* Gen3 is compatible with Gen2 */
+               .compatible = "renesas,usbhs-r8a7795",
+               .data = (void *)USBHS_TYPE_RCAR_GEN2,
+       },
        { },
 };
 MODULE_DEVICE_TABLE(of, usbhs_of_match);
@@ -493,7 +498,7 @@ static struct renesas_usbhs_platform_info *usbhs_parse_dt(struct device *dev)
                return NULL;
 
        dparam = &info->driver_param;
-       dparam->type = of_id ? (u32)of_id->data : 0;
+       dparam->type = of_id ? (uintptr_t)of_id->data : 0;
        if (!of_property_read_u32(dev->of_node, "renesas,buswait", &tmp))
                dparam->buswait_bwait = tmp;
        gpio = of_get_named_gpio_flags(dev->of_node, "renesas,enable-gpio", 0,
index 6d1941a2396a7c76dc8a9a4d905bb1850c63282d..6956c4f6221614a79a09429c6b9f541dc54baa5e 100644 (file)
@@ -278,6 +278,10 @@ static void option_instat_callback(struct urb *urb);
 #define ZTE_PRODUCT_MF622                      0x0001
 #define ZTE_PRODUCT_MF628                      0x0015
 #define ZTE_PRODUCT_MF626                      0x0031
+#define ZTE_PRODUCT_ZM8620_X                   0x0396
+#define ZTE_PRODUCT_ME3620_MBIM                        0x0426
+#define ZTE_PRODUCT_ME3620_X                   0x1432
+#define ZTE_PRODUCT_ME3620_L                   0x1433
 #define ZTE_PRODUCT_AC2726                     0xfff1
 #define ZTE_PRODUCT_MG880                      0xfffd
 #define ZTE_PRODUCT_CDMA_TECH                  0xfffe
@@ -544,6 +548,18 @@ static const struct option_blacklist_info zte_mc2716_z_blacklist = {
        .sendsetup = BIT(1) | BIT(2) | BIT(3),
 };
 
+static const struct option_blacklist_info zte_me3620_mbim_blacklist = {
+       .reserved = BIT(2) | BIT(3) | BIT(4),
+};
+
+static const struct option_blacklist_info zte_me3620_xl_blacklist = {
+       .reserved = BIT(3) | BIT(4) | BIT(5),
+};
+
+static const struct option_blacklist_info zte_zm8620_x_blacklist = {
+       .reserved = BIT(3) | BIT(4) | BIT(5),
+};
+
 static const struct option_blacklist_info huawei_cdc12_blacklist = {
        .reserved = BIT(1) | BIT(2),
 };
@@ -1591,6 +1607,14 @@ static const struct usb_device_id option_ids[] = {
         .driver_info = (kernel_ulong_t)&zte_ad3812_z_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2716, 0xff, 0xff, 0xff),
         .driver_info = (kernel_ulong_t)&zte_mc2716_z_blacklist },
+       { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_ME3620_L),
+        .driver_info = (kernel_ulong_t)&zte_me3620_xl_blacklist },
+       { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_ME3620_MBIM),
+        .driver_info = (kernel_ulong_t)&zte_me3620_mbim_blacklist },
+       { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_ME3620_X),
+        .driver_info = (kernel_ulong_t)&zte_me3620_xl_blacklist },
+       { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_ZM8620_X),
+        .driver_info = (kernel_ulong_t)&zte_zm8620_x_blacklist },
        { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x01) },
        { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x05) },
        { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x86, 0x10) },
index 6c3734d2b45a7a9ca24557a586ba10135b7cadb3..d3ea90bef84d98a67f110f6040ca70ec12b7a5fb 100644 (file)
@@ -80,6 +80,8 @@ static int  whiteheat_firmware_download(struct usb_serial *serial,
 static int  whiteheat_firmware_attach(struct usb_serial *serial);
 
 /* function prototypes for the Connect Tech WhiteHEAT serial converter */
+static int whiteheat_probe(struct usb_serial *serial,
+                               const struct usb_device_id *id);
 static int  whiteheat_attach(struct usb_serial *serial);
 static void whiteheat_release(struct usb_serial *serial);
 static int  whiteheat_port_probe(struct usb_serial_port *port);
@@ -116,6 +118,7 @@ static struct usb_serial_driver whiteheat_device = {
        .description =          "Connect Tech - WhiteHEAT",
        .id_table =             id_table_std,
        .num_ports =            4,
+       .probe =                whiteheat_probe,
        .attach =               whiteheat_attach,
        .release =              whiteheat_release,
        .port_probe =           whiteheat_port_probe,
@@ -217,6 +220,34 @@ static int whiteheat_firmware_attach(struct usb_serial *serial)
 /*****************************************************************************
  * Connect Tech's White Heat serial driver functions
  *****************************************************************************/
+
+static int whiteheat_probe(struct usb_serial *serial,
+                               const struct usb_device_id *id)
+{
+       struct usb_host_interface *iface_desc;
+       struct usb_endpoint_descriptor *endpoint;
+       size_t num_bulk_in = 0;
+       size_t num_bulk_out = 0;
+       size_t min_num_bulk;
+       unsigned int i;
+
+       iface_desc = serial->interface->cur_altsetting;
+
+       for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
+               endpoint = &iface_desc->endpoint[i].desc;
+               if (usb_endpoint_is_bulk_in(endpoint))
+                       ++num_bulk_in;
+               if (usb_endpoint_is_bulk_out(endpoint))
+                       ++num_bulk_out;
+       }
+
+       min_num_bulk = COMMAND_PORT + 1;
+       if (num_bulk_in < min_num_bulk || num_bulk_out < min_num_bulk)
+               return -ENODEV;
+
+       return 0;
+}
+
 static int whiteheat_attach(struct usb_serial *serial)
 {
        struct usb_serial_port *command_port;
index 7d137a43cc86842ed98bc27e63d6dfcb2042f177..9eda69e406787a55a347370328cdf07d5375dc0a 100644 (file)
@@ -61,8 +61,7 @@ MODULE_PARM_DESC(experimental_zcopytx, "Enable Zero Copy TX;"
 enum {
        VHOST_NET_FEATURES = VHOST_FEATURES |
                         (1ULL << VHOST_NET_F_VIRTIO_NET_HDR) |
-                        (1ULL << VIRTIO_NET_F_MRG_RXBUF) |
-                        (1ULL << VIRTIO_F_VERSION_1),
+                        (1ULL << VIRTIO_NET_F_MRG_RXBUF)
 };
 
 enum {
index f114a9dbb48f0ea59718da7fe59a02180da07821..e25a23692822c16ce26f7a2b9b9f7f96153a6563 100644 (file)
@@ -166,9 +166,7 @@ enum {
 /* Note: can't set VIRTIO_F_VERSION_1 yet, since that implies ANY_LAYOUT. */
 enum {
        VHOST_SCSI_FEATURES = VHOST_FEATURES | (1ULL << VIRTIO_SCSI_F_HOTPLUG) |
-                                              (1ULL << VIRTIO_SCSI_F_T10_PI) |
-                                              (1ULL << VIRTIO_F_ANY_LAYOUT) |
-                                              (1ULL << VIRTIO_F_VERSION_1)
+                                              (1ULL << VIRTIO_SCSI_F_T10_PI)
 };
 
 #define VHOST_SCSI_MAX_TARGET  256
index d9c501eaa6c3362b7ea89cdb39d33334f435af47..f2882ac98726447980dda9d1d7c916161b22eac1 100644 (file)
@@ -277,10 +277,13 @@ static long vhost_test_ioctl(struct file *f, unsigned int ioctl,
                        return -EFAULT;
                return 0;
        case VHOST_SET_FEATURES:
+               printk(KERN_ERR "1\n");
                if (copy_from_user(&features, featurep, sizeof features))
                        return -EFAULT;
+               printk(KERN_ERR "2\n");
                if (features & ~VHOST_FEATURES)
                        return -EOPNOTSUPP;
+               printk(KERN_ERR "3\n");
                return vhost_test_set_features(n, features);
        case VHOST_RESET_OWNER:
                return vhost_test_reset_owner(n);
index ce6f6da4b09f988bc4ae15268912335fcd1bab18..d3f767448a72c75f468afe6b922e9306c35e5011 100644 (file)
@@ -173,7 +173,9 @@ enum {
        VHOST_FEATURES = (1ULL << VIRTIO_F_NOTIFY_ON_EMPTY) |
                         (1ULL << VIRTIO_RING_F_INDIRECT_DESC) |
                         (1ULL << VIRTIO_RING_F_EVENT_IDX) |
-                        (1ULL << VHOST_F_LOG_ALL),
+                        (1ULL << VHOST_F_LOG_ALL) |
+                        (1ULL << VIRTIO_F_ANY_LAYOUT) |
+                        (1ULL << VIRTIO_F_VERSION_1)
 };
 
 static inline bool vhost_has_feature(struct vhost_virtqueue *vq, int bit)
@@ -181,10 +183,17 @@ static inline bool vhost_has_feature(struct vhost_virtqueue *vq, int bit)
        return vq->acked_features & (1ULL << bit);
 }
 
+#ifdef CONFIG_VHOST_CROSS_ENDIAN_LEGACY
 static inline bool vhost_is_little_endian(struct vhost_virtqueue *vq)
 {
        return vq->is_le;
 }
+#else
+static inline bool vhost_is_little_endian(struct vhost_virtqueue *vq)
+{
+       return virtio_legacy_is_little_endian() || vq->is_le;
+}
+#endif
 
 /* Memory accessors */
 static inline u16 vhost16_to_cpu(struct vhost_virtqueue *vq, __virtio16 val)
index 1aaf89300621abc811f57f549c25b9a540a21d99..92f394927f241bef338a293170e4a09b9f45c647 100644 (file)
@@ -1093,6 +1093,7 @@ static void fbcon_init(struct vc_data *vc, int init)
                con_copy_unimap(vc, svc);
 
        ops = info->fbcon_par;
+       ops->cur_blink_jiffies = msecs_to_jiffies(vc->vc_cur_blink_ms);
        p->con_rotate = initial_rotation;
        set_blitting_type(vc, info);
 
index 0e5fde1d3ffbe5a152035f33063afa98bf84f33e..9f9a7bef1ff6d46d80fe8cb6dcfeea5a3e26729d 100644 (file)
@@ -752,7 +752,7 @@ static ssize_t broadsheet_loadstore_waveform(struct device *dev,
        if ((fw_entry->size < 8*1024) || (fw_entry->size > 64*1024)) {
                dev_err(dev, "Invalid waveform\n");
                err = -EINVAL;
-               goto err_failed;
+               goto err_fw;
        }
 
        mutex_lock(&(par->io_lock));
@@ -762,13 +762,15 @@ static ssize_t broadsheet_loadstore_waveform(struct device *dev,
        mutex_unlock(&(par->io_lock));
        if (err < 0) {
                dev_err(dev, "Failed to store broadsheet waveform\n");
-               goto err_failed;
+               goto err_fw;
        }
 
        dev_info(dev, "Stored broadsheet waveform, size %zd\n", fw_entry->size);
 
-       return len;
+       err = len;
 
+err_fw:
+       release_firmware(fw_entry);
 err_failed:
        return err;
 }
index 7fa2e6f9e322d1e2223116474800b515684abfc2..b335c1ae8625106efff818d696ebad532ade7f17 100644 (file)
@@ -1628,9 +1628,16 @@ static int fsl_diu_suspend(struct platform_device *ofdev, pm_message_t state)
 static int fsl_diu_resume(struct platform_device *ofdev)
 {
        struct fsl_diu_data *data;
+       unsigned int i;
 
        data = dev_get_drvdata(&ofdev->dev);
-       enable_lcdc(data->fsl_diu_info);
+
+       fsl_diu_enable_interrupts(data);
+       update_lcdc(data->fsl_diu_info);
+       for (i = 0; i < NUM_AOIS; i++) {
+               if (data->mfb[i].count)
+                       fsl_diu_enable_panel(&data->fsl_diu_info[i]);
+       }
 
        return 0;
 }
index 9b8bebdf8f86e1209f0ca2f6f9779e8c64fa2e43..f9ec5c0484fabbd8d6f2cc5b5e5897c003e07b10 100644 (file)
@@ -831,6 +831,7 @@ static struct of_device_id of_platform_mb862xx_tbl[] = {
        { .compatible = "fujitsu,coral", },
        { /* end */ }
 };
+MODULE_DEVICE_TABLE(of, of_platform_mb862xx_tbl);
 
 static struct platform_driver of_platform_mb862xxfb_driver = {
        .driver = {
index a8ce920fa797d335d2dbfbbc1c9d8f93a4378959..d811e6dcaef727588cdc65695673a4f7144f0f30 100644 (file)
@@ -294,7 +294,7 @@ static int dvic_probe_of(struct platform_device *pdev)
 
        adapter_node = of_parse_phandle(node, "ddc-i2c-bus", 0);
        if (adapter_node) {
-               adapter = of_find_i2c_adapter_by_node(adapter_node);
+               adapter = of_get_i2c_adapter_by_node(adapter_node);
                if (adapter == NULL) {
                        dev_err(&pdev->dev, "failed to parse ddc-i2c-bus\n");
                        omap_dss_put_device(ddata->in);
index 90cbc4c3406c719909f3495cb97533face292d3c..c581231c74a53bb837dcc24da190202ed56cb648 100644 (file)
@@ -898,6 +898,7 @@ static const struct of_device_id acx565akm_of_match[] = {
        { .compatible = "omapdss,sony,acx565akm", },
        {},
 };
+MODULE_DEVICE_TABLE(of, acx565akm_of_match);
 
 static struct spi_driver acx565akm_driver = {
        .driver = {
index 7ed9a227f5eaf006ed5c2a9759ee9db299d114e3..01b43e9ce941acb8751c0c2e8294e19db7ce927c 100644 (file)
@@ -226,7 +226,7 @@ static void blade_image_blit(struct tridentfb_par *par, const char *data,
        writemmr(par, DST1, point(x, y));
        writemmr(par, DST2, point(x + w - 1, y + h - 1));
 
-       memcpy(par->io_virt + 0x10000, data, 4 * size);
+       iowrite32_rep(par->io_virt + 0x10000, data, size);
 }
 
 static void blade_copy_rect(struct tridentfb_par *par,
@@ -673,8 +673,14 @@ static int get_nativex(struct tridentfb_par *par)
 static inline void set_lwidth(struct tridentfb_par *par, int width)
 {
        write3X4(par, VGA_CRTC_OFFSET, width & 0xFF);
-       write3X4(par, AddColReg,
-                (read3X4(par, AddColReg) & 0xCF) | ((width & 0x300) >> 4));
+       /* chips older than TGUI9660 have only 1 width bit in AddColReg */
+       /* touching the other one breaks I2C/DDC */
+       if (par->chip_id == TGUI9440 || par->chip_id == CYBER9320)
+               write3X4(par, AddColReg,
+                    (read3X4(par, AddColReg) & 0xEF) | ((width & 0x100) >> 4));
+       else
+               write3X4(par, AddColReg,
+                    (read3X4(par, AddColReg) & 0xCF) | ((width & 0x300) >> 4));
 }
 
 /* For resolutions smaller than FP resolution stretch */
index 32d8275e4c88485b2b522f56733e90ba614fc7b2..8a1076beecd33aa29891849f5feaa36b42027036 100644 (file)
@@ -210,6 +210,7 @@ struct display_timings *of_get_display_timings(struct device_node *np)
                         */
                        pr_err("%s: error in timing %d\n",
                                of_node_full_name(np), disp->num_timings + 1);
+                       kfree(dt);
                        goto timingfail;
                }
 
index c68edc16aa54c5e65347588e32c883ffdaf71f63..79e1aa1b0959f1ed8b2e2404fc3a044683c68f0d 100644 (file)
@@ -817,8 +817,9 @@ config ITCO_WDT
        tristate "Intel TCO Timer/Watchdog"
        depends on (X86 || IA64) && PCI
        select WATCHDOG_CORE
+       depends on I2C || I2C=n
        select LPC_ICH if !EXPERT
-       select I2C_I801 if !EXPERT
+       select I2C_I801 if !EXPERT && I2C
        ---help---
          Hardware driver for the intel TCO timer based watchdog devices.
          These drivers are included in the Intel 82801 I/O Controller
index 66c3e656a616619e02c8c523f19913e3274459ff..8a5ce5b5a0b6f9cc684382ddfaa6ed96b4dadb7d 100644 (file)
 #define PM_RSTC_WRCFG_FULL_RESET       0x00000020
 #define PM_RSTC_RESET                  0x00000102
 
+/*
+ * The Raspberry Pi firmware uses the RSTS register to know which partiton
+ * to boot from. The partiton value is spread into bits 0, 2, 4, 6, 8, 10.
+ * Partiton 63 is a special partition used by the firmware to indicate halt.
+ */
+#define PM_RSTS_RASPBERRYPI_HALT       0x555
+
 #define SECS_TO_WDOG_TICKS(x) ((x) << 16)
 #define WDOG_TICKS_TO_SECS(x) ((x) >> 16)
 
@@ -151,8 +158,7 @@ static void bcm2835_power_off(void)
         * hard reset.
         */
        val = readl_relaxed(wdt->base + PM_RSTS);
-       val &= PM_RSTC_WRCFG_CLR;
-       val |= PM_PASSWORD | PM_RSTS_HADWRH_SET;
+       val |= PM_PASSWORD | PM_RSTS_RASPBERRYPI_HALT;
        writel_relaxed(val, wdt->base + PM_RSTS);
 
        /* Continue with normal reset mechanism */
index cc1bdfc2ff71c31b65dc455c382fb3455815fc2a..006e2348022cbc7015831819fa0f2ae0f689ebfc 100644 (file)
@@ -303,6 +303,7 @@ static const struct of_device_id gef_wdt_ids[] = {
        },
        {},
 };
+MODULE_DEVICE_TABLE(of, gef_wdt_ids);
 
 static struct platform_driver gef_wdt_driver = {
        .driver = {
index 69013007dc4701826518c0babd6d94d258719892..098fa9c34d6d8232b86ed51c2e2f7bea9a50c982 100644 (file)
@@ -253,6 +253,7 @@ static const struct of_device_id a21_wdt_ids[] = {
        { .compatible = "men,a021-wdt" },
        { },
 };
+MODULE_DEVICE_TABLE(of, a21_wdt_ids);
 
 static struct platform_driver a21_wdt_driver = {
        .probe = a21_wdt_probe,
index 2789da2c05156d02931779cd21322a24e5f133e2..60b0605bd7e60eb7ed1f8d67f4b01022a70997b3 100644 (file)
@@ -168,6 +168,7 @@ static const struct of_device_id moxart_watchdog_match[] = {
        { .compatible = "moxa,moxart-watchdog" },
        { },
 };
+MODULE_DEVICE_TABLE(of, moxart_watchdog_match);
 
 static struct platform_driver moxart_wdt_driver = {
        .probe      = moxart_wdt_probe,
index 22ea424ee741ea1a967676298e7877332fc324b2..073bb57adab10ce14e55205eddf0e3de5862be1d 100644 (file)
@@ -1242,6 +1242,13 @@ 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);
+                       /*
+                        * If the partition is not aligned on a page
+                        * boundary, we can't do dax I/O to it.
+                        */
+                       if ((bdev->bd_part->start_sect % (PAGE_SIZE / 512)) ||
+                           (bdev->bd_part->nr_sects % (PAGE_SIZE / 512)))
+                               bdev->bd_inode->i_flags &= ~S_DAX;
                }
        } else {
                if (bdev->bd_contains == bdev) {
index ecbc63d3143e78d53a9ab0e3dd2091686e51d620..9a2ec79e8cfb6c4ad26a5578e39f62f8fa80226b 100644 (file)
@@ -1828,7 +1828,6 @@ static int iterate_inode_extrefs(u64 inum, struct btrfs_root *fs_root,
        int found = 0;
        struct extent_buffer *eb;
        struct btrfs_inode_extref *extref;
-       struct extent_buffer *leaf;
        u32 item_size;
        u32 cur_offset;
        unsigned long ptr;
@@ -1856,9 +1855,8 @@ static int iterate_inode_extrefs(u64 inum, struct btrfs_root *fs_root,
                btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK);
                btrfs_release_path(path);
 
-               leaf = path->nodes[0];
-               item_size = btrfs_item_size_nr(leaf, slot);
-               ptr = btrfs_item_ptr_offset(leaf, slot);
+               item_size = btrfs_item_size_nr(eb, slot);
+               ptr = btrfs_item_ptr_offset(eb, slot);
                cur_offset = 0;
 
                while (cur_offset < item_size) {
@@ -1872,7 +1870,7 @@ static int iterate_inode_extrefs(u64 inum, struct btrfs_root *fs_root,
                        if (ret)
                                break;
 
-                       cur_offset += btrfs_inode_extref_name_len(leaf, extref);
+                       cur_offset += btrfs_inode_extref_name_len(eb, extref);
                        cur_offset += sizeof(*extref);
                }
                btrfs_tree_read_unlock_blocking(eb);
index 81220b2203c61f1033bc5a4a0666f9b7b96f08df..0ef5cc13fae26f8899cad7ed30b59344c79120d4 100644 (file)
@@ -44,8 +44,6 @@
 #define BTRFS_INODE_IN_DELALLOC_LIST           9
 #define BTRFS_INODE_READDIO_NEED_LOCK          10
 #define BTRFS_INODE_HAS_PROPS                  11
-/* DIO is ready to submit */
-#define BTRFS_INODE_DIO_READY                  12
 /*
  * The following 3 bits are meant only for the btree inode.
  * When any of them is set, it means an error happened while writing an
index 0d98aee34fee8f716771e46a70cbee478ac27e2d..1e60d00d4ea7c42104614ede9e203a1f56e6408a 100644 (file)
@@ -2847,6 +2847,8 @@ int open_ctree(struct super_block *sb,
            !extent_buffer_uptodate(chunk_root->node)) {
                printk(KERN_ERR "BTRFS: failed to read chunk root on %s\n",
                       sb->s_id);
+               if (!IS_ERR(chunk_root->node))
+                       free_extent_buffer(chunk_root->node);
                chunk_root->node = NULL;
                goto fail_tree_roots;
        }
@@ -2885,6 +2887,8 @@ retry_root_backup:
            !extent_buffer_uptodate(tree_root->node)) {
                printk(KERN_WARNING "BTRFS: failed to read tree root on %s\n",
                       sb->s_id);
+               if (!IS_ERR(tree_root->node))
+                       free_extent_buffer(tree_root->node);
                tree_root->node = NULL;
                goto recovery_tree_root;
        }
@@ -3765,9 +3769,7 @@ void close_ctree(struct btrfs_root *root)
                 * block groups queued for removal, the deletion will be
                 * skipped when we quit the cleaner thread.
                 */
-               mutex_lock(&root->fs_info->cleaner_mutex);
                btrfs_delete_unused_bgs(root->fs_info);
-               mutex_unlock(&root->fs_info->cleaner_mutex);
 
                ret = btrfs_commit_super(root);
                if (ret)
index 8d052209f473be1d0959b6e65bded71b92c05584..2513a7f533342c827c5c5e1150de6a3d196879ac 100644 (file)
@@ -112,11 +112,11 @@ static struct dentry *btrfs_fh_to_parent(struct super_block *sb, struct fid *fh,
        u32 generation;
 
        if (fh_type == FILEID_BTRFS_WITH_PARENT) {
-               if (fh_len !=  BTRFS_FID_SIZE_CONNECTABLE)
+               if (fh_len <  BTRFS_FID_SIZE_CONNECTABLE)
                        return NULL;
                root_objectid = fid->root_objectid;
        } else if (fh_type == FILEID_BTRFS_WITH_PARENT_ROOT) {
-               if (fh_len != BTRFS_FID_SIZE_CONNECTABLE_ROOT)
+               if (fh_len < BTRFS_FID_SIZE_CONNECTABLE_ROOT)
                        return NULL;
                root_objectid = fid->parent_root_objectid;
        } else
@@ -136,11 +136,11 @@ static struct dentry *btrfs_fh_to_dentry(struct super_block *sb, struct fid *fh,
        u32 generation;
 
        if ((fh_type != FILEID_BTRFS_WITH_PARENT ||
-            fh_len != BTRFS_FID_SIZE_CONNECTABLE) &&
+            fh_len < BTRFS_FID_SIZE_CONNECTABLE) &&
            (fh_type != FILEID_BTRFS_WITH_PARENT_ROOT ||
-            fh_len != BTRFS_FID_SIZE_CONNECTABLE_ROOT) &&
+            fh_len < BTRFS_FID_SIZE_CONNECTABLE_ROOT) &&
            (fh_type != FILEID_BTRFS_WITHOUT_PARENT ||
-            fh_len != BTRFS_FID_SIZE_NON_CONNECTABLE))
+            fh_len < BTRFS_FID_SIZE_NON_CONNECTABLE))
                return NULL;
 
        objectid = fid->objectid;
index 5411f0ab56831aa3923f5d4b2d1d53adf9a88991..601d7d45d164a7e91477748a900bbef8cf67d0b0 100644 (file)
@@ -2828,6 +2828,7 @@ int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
        struct btrfs_delayed_ref_head *head;
        int ret;
        int run_all = count == (unsigned long)-1;
+       bool can_flush_pending_bgs = trans->can_flush_pending_bgs;
 
        /* We'll clean this up in btrfs_cleanup_transaction */
        if (trans->aborted)
@@ -2844,6 +2845,7 @@ again:
 #ifdef SCRAMBLE_DELAYED_REFS
        delayed_refs->run_delayed_start = find_middle(&delayed_refs->root);
 #endif
+       trans->can_flush_pending_bgs = false;
        ret = __btrfs_run_delayed_refs(trans, root, count);
        if (ret < 0) {
                btrfs_abort_transaction(trans, root, ret);
@@ -2893,6 +2895,7 @@ again:
        }
 out:
        assert_qgroups_uptodate(trans);
+       trans->can_flush_pending_bgs = can_flush_pending_bgs;
        return 0;
 }
 
@@ -3742,10 +3745,7 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags,
        found->bytes_reserved = 0;
        found->bytes_readonly = 0;
        found->bytes_may_use = 0;
-       if (total_bytes > 0)
-               found->full = 0;
-       else
-               found->full = 1;
+       found->full = 0;
        found->force_alloc = CHUNK_ALLOC_NO_FORCE;
        found->chunk_alloc = 0;
        found->flush = 0;
@@ -4309,7 +4309,8 @@ out:
         * the block groups that were made dirty during the lifetime of the
         * transaction.
         */
-       if (trans->chunk_bytes_reserved >= (2 * 1024 * 1024ull)) {
+       if (trans->can_flush_pending_bgs &&
+           trans->chunk_bytes_reserved >= (2 * 1024 * 1024ull)) {
                btrfs_create_pending_block_groups(trans, trans->root);
                btrfs_trans_release_chunk_metadata(trans);
        }
@@ -8668,7 +8669,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
        }
 
        if (test_bit(BTRFS_ROOT_IN_RADIX, &root->state)) {
-               btrfs_drop_and_free_fs_root(tree_root->fs_info, root);
+               btrfs_add_dropped_root(trans, root);
        } else {
                free_extent_buffer(root->node);
                free_extent_buffer(root->commit_root);
@@ -9563,7 +9564,9 @@ void btrfs_create_pending_block_groups(struct btrfs_trans_handle *trans,
        struct btrfs_block_group_item item;
        struct btrfs_key key;
        int ret = 0;
+       bool can_flush_pending_bgs = trans->can_flush_pending_bgs;
 
+       trans->can_flush_pending_bgs = false;
        list_for_each_entry_safe(block_group, tmp, &trans->new_bgs, bg_list) {
                if (ret)
                        goto next;
@@ -9584,6 +9587,7 @@ void btrfs_create_pending_block_groups(struct btrfs_trans_handle *trans,
 next:
                list_del_init(&block_group->bg_list);
        }
+       trans->can_flush_pending_bgs = can_flush_pending_bgs;
 }
 
 int btrfs_make_block_group(struct btrfs_trans_handle *trans,
index f1018cfbfefad0f7b43920bf32ece43b46228276..3915c9473e9445d4aeada81c8fb96af7fb521f2c 100644 (file)
@@ -2798,7 +2798,8 @@ static int submit_extent_page(int rw, struct extent_io_tree *tree,
                              bio_end_io_t end_io_func,
                              int mirror_num,
                              unsigned long prev_bio_flags,
-                             unsigned long bio_flags)
+                             unsigned long bio_flags,
+                             bool force_bio_submit)
 {
        int ret = 0;
        struct bio *bio;
@@ -2814,6 +2815,7 @@ static int submit_extent_page(int rw, struct extent_io_tree *tree,
                        contig = bio_end_sector(bio) == sector;
 
                if (prev_bio_flags != bio_flags || !contig ||
+                   force_bio_submit ||
                    merge_bio(rw, tree, page, offset, page_size, bio, bio_flags) ||
                    bio_add_page(bio, page, page_size, offset) < page_size) {
                        ret = submit_one_bio(rw, bio, mirror_num,
@@ -2910,7 +2912,8 @@ static int __do_readpage(struct extent_io_tree *tree,
                         get_extent_t *get_extent,
                         struct extent_map **em_cached,
                         struct bio **bio, int mirror_num,
-                        unsigned long *bio_flags, int rw)
+                        unsigned long *bio_flags, int rw,
+                        u64 *prev_em_start)
 {
        struct inode *inode = page->mapping->host;
        u64 start = page_offset(page);
@@ -2958,6 +2961,7 @@ static int __do_readpage(struct extent_io_tree *tree,
        }
        while (cur <= end) {
                unsigned long pnr = (last_byte >> PAGE_CACHE_SHIFT) + 1;
+               bool force_bio_submit = false;
 
                if (cur >= last_byte) {
                        char *userpage;
@@ -3008,6 +3012,49 @@ static int __do_readpage(struct extent_io_tree *tree,
                block_start = em->block_start;
                if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags))
                        block_start = EXTENT_MAP_HOLE;
+
+               /*
+                * If we have a file range that points to a compressed extent
+                * and it's followed by a consecutive file range that points to
+                * to the same compressed extent (possibly with a different
+                * offset and/or length, so it either points to the whole extent
+                * or only part of it), we must make sure we do not submit a
+                * single bio to populate the pages for the 2 ranges because
+                * this makes the compressed extent read zero out the pages
+                * belonging to the 2nd range. Imagine the following scenario:
+                *
+                *  File layout
+                *  [0 - 8K]                     [8K - 24K]
+                *    |                               |
+                *    |                               |
+                * points to extent X,         points to extent X,
+                * offset 4K, length of 8K     offset 0, length 16K
+                *
+                * [extent X, compressed length = 4K uncompressed length = 16K]
+                *
+                * If the bio to read the compressed extent covers both ranges,
+                * it will decompress extent X into the pages belonging to the
+                * first range and then it will stop, zeroing out the remaining
+                * pages that belong to the other range that points to extent X.
+                * So here we make sure we submit 2 bios, one for the first
+                * range and another one for the third range. Both will target
+                * the same physical extent from disk, but we can't currently
+                * make the compressed bio endio callback populate the pages
+                * for both ranges because each compressed bio is tightly
+                * coupled with a single extent map, and each range can have
+                * an extent map with a different offset value relative to the
+                * uncompressed data of our extent and different lengths. This
+                * is a corner case so we prioritize correctness over
+                * non-optimal behavior (submitting 2 bios for the same extent).
+                */
+               if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags) &&
+                   prev_em_start && *prev_em_start != (u64)-1 &&
+                   *prev_em_start != em->orig_start)
+                       force_bio_submit = true;
+
+               if (prev_em_start)
+                       *prev_em_start = em->orig_start;
+
                free_extent_map(em);
                em = NULL;
 
@@ -3057,7 +3104,8 @@ static int __do_readpage(struct extent_io_tree *tree,
                                         bdev, bio, pnr,
                                         end_bio_extent_readpage, mirror_num,
                                         *bio_flags,
-                                        this_bio_flag);
+                                        this_bio_flag,
+                                        force_bio_submit);
                if (!ret) {
                        nr++;
                        *bio_flags = this_bio_flag;
@@ -3084,7 +3132,8 @@ static inline void __do_contiguous_readpages(struct extent_io_tree *tree,
                                             get_extent_t *get_extent,
                                             struct extent_map **em_cached,
                                             struct bio **bio, int mirror_num,
-                                            unsigned long *bio_flags, int rw)
+                                            unsigned long *bio_flags, int rw,
+                                            u64 *prev_em_start)
 {
        struct inode *inode;
        struct btrfs_ordered_extent *ordered;
@@ -3104,7 +3153,7 @@ static inline void __do_contiguous_readpages(struct extent_io_tree *tree,
 
        for (index = 0; index < nr_pages; index++) {
                __do_readpage(tree, pages[index], get_extent, em_cached, bio,
-                             mirror_num, bio_flags, rw);
+                             mirror_num, bio_flags, rw, prev_em_start);
                page_cache_release(pages[index]);
        }
 }
@@ -3114,7 +3163,8 @@ static void __extent_readpages(struct extent_io_tree *tree,
                               int nr_pages, get_extent_t *get_extent,
                               struct extent_map **em_cached,
                               struct bio **bio, int mirror_num,
-                              unsigned long *bio_flags, int rw)
+                              unsigned long *bio_flags, int rw,
+                              u64 *prev_em_start)
 {
        u64 start = 0;
        u64 end = 0;
@@ -3135,7 +3185,7 @@ static void __extent_readpages(struct extent_io_tree *tree,
                                                  index - first_index, start,
                                                  end, get_extent, em_cached,
                                                  bio, mirror_num, bio_flags,
-                                                 rw);
+                                                 rw, prev_em_start);
                        start = page_start;
                        end = start + PAGE_CACHE_SIZE - 1;
                        first_index = index;
@@ -3146,7 +3196,8 @@ static void __extent_readpages(struct extent_io_tree *tree,
                __do_contiguous_readpages(tree, &pages[first_index],
                                          index - first_index, start,
                                          end, get_extent, em_cached, bio,
-                                         mirror_num, bio_flags, rw);
+                                         mirror_num, bio_flags, rw,
+                                         prev_em_start);
 }
 
 static int __extent_read_full_page(struct extent_io_tree *tree,
@@ -3172,7 +3223,7 @@ static int __extent_read_full_page(struct extent_io_tree *tree,
        }
 
        ret = __do_readpage(tree, page, get_extent, NULL, bio, mirror_num,
-                           bio_flags, rw);
+                           bio_flags, rw, NULL);
        return ret;
 }
 
@@ -3198,7 +3249,7 @@ int extent_read_full_page_nolock(struct extent_io_tree *tree, struct page *page,
        int ret;
 
        ret = __do_readpage(tree, page, get_extent, NULL, &bio, mirror_num,
-                                     &bio_flags, READ);
+                           &bio_flags, READ, NULL);
        if (bio)
                ret = submit_one_bio(READ, bio, mirror_num, bio_flags);
        return ret;
@@ -3451,7 +3502,7 @@ static noinline_for_stack int __extent_writepage_io(struct inode *inode,
                                                 sector, iosize, pg_offset,
                                                 bdev, &epd->bio, max_nr,
                                                 end_bio_extent_writepage,
-                                                0, 0, 0);
+                                                0, 0, 0, false);
                        if (ret)
                                SetPageError(page);
                }
@@ -3754,7 +3805,7 @@ static noinline_for_stack int write_one_eb(struct extent_buffer *eb,
                ret = submit_extent_page(rw, tree, wbc, p, offset >> 9,
                                         PAGE_CACHE_SIZE, 0, bdev, &epd->bio,
                                         -1, end_bio_extent_buffer_writepage,
-                                        0, epd->bio_flags, bio_flags);
+                                        0, epd->bio_flags, bio_flags, false);
                epd->bio_flags = bio_flags;
                if (ret) {
                        set_btree_ioerr(p);
@@ -4158,6 +4209,7 @@ int extent_readpages(struct extent_io_tree *tree,
        struct page *page;
        struct extent_map *em_cached = NULL;
        int nr = 0;
+       u64 prev_em_start = (u64)-1;
 
        for (page_idx = 0; page_idx < nr_pages; page_idx++) {
                page = list_entry(pages->prev, struct page, lru);
@@ -4174,12 +4226,12 @@ int extent_readpages(struct extent_io_tree *tree,
                if (nr < ARRAY_SIZE(pagepool))
                        continue;
                __extent_readpages(tree, pagepool, nr, get_extent, &em_cached,
-                                  &bio, 0, &bio_flags, READ);
+                                  &bio, 0, &bio_flags, READ, &prev_em_start);
                nr = 0;
        }
        if (nr)
                __extent_readpages(tree, pagepool, nr, get_extent, &em_cached,
-                                  &bio, 0, &bio_flags, READ);
+                                  &bio, 0, &bio_flags, READ, &prev_em_start);
 
        if (em_cached)
                free_extent_map(em_cached);
index b823fac91c9289bc67d3bb5191f4ce96e38294ac..8c6f247ba81d4e84c6a7d3d00d0348c974c1b049 100644 (file)
@@ -2584,7 +2584,7 @@ static long btrfs_fallocate(struct file *file, int mode,
                                        alloc_start);
                if (ret)
                        goto out;
-       } else {
+       } else if (offset + len > inode->i_size) {
                /*
                 * If we are fallocating from the end of the file onward we
                 * need to zero out the end of the page if i_size lands in the
index a0fa7253a2d77b6faa2e71366c762b331cd784b2..611b66d73e80ba0e5f97b4415595d20f8ae35e1a 100644 (file)
@@ -5084,7 +5084,8 @@ void btrfs_evict_inode(struct inode *inode)
                goto no_delete;
        }
        /* do we really want it for ->i_nlink > 0 and zero btrfs_root_refs? */
-       btrfs_wait_ordered_range(inode, 0, (u64)-1);
+       if (!special_file(inode->i_mode))
+               btrfs_wait_ordered_range(inode, 0, (u64)-1);
 
        btrfs_free_io_failure_record(inode, 0, (u64)-1);
 
@@ -7408,6 +7409,10 @@ static struct extent_map *create_pinned_em(struct inode *inode, u64 start,
        return em;
 }
 
+struct btrfs_dio_data {
+       u64 outstanding_extents;
+       u64 reserve;
+};
 
 static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
                                   struct buffer_head *bh_result, int create)
@@ -7415,10 +7420,10 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
        struct extent_map *em;
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct extent_state *cached_state = NULL;
+       struct btrfs_dio_data *dio_data = NULL;
        u64 start = iblock << inode->i_blkbits;
        u64 lockstart, lockend;
        u64 len = bh_result->b_size;
-       u64 *outstanding_extents = NULL;
        int unlock_bits = EXTENT_LOCKED;
        int ret = 0;
 
@@ -7436,7 +7441,7 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
                 * that anything that needs to check if there's a transction doesn't get
                 * confused.
                 */
-               outstanding_extents = current->journal_info;
+               dio_data = current->journal_info;
                current->journal_info = NULL;
        }
 
@@ -7568,17 +7573,18 @@ unlock:
                 * within our reservation, otherwise we need to adjust our inode
                 * counter appropriately.
                 */
-               if (*outstanding_extents) {
-                       (*outstanding_extents)--;
+               if (dio_data->outstanding_extents) {
+                       (dio_data->outstanding_extents)--;
                } else {
                        spin_lock(&BTRFS_I(inode)->lock);
                        BTRFS_I(inode)->outstanding_extents++;
                        spin_unlock(&BTRFS_I(inode)->lock);
                }
 
-               current->journal_info = outstanding_extents;
                btrfs_free_reserved_data_space(inode, len);
-               set_bit(BTRFS_INODE_DIO_READY, &BTRFS_I(inode)->runtime_flags);
+               WARN_ON(dio_data->reserve < len);
+               dio_data->reserve -= len;
+               current->journal_info = dio_data;
        }
 
        /*
@@ -7601,8 +7607,8 @@ unlock:
 unlock_err:
        clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart, lockend,
                         unlock_bits, 1, 0, &cached_state, GFP_NOFS);
-       if (outstanding_extents)
-               current->journal_info = outstanding_extents;
+       if (dio_data)
+               current->journal_info = dio_data;
        return ret;
 }
 
@@ -8329,7 +8335,8 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
 {
        struct file *file = iocb->ki_filp;
        struct inode *inode = file->f_mapping->host;
-       u64 outstanding_extents = 0;
+       struct btrfs_root *root = BTRFS_I(inode)->root;
+       struct btrfs_dio_data dio_data = { 0 };
        size_t count = 0;
        int flags = 0;
        bool wakeup = true;
@@ -8367,7 +8374,7 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
                ret = btrfs_delalloc_reserve_space(inode, count);
                if (ret)
                        goto out;
-               outstanding_extents = div64_u64(count +
+               dio_data.outstanding_extents = div64_u64(count +
                                                BTRFS_MAX_EXTENT_SIZE - 1,
                                                BTRFS_MAX_EXTENT_SIZE);
 
@@ -8376,7 +8383,8 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
                 * do the accounting properly if we go over the number we
                 * originally calculated.  Abuse current->journal_info for this.
                 */
-               current->journal_info = &outstanding_extents;
+               dio_data.reserve = round_up(count, root->sectorsize);
+               current->journal_info = &dio_data;
        } else if (test_bit(BTRFS_INODE_READDIO_NEED_LOCK,
                                     &BTRFS_I(inode)->runtime_flags)) {
                inode_dio_end(inode);
@@ -8391,16 +8399,9 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
        if (iov_iter_rw(iter) == WRITE) {
                current->journal_info = NULL;
                if (ret < 0 && ret != -EIOCBQUEUED) {
-                       /*
-                        * If the error comes from submitting stage,
-                        * btrfs_get_blocsk_direct() has free'd data space,
-                        * and metadata space will be handled by
-                        * finish_ordered_fn, don't do that again to make
-                        * sure bytes_may_use is correct.
-                        */
-                       if (!test_and_clear_bit(BTRFS_INODE_DIO_READY,
-                                    &BTRFS_I(inode)->runtime_flags))
-                               btrfs_delalloc_release_space(inode, count);
+                       if (dio_data.reserve)
+                               btrfs_delalloc_release_space(inode,
+                                                       dio_data.reserve);
                } else if (ret >= 0 && (size_t)ret < count)
                        btrfs_delalloc_release_space(inode,
                                                     count - (size_t)ret);
index 0adf5422fce9d4b9fc62c2bbf319429b38aaec7c..8d20f3b1cab0abfa7b5f2bc4b8646c094a9353a5 100644 (file)
@@ -4639,6 +4639,11 @@ locked:
                bctl->flags |= BTRFS_BALANCE_TYPE_MASK;
        }
 
+       if (bctl->flags & ~(BTRFS_BALANCE_ARGS_MASK | BTRFS_BALANCE_TYPE_MASK)) {
+               ret = -EINVAL;
+               goto out_bctl;
+       }
+
 do_balance:
        /*
         * Ownership of bctl and mutually_exclusive_operation_running
@@ -4650,12 +4655,15 @@ do_balance:
        need_unlock = false;
 
        ret = btrfs_balance(bctl, bargs);
+       bctl = NULL;
 
        if (arg) {
                if (copy_to_user(arg, bargs, sizeof(*bargs)))
                        ret = -EFAULT;
        }
 
+out_bctl:
+       kfree(bctl);
 out_bargs:
        kfree(bargs);
 out_unlock:
index aa72bfd28f7dcbd88c73452aafd2a3d9e7f42e00..a739b825bdd364cfa9cbf16edc9f978a68feb95f 100644 (file)
@@ -1920,10 +1920,12 @@ static int did_overwrite_ref(struct send_ctx *sctx,
        /*
         * We know that it is or will be overwritten. Check this now.
         * The current inode being processed might have been the one that caused
-        * inode 'ino' to be orphanized, therefore ow_inode can actually be the
-        * same as sctx->send_progress.
+        * inode 'ino' to be orphanized, therefore check if ow_inode matches
+        * the current inode being processed.
         */
-       if (ow_inode <= sctx->send_progress)
+       if ((ow_inode < sctx->send_progress) ||
+           (ino != sctx->cur_ino && ow_inode == sctx->cur_ino &&
+            gen == sctx->cur_inode_gen))
                ret = 1;
        else
                ret = 0;
index 2b07b3581781b7b952a384295d8bac5fee983f07..11d1eab9234dc818244d1c1bbecd6d25981f4890 100644 (file)
@@ -1658,9 +1658,7 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
                 * groups on disk until we're mounted read-write again
                 * unless we clean them up here.
                 */
-               mutex_lock(&root->fs_info->cleaner_mutex);
                btrfs_delete_unused_bgs(fs_info);
-               mutex_unlock(&root->fs_info->cleaner_mutex);
 
                btrfs_dev_replace_suspend_for_unmount(fs_info);
                btrfs_scrub_cancel(fs_info);
index 8f259b3a66b366d6e90393d4b3f15e91d23fd2b0..a5b06442f0bf9d1630f201da3e0eb5c0422e8cc9 100644 (file)
@@ -117,6 +117,18 @@ static noinline void switch_commit_roots(struct btrfs_transaction *trans,
                        btrfs_unpin_free_ino(root);
                clear_btree_io_tree(&root->dirty_log_pages);
        }
+
+       /* We can free old roots now. */
+       spin_lock(&trans->dropped_roots_lock);
+       while (!list_empty(&trans->dropped_roots)) {
+               root = list_first_entry(&trans->dropped_roots,
+                                       struct btrfs_root, root_list);
+               list_del_init(&root->root_list);
+               spin_unlock(&trans->dropped_roots_lock);
+               btrfs_drop_and_free_fs_root(fs_info, root);
+               spin_lock(&trans->dropped_roots_lock);
+       }
+       spin_unlock(&trans->dropped_roots_lock);
        up_write(&fs_info->commit_root_sem);
 }
 
@@ -255,11 +267,13 @@ loop:
        INIT_LIST_HEAD(&cur_trans->pending_ordered);
        INIT_LIST_HEAD(&cur_trans->dirty_bgs);
        INIT_LIST_HEAD(&cur_trans->io_bgs);
+       INIT_LIST_HEAD(&cur_trans->dropped_roots);
        mutex_init(&cur_trans->cache_write_mutex);
        cur_trans->num_dirty_bgs = 0;
        spin_lock_init(&cur_trans->dirty_bgs_lock);
        INIT_LIST_HEAD(&cur_trans->deleted_bgs);
        spin_lock_init(&cur_trans->deleted_bgs_lock);
+       spin_lock_init(&cur_trans->dropped_roots_lock);
        list_add_tail(&cur_trans->list, &fs_info->trans_list);
        extent_io_tree_init(&cur_trans->dirty_pages,
                             fs_info->btree_inode->i_mapping);
@@ -336,6 +350,24 @@ static int record_root_in_trans(struct btrfs_trans_handle *trans,
 }
 
 
+void btrfs_add_dropped_root(struct btrfs_trans_handle *trans,
+                           struct btrfs_root *root)
+{
+       struct btrfs_transaction *cur_trans = trans->transaction;
+
+       /* Add ourselves to the transaction dropped list */
+       spin_lock(&cur_trans->dropped_roots_lock);
+       list_add_tail(&root->root_list, &cur_trans->dropped_roots);
+       spin_unlock(&cur_trans->dropped_roots_lock);
+
+       /* Make sure we don't try to update the root at commit time */
+       spin_lock(&root->fs_info->fs_roots_radix_lock);
+       radix_tree_tag_clear(&root->fs_info->fs_roots_radix,
+                            (unsigned long)root->root_key.objectid,
+                            BTRFS_ROOT_TRANS_TAG);
+       spin_unlock(&root->fs_info->fs_roots_radix_lock);
+}
+
 int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans,
                               struct btrfs_root *root)
 {
@@ -525,6 +557,7 @@ again:
        h->delayed_ref_elem.seq = 0;
        h->type = type;
        h->allocating_chunk = false;
+       h->can_flush_pending_bgs = true;
        h->reloc_reserved = false;
        h->sync = false;
        INIT_LIST_HEAD(&h->qgroup_ref_list);
index edc2fbc262d7680a55a95ffaeab9f0913129d713..a994bb097ee59c12bb0d5599f10c8a64b1954f43 100644 (file)
@@ -65,6 +65,7 @@ struct btrfs_transaction {
        struct list_head switch_commits;
        struct list_head dirty_bgs;
        struct list_head io_bgs;
+       struct list_head dropped_roots;
        u64 num_dirty_bgs;
 
        /*
@@ -76,6 +77,7 @@ struct btrfs_transaction {
        spinlock_t dirty_bgs_lock;
        struct list_head deleted_bgs;
        spinlock_t deleted_bgs_lock;
+       spinlock_t dropped_roots_lock;
        struct btrfs_delayed_ref_root delayed_refs;
        int aborted;
        int dirty_bg_run;
@@ -116,6 +118,7 @@ struct btrfs_trans_handle {
        short aborted;
        short adding_csums;
        bool allocating_chunk;
+       bool can_flush_pending_bgs;
        bool reloc_reserved;
        bool sync;
        unsigned int type;
@@ -216,5 +219,6 @@ int btrfs_transaction_blocked(struct btrfs_fs_info *info);
 int btrfs_transaction_in_commit(struct btrfs_fs_info *info);
 void btrfs_put_transaction(struct btrfs_transaction *transaction);
 void btrfs_apply_pending_changes(struct btrfs_fs_info *fs_info);
-
+void btrfs_add_dropped_root(struct btrfs_trans_handle *trans,
+                           struct btrfs_root *root);
 #endif
index 2ca784a14e84bc2a00d0c3d1ec1a15290128edfc..595279a8b99fd461e24cb24df3805fa8401f3dd6 100644 (file)
@@ -376,6 +376,14 @@ struct map_lookup {
 #define BTRFS_BALANCE_ARGS_VRANGE      (1ULL << 4)
 #define BTRFS_BALANCE_ARGS_LIMIT       (1ULL << 5)
 
+#define BTRFS_BALANCE_ARGS_MASK                        \
+       (BTRFS_BALANCE_ARGS_PROFILES |          \
+        BTRFS_BALANCE_ARGS_USAGE |             \
+        BTRFS_BALANCE_ARGS_DEVID |             \
+        BTRFS_BALANCE_ARGS_DRANGE |            \
+        BTRFS_BALANCE_ARGS_VRANGE |            \
+        BTRFS_BALANCE_ARGS_LIMIT)
+
 /*
  * Profile changing flags.  When SOFT is set we won't relocate chunk if
  * it already has the target profile (even though it may be
index aa0dc2573374184597b9e449fad6467f924f0f45..afa09fce81515e4caf7500b04c16dfb96a71cfd1 100644 (file)
@@ -444,6 +444,48 @@ find_domain_name(struct cifs_ses *ses, const struct nls_table *nls_cp)
        return 0;
 }
 
+/* Server has provided av pairs/target info in the type 2 challenge
+ * packet and we have plucked it and stored within smb session.
+ * We parse that blob here to find the server given timestamp
+ * as part of ntlmv2 authentication (or local current time as
+ * default in case of failure)
+ */
+static __le64
+find_timestamp(struct cifs_ses *ses)
+{
+       unsigned int attrsize;
+       unsigned int type;
+       unsigned int onesize = sizeof(struct ntlmssp2_name);
+       unsigned char *blobptr;
+       unsigned char *blobend;
+       struct ntlmssp2_name *attrptr;
+
+       if (!ses->auth_key.len || !ses->auth_key.response)
+               return 0;
+
+       blobptr = ses->auth_key.response;
+       blobend = blobptr + ses->auth_key.len;
+
+       while (blobptr + onesize < blobend) {
+               attrptr = (struct ntlmssp2_name *) blobptr;
+               type = le16_to_cpu(attrptr->type);
+               if (type == NTLMSSP_AV_EOL)
+                       break;
+               blobptr += 2; /* advance attr type */
+               attrsize = le16_to_cpu(attrptr->length);
+               blobptr += 2; /* advance attr size */
+               if (blobptr + attrsize > blobend)
+                       break;
+               if (type == NTLMSSP_AV_TIMESTAMP) {
+                       if (attrsize == sizeof(u64))
+                               return *((__le64 *)blobptr);
+               }
+               blobptr += attrsize; /* advance attr value */
+       }
+
+       return cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
+}
+
 static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
                            const struct nls_table *nls_cp)
 {
@@ -641,6 +683,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
        struct ntlmv2_resp *ntlmv2;
        char ntlmv2_hash[16];
        unsigned char *tiblob = NULL; /* target info blob */
+       __le64 rsp_timestamp;
 
        if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED) {
                if (!ses->domainName) {
@@ -659,6 +702,12 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
                }
        }
 
+       /* Must be within 5 minutes of the server (or in range +/-2h
+        * in case of Mac OS X), so simply carry over server timestamp
+        * (as Windows 7 does)
+        */
+       rsp_timestamp = find_timestamp(ses);
+
        baselen = CIFS_SESS_KEY_SIZE + sizeof(struct ntlmv2_resp);
        tilen = ses->auth_key.len;
        tiblob = ses->auth_key.response;
@@ -675,8 +724,8 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
                        (ses->auth_key.response + CIFS_SESS_KEY_SIZE);
        ntlmv2->blob_signature = cpu_to_le32(0x00000101);
        ntlmv2->reserved = 0;
-       /* Must be within 5 minutes of the server */
-       ntlmv2->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
+       ntlmv2->time = rsp_timestamp;
+
        get_random_bytes(&ntlmv2->client_chal, sizeof(ntlmv2->client_chal));
        ntlmv2->reserved2 = 0;
 
index 6a1119e87fbb6fb636e4d76e814574402b7dc139..e739950ca08485543db80bee53f1021384ed0b9a 100644 (file)
@@ -325,8 +325,11 @@ cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server)
 static void
 cifs_show_security(struct seq_file *s, struct cifs_ses *ses)
 {
-       if (ses->sectype == Unspecified)
+       if (ses->sectype == Unspecified) {
+               if (ses->user_name == NULL)
+                       seq_puts(s, ",sec=none");
                return;
+       }
 
        seq_puts(s, ",sec=");
 
index 27aea110e92365e1e91610579369215cc54644ea..c3cc1609025fa3a966c2d5b10f32626214a9e4ef 100644 (file)
@@ -136,5 +136,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.07"
+#define CIFS_VERSION   "2.08"
 #endif                         /* _CIFSFS_H */
index e2a6af1508af2aef789d0caab21fedfa91d49c60..62203c387db45a23b05c1cadcc0946843ea5332f 100644 (file)
@@ -3380,6 +3380,7 @@ readpages_get_pages(struct address_space *mapping, struct list_head *page_list,
        struct page *page, *tpage;
        unsigned int expected_index;
        int rc;
+       gfp_t gfp = GFP_KERNEL & mapping_gfp_mask(mapping);
 
        INIT_LIST_HEAD(tmplist);
 
@@ -3392,7 +3393,7 @@ readpages_get_pages(struct address_space *mapping, struct list_head *page_list,
         */
        __set_page_locked(page);
        rc = add_to_page_cache_locked(page, mapping,
-                                     page->index, GFP_KERNEL);
+                                     page->index, gfp);
 
        /* give up if we can't stick it in the cache */
        if (rc) {
@@ -3418,8 +3419,7 @@ readpages_get_pages(struct address_space *mapping, struct list_head *page_list,
                        break;
 
                __set_page_locked(page);
-               if (add_to_page_cache_locked(page, mapping, page->index,
-                                                               GFP_KERNEL)) {
+               if (add_to_page_cache_locked(page, mapping, page->index, gfp)) {
                        __clear_page_locked(page);
                        break;
                }
index f621b44cb8009fe87bf631e0a96c941fe63d3408..6b66dd5d15408676ab6510f7ce415164fe5c0571 100644 (file)
@@ -2034,7 +2034,6 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
        struct tcon_link *tlink = NULL;
        struct cifs_tcon *tcon = NULL;
        struct TCP_Server_Info *server;
-       struct cifs_io_parms io_parms;
 
        /*
         * To avoid spurious oplock breaks from server, in the case of
@@ -2056,18 +2055,6 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
                        rc = -ENOSYS;
                cifsFileInfo_put(open_file);
                cifs_dbg(FYI, "SetFSize for attrs rc = %d\n", rc);
-               if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
-                       unsigned int bytes_written;
-
-                       io_parms.netfid = open_file->fid.netfid;
-                       io_parms.pid = open_file->pid;
-                       io_parms.tcon = tcon;
-                       io_parms.offset = 0;
-                       io_parms.length = attrs->ia_size;
-                       rc = CIFSSMBWrite(xid, &io_parms, &bytes_written,
-                                         NULL, NULL, 1);
-                       cifs_dbg(FYI, "Wrt seteof rc %d\n", rc);
-               }
        } else
                rc = -EINVAL;
 
@@ -2093,28 +2080,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
        else
                rc = -ENOSYS;
        cifs_dbg(FYI, "SetEOF by path (setattrs) rc = %d\n", rc);
-       if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
-               __u16 netfid;
-               int oplock = 0;
 
-               rc = SMBLegacyOpen(xid, tcon, full_path, FILE_OPEN,
-                                  GENERIC_WRITE, CREATE_NOT_DIR, &netfid,
-                                  &oplock, NULL, cifs_sb->local_nls,
-                                  cifs_remap(cifs_sb));
-               if (rc == 0) {
-                       unsigned int bytes_written;
-
-                       io_parms.netfid = netfid;
-                       io_parms.pid = current->tgid;
-                       io_parms.tcon = tcon;
-                       io_parms.offset = 0;
-                       io_parms.length = attrs->ia_size;
-                       rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, NULL,
-                                         NULL,  1);
-                       cifs_dbg(FYI, "wrt seteof rc %d\n", rc);
-                       CIFSSMBClose(xid, tcon, netfid);
-               }
-       }
        if (tlink)
                cifs_put_tlink(tlink);
 
index c63f5227b68181ed772d1a999686a852a23d41e9..28a77bf1d55924693d27d1c701571e1b1fef2d49 100644 (file)
@@ -67,6 +67,12 @@ static long cifs_ioctl_clone(unsigned int xid, struct file *dst_file,
                goto out_drop_write;
        }
 
+       if (src_file.file->f_op->unlocked_ioctl != cifs_ioctl) {
+               rc = -EBADF;
+               cifs_dbg(VFS, "src file seems to be from a different filesystem type\n");
+               goto out_fput;
+       }
+
        if ((!src_file.file->private_data) || (!dst_file->private_data)) {
                rc = -EBADF;
                cifs_dbg(VFS, "missing cifsFileInfo on copy range src file\n");
index df91bcf56d67a35f0dd60d0361514f65cdc6705e..18da19f4f811ed19c327ab44a706e66c3a339bb0 100644 (file)
@@ -50,9 +50,13 @@ change_conf(struct TCP_Server_Info *server)
                break;
        default:
                server->echoes = true;
-               server->oplocks = true;
+               if (enable_oplocks) {
+                       server->oplocks = true;
+                       server->oplock_credits = 1;
+               } else
+                       server->oplocks = false;
+
                server->echo_credits = 1;
-               server->oplock_credits = 1;
        }
        server->credits -= server->echo_credits + server->oplock_credits;
        return 0;
index 070fb2ad85ced4483d28d88c1fa4832e92eef3ba..597a417ba94d3bb910f52e3f14119a197ff2d090 100644 (file)
@@ -46,6 +46,7 @@
 #include "smb2status.h"
 #include "smb2glob.h"
 #include "cifspdu.h"
+#include "cifs_spnego.h"
 
 /*
  *  The following table defines the expected "StructureSize" of SMB2 requests
@@ -486,19 +487,15 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
                cifs_dbg(FYI, "missing security blob on negprot\n");
 
        rc = cifs_enable_signing(server, ses->sign);
-#ifdef CONFIG_SMB2_ASN1  /* BB REMOVEME when updated asn1.c ready */
        if (rc)
                goto neg_exit;
-       if (blob_length)
+       if (blob_length) {
                rc = decode_negTokenInit(security_blob, blob_length, server);
-       if (rc == 1)
-               rc = 0;
-       else if (rc == 0) {
-               rc = -EIO;
-               goto neg_exit;
+               if (rc == 1)
+                       rc = 0;
+               else if (rc == 0)
+                       rc = -EIO;
        }
-#endif
-
 neg_exit:
        free_rsp_buf(resp_buftype, rsp);
        return rc;
@@ -592,7 +589,8 @@ SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses,
        __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */
        struct TCP_Server_Info *server = ses->server;
        u16 blob_length = 0;
-       char *security_blob;
+       struct key *spnego_key = NULL;
+       char *security_blob = NULL;
        char *ntlmssp_blob = NULL;
        bool use_spnego = false; /* else use raw ntlmssp */
 
@@ -620,7 +618,8 @@ SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses,
        ses->ntlmssp->sesskey_per_smbsess = true;
 
        /* FIXME: allow for other auth types besides NTLMSSP (e.g. krb5) */
-       ses->sectype = RawNTLMSSP;
+       if (ses->sectype != Kerberos && ses->sectype != RawNTLMSSP)
+               ses->sectype = RawNTLMSSP;
 
 ssetup_ntlmssp_authenticate:
        if (phase == NtLmChallenge)
@@ -649,7 +648,48 @@ ssetup_ntlmssp_authenticate:
        iov[0].iov_base = (char *)req;
        /* 4 for rfc1002 length field and 1 for pad */
        iov[0].iov_len = get_rfc1002_length(req) + 4 - 1;
-       if (phase == NtLmNegotiate) {
+
+       if (ses->sectype == Kerberos) {
+#ifdef CONFIG_CIFS_UPCALL
+               struct cifs_spnego_msg *msg;
+
+               spnego_key = cifs_get_spnego_key(ses);
+               if (IS_ERR(spnego_key)) {
+                       rc = PTR_ERR(spnego_key);
+                       spnego_key = NULL;
+                       goto ssetup_exit;
+               }
+
+               msg = spnego_key->payload.data;
+               /*
+                * check version field to make sure that cifs.upcall is
+                * sending us a response in an expected form
+                */
+               if (msg->version != CIFS_SPNEGO_UPCALL_VERSION) {
+                       cifs_dbg(VFS,
+                                 "bad cifs.upcall version. Expected %d got %d",
+                                 CIFS_SPNEGO_UPCALL_VERSION, msg->version);
+                       rc = -EKEYREJECTED;
+                       goto ssetup_exit;
+               }
+               ses->auth_key.response = kmemdup(msg->data, msg->sesskey_len,
+                                                GFP_KERNEL);
+               if (!ses->auth_key.response) {
+                       cifs_dbg(VFS,
+                               "Kerberos can't allocate (%u bytes) memory",
+                               msg->sesskey_len);
+                       rc = -ENOMEM;
+                       goto ssetup_exit;
+               }
+               ses->auth_key.len = msg->sesskey_len;
+               blob_length = msg->secblob_len;
+               iov[1].iov_base = msg->data + msg->sesskey_len;
+               iov[1].iov_len = blob_length;
+#else
+               rc = -EOPNOTSUPP;
+               goto ssetup_exit;
+#endif /* CONFIG_CIFS_UPCALL */
+       } else if (phase == NtLmNegotiate) { /* if not krb5 must be ntlmssp */
                ntlmssp_blob = kmalloc(sizeof(struct _NEGOTIATE_MESSAGE),
                                       GFP_KERNEL);
                if (ntlmssp_blob == NULL) {
@@ -672,6 +712,8 @@ ssetup_ntlmssp_authenticate:
                        /* with raw NTLMSSP we don't encapsulate in SPNEGO */
                        security_blob = ntlmssp_blob;
                }
+               iov[1].iov_base = security_blob;
+               iov[1].iov_len = blob_length;
        } else if (phase == NtLmAuthenticate) {
                req->hdr.SessionId = ses->Suid;
                ntlmssp_blob = kzalloc(sizeof(struct _NEGOTIATE_MESSAGE) + 500,
@@ -699,6 +741,8 @@ ssetup_ntlmssp_authenticate:
                } else {
                        security_blob = ntlmssp_blob;
                }
+               iov[1].iov_base = security_blob;
+               iov[1].iov_len = blob_length;
        } else {
                cifs_dbg(VFS, "illegal ntlmssp phase\n");
                rc = -EIO;
@@ -710,8 +754,6 @@ ssetup_ntlmssp_authenticate:
                                cpu_to_le16(sizeof(struct smb2_sess_setup_req) -
                                            1 /* pad */ - 4 /* rfc1001 len */);
        req->SecurityBufferLength = cpu_to_le16(blob_length);
-       iov[1].iov_base = security_blob;
-       iov[1].iov_len = blob_length;
 
        inc_rfc1001_len(req, blob_length - 1 /* pad */);
 
@@ -722,6 +764,7 @@ ssetup_ntlmssp_authenticate:
 
        kfree(security_blob);
        rsp = (struct smb2_sess_setup_rsp *)iov[0].iov_base;
+       ses->Suid = rsp->hdr.SessionId;
        if (resp_buftype != CIFS_NO_BUFFER &&
            rsp->hdr.Status == STATUS_MORE_PROCESSING_REQUIRED) {
                if (phase != NtLmNegotiate) {
@@ -739,7 +782,6 @@ ssetup_ntlmssp_authenticate:
                /* NTLMSSP Negotiate sent now processing challenge (response) */
                phase = NtLmChallenge; /* process ntlmssp challenge */
                rc = 0; /* MORE_PROCESSING is not an error here but expected */
-               ses->Suid = rsp->hdr.SessionId;
                rc = decode_ntlmssp_challenge(rsp->Buffer,
                                le16_to_cpu(rsp->SecurityBufferLength), ses);
        }
@@ -796,6 +838,10 @@ keygen_exit:
                kfree(ses->auth_key.response);
                ses->auth_key.response = NULL;
        }
+       if (spnego_key) {
+               key_invalidate(spnego_key);
+               key_put(spnego_key);
+       }
        kfree(ses->ntlmssp);
 
        return rc;
@@ -876,6 +922,12 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
        if (tcon && tcon->bad_network_name)
                return -ENOENT;
 
+       if ((tcon && tcon->seal) &&
+           ((ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION) == 0)) {
+               cifs_dbg(VFS, "encryption requested but no server support");
+               return -EOPNOTSUPP;
+       }
+
        unc_path = kmalloc(MAX_SHARENAME_LENGTH * 2, GFP_KERNEL);
        if (unc_path == NULL)
                return -ENOMEM;
@@ -955,6 +1007,8 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
            ((tcon->share_flags & SHI1005_FLAGS_DFS) == 0))
                cifs_dbg(VFS, "DFS capability contradicts DFS flag\n");
        init_copy_chunk_defaults(tcon);
+       if (tcon->share_flags & SHI1005_FLAGS_ENCRYPT_DATA)
+               cifs_dbg(VFS, "Encrypted shares not supported");
        if (tcon->ses->server->ops->validate_negotiate)
                rc = tcon->ses->server->ops->validate_negotiate(xid, tcon);
 tcon_exit:
index 93bf2f990ace462b31dba2ee239084e112b1dfd0..a86d3cc2b38941b0e39f23be84e4986d8852ae42 100644 (file)
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -119,7 +119,8 @@ static ssize_t dax_io(struct inode *inode, struct iov_iter *iter,
                size_t len;
                if (pos == max) {
                        unsigned blkbits = inode->i_blkbits;
-                       sector_t block = pos >> blkbits;
+                       long page = pos >> PAGE_SHIFT;
+                       sector_t block = page << (PAGE_SHIFT - blkbits);
                        unsigned first = pos - (block << blkbits);
                        long size;
 
@@ -284,6 +285,7 @@ static int copy_user_bh(struct page *to, struct buffer_head *bh,
 static int dax_insert_mapping(struct inode *inode, struct buffer_head *bh,
                        struct vm_area_struct *vma, struct vm_fault *vmf)
 {
+       struct address_space *mapping = inode->i_mapping;
        sector_t sector = bh->b_blocknr << (inode->i_blkbits - 9);
        unsigned long vaddr = (unsigned long)vmf->virtual_address;
        void __pmem *addr;
@@ -291,6 +293,8 @@ static int dax_insert_mapping(struct inode *inode, struct buffer_head *bh,
        pgoff_t size;
        int error;
 
+       i_mmap_lock_read(mapping);
+
        /*
         * Check truncate didn't happen while we were allocating a block.
         * If it did, this block may or may not be still allocated to the
@@ -320,6 +324,8 @@ static int dax_insert_mapping(struct inode *inode, struct buffer_head *bh,
        error = vm_insert_mixed(vma, vaddr, pfn);
 
  out:
+       i_mmap_unlock_read(mapping);
+
        return error;
 }
 
@@ -381,17 +387,15 @@ int __dax_fault(struct vm_area_struct *vma, struct vm_fault *vmf,
                         * from a read fault and we've raced with a truncate
                         */
                        error = -EIO;
-                       goto unlock;
+                       goto unlock_page;
                }
-       } else {
-               i_mmap_lock_write(mapping);
        }
 
        error = get_block(inode, block, &bh, 0);
        if (!error && (bh.b_size < PAGE_SIZE))
                error = -EIO;           /* fs corruption? */
        if (error)
-               goto unlock;
+               goto unlock_page;
 
        if (!buffer_mapped(&bh) && !buffer_unwritten(&bh) && !vmf->cow_page) {
                if (vmf->flags & FAULT_FLAG_WRITE) {
@@ -402,9 +406,8 @@ int __dax_fault(struct vm_area_struct *vma, struct vm_fault *vmf,
                        if (!error && (bh.b_size < PAGE_SIZE))
                                error = -EIO;
                        if (error)
-                               goto unlock;
+                               goto unlock_page;
                } else {
-                       i_mmap_unlock_write(mapping);
                        return dax_load_hole(mapping, page, vmf);
                }
        }
@@ -416,15 +419,17 @@ int __dax_fault(struct vm_area_struct *vma, struct vm_fault *vmf,
                else
                        clear_user_highpage(new_page, vaddr);
                if (error)
-                       goto unlock;
+                       goto unlock_page;
                vmf->page = page;
                if (!page) {
+                       i_mmap_lock_read(mapping);
                        /* Check we didn't race with truncate */
                        size = (i_size_read(inode) + PAGE_SIZE - 1) >>
                                                                PAGE_SHIFT;
                        if (vmf->pgoff >= size) {
+                               i_mmap_unlock_read(mapping);
                                error = -EIO;
-                               goto unlock;
+                               goto out;
                        }
                }
                return VM_FAULT_LOCKED;
@@ -460,8 +465,6 @@ int __dax_fault(struct vm_area_struct *vma, struct vm_fault *vmf,
                        WARN_ON_ONCE(!(vmf->flags & FAULT_FLAG_WRITE));
        }
 
-       if (!page)
-               i_mmap_unlock_write(mapping);
  out:
        if (error == -ENOMEM)
                return VM_FAULT_OOM | major;
@@ -470,14 +473,11 @@ int __dax_fault(struct vm_area_struct *vma, struct vm_fault *vmf,
                return VM_FAULT_SIGBUS | major;
        return VM_FAULT_NOPAGE | major;
 
- unlock:
+ unlock_page:
        if (page) {
                unlock_page(page);
                page_cache_release(page);
-       } else {
-               i_mmap_unlock_write(mapping);
        }
-
        goto out;
 }
 EXPORT_SYMBOL(__dax_fault);
@@ -555,10 +555,10 @@ int __dax_pmd_fault(struct vm_area_struct *vma, unsigned long address,
        block = (sector_t)pgoff << (PAGE_SHIFT - blkbits);
 
        bh.b_size = PMD_SIZE;
-       i_mmap_lock_write(mapping);
        length = get_block(inode, block, &bh, write);
        if (length)
                return VM_FAULT_SIGBUS;
+       i_mmap_lock_read(mapping);
 
        /*
         * If the filesystem isn't willing to tell us the length of a hole,
@@ -568,24 +568,14 @@ int __dax_pmd_fault(struct vm_area_struct *vma, unsigned long address,
        if (!buffer_size_valid(&bh) || bh.b_size < PMD_SIZE)
                goto fallback;
 
-       if (buffer_unwritten(&bh) || buffer_new(&bh)) {
-               int i;
-               for (i = 0; i < PTRS_PER_PMD; i++)
-                       clear_pmem(kaddr + i * PAGE_SIZE, PAGE_SIZE);
-               wmb_pmem();
-               count_vm_event(PGMAJFAULT);
-               mem_cgroup_count_vm_event(vma->vm_mm, PGMAJFAULT);
-               result |= VM_FAULT_MAJOR;
-       }
-
        /*
         * If we allocated new storage, make sure no process has any
         * zero pages covering this hole
         */
        if (buffer_new(&bh)) {
-               i_mmap_unlock_write(mapping);
+               i_mmap_unlock_read(mapping);
                unmap_mapping_range(mapping, pgoff << PAGE_SHIFT, PMD_SIZE, 0);
-               i_mmap_lock_write(mapping);
+               i_mmap_lock_read(mapping);
        }
 
        /*
@@ -632,15 +622,25 @@ int __dax_pmd_fault(struct vm_area_struct *vma, unsigned long address,
                if ((length < PMD_SIZE) || (pfn & PG_PMD_COLOUR))
                        goto fallback;
 
+               if (buffer_unwritten(&bh) || buffer_new(&bh)) {
+                       int i;
+                       for (i = 0; i < PTRS_PER_PMD; i++)
+                               clear_pmem(kaddr + i * PAGE_SIZE, PAGE_SIZE);
+                       wmb_pmem();
+                       count_vm_event(PGMAJFAULT);
+                       mem_cgroup_count_vm_event(vma->vm_mm, PGMAJFAULT);
+                       result |= VM_FAULT_MAJOR;
+               }
+
                result |= vmf_insert_pfn_pmd(vma, address, pmd, pfn, write);
        }
 
  out:
+       i_mmap_unlock_read(mapping);
+
        if (buffer_unwritten(&bh))
                complete_unwritten(&bh, !(result & VM_FAULT_ERROR));
 
-       i_mmap_unlock_write(mapping);
-
        return result;
 
  fallback:
index 47728da7702cdf69d2977af996dea42170a8b07d..b46e9fc641960aeba81b48d61b6e933d724b5205 100644 (file)
@@ -63,7 +63,7 @@ config EXT4_FS
          If unsure, say N.
 
 config EXT4_USE_FOR_EXT2
-       bool "Use ext4 for ext2/ext3 file systems"
+       bool "Use ext4 for ext2 file systems"
        depends on EXT4_FS
        depends on EXT2_FS=n
        default y
index e26803fb210d3bf1134f500b85f43802b2ce7e58..560af043770462df6170acd4d523f9d0385884a3 100644 (file)
@@ -165,8 +165,8 @@ int ext4_mpage_readpages(struct address_space *mapping,
                if (pages) {
                        page = list_entry(pages->prev, struct page, lru);
                        list_del(&page->lru);
-                       if (add_to_page_cache_lru(page, mapping,
-                                                 page->index, GFP_KERNEL))
+                       if (add_to_page_cache_lru(page, mapping, page->index,
+                                       GFP_KERNEL & mapping_gfp_mask(mapping)))
                                goto next_page;
                }
 
index 587ac08eabb62bcd47c0a90309e0442262eafd39..29e4599f6fc1c20b73acb2c580ce8383e169c5f2 100644 (file)
@@ -778,19 +778,24 @@ static void bdi_split_work_to_wbs(struct backing_dev_info *bdi,
                                  struct wb_writeback_work *base_work,
                                  bool skip_if_busy)
 {
-       int next_memcg_id = 0;
-       struct bdi_writeback *wb;
-       struct wb_iter iter;
+       struct bdi_writeback *last_wb = NULL;
+       struct bdi_writeback *wb = list_entry_rcu(&bdi->wb_list,
+                                               struct bdi_writeback, bdi_node);
 
        might_sleep();
 restart:
        rcu_read_lock();
-       bdi_for_each_wb(wb, bdi, &iter, next_memcg_id) {
+       list_for_each_entry_continue_rcu(wb, &bdi->wb_list, bdi_node) {
                DEFINE_WB_COMPLETION_ONSTACK(fallback_work_done);
                struct wb_writeback_work fallback_work;
                struct wb_writeback_work *work;
                long nr_pages;
 
+               if (last_wb) {
+                       wb_put(last_wb);
+                       last_wb = NULL;
+               }
+
                /* SYNC_ALL writes out I_DIRTY_TIME too */
                if (!wb_has_dirty_io(wb) &&
                    (base_work->sync_mode == WB_SYNC_NONE ||
@@ -819,12 +824,22 @@ restart:
 
                wb_queue_work(wb, work);
 
-               next_memcg_id = wb->memcg_css->id + 1;
+               /*
+                * Pin @wb so that it stays on @bdi->wb_list.  This allows
+                * continuing iteration from @wb after dropping and
+                * regrabbing rcu read lock.
+                */
+               wb_get(wb);
+               last_wb = wb;
+
                rcu_read_unlock();
                wb_wait_for_completion(bdi, &fallback_work_done);
                goto restart;
        }
        rcu_read_unlock();
+
+       if (last_wb)
+               wb_put(last_wb);
 }
 
 #else  /* CONFIG_CGROUP_WRITEBACK */
@@ -1481,6 +1496,21 @@ static long writeback_sb_inodes(struct super_block *sb,
                wbc_detach_inode(&wbc);
                work->nr_pages -= write_chunk - wbc.nr_to_write;
                wrote += write_chunk - wbc.nr_to_write;
+
+               if (need_resched()) {
+                       /*
+                        * We're trying to balance between building up a nice
+                        * long list of IOs to improve our merge rate, and
+                        * getting those IOs out quickly for anyone throttling
+                        * in balance_dirty_pages().  cond_resched() doesn't
+                        * unplug, so get our IOs out the door before we
+                        * give up the CPU.
+                        */
+                       blk_flush_plug(current);
+                       cond_resched();
+               }
+
+
                spin_lock(&wb->list_lock);
                spin_lock(&inode->i_lock);
                if (!(inode->i_state & I_DIRTY_ALL))
@@ -1488,7 +1518,7 @@ static long writeback_sb_inodes(struct super_block *sb,
                requeue_inode(inode, wb, &wbc);
                inode_sync_complete(inode);
                spin_unlock(&inode->i_lock);
-               cond_resched_lock(&wb->list_lock);
+
                /*
                 * bail out to wb_writeback() often enough to check
                 * background threshold and other termination conditions.
@@ -1842,12 +1872,11 @@ void wakeup_flusher_threads(long nr_pages, enum wb_reason reason)
        rcu_read_lock();
        list_for_each_entry_rcu(bdi, &bdi_list, bdi_list) {
                struct bdi_writeback *wb;
-               struct wb_iter iter;
 
                if (!bdi_has_dirty_io(bdi))
                        continue;
 
-               bdi_for_each_wb(wb, bdi, &iter, 0)
+               list_for_each_entry_rcu(wb, &bdi->wb_list, bdi_node)
                        wb_start_writeback(wb, wb_split_bdi_pages(wb, nr_pages),
                                           false, reason);
        }
@@ -1879,11 +1908,10 @@ static void wakeup_dirtytime_writeback(struct work_struct *w)
        rcu_read_lock();
        list_for_each_entry_rcu(bdi, &bdi_list, bdi_list) {
                struct bdi_writeback *wb;
-               struct wb_iter iter;
 
-               bdi_for_each_wb(wb, bdi, &iter, 0)
-                       if (!list_empty(&bdi->wb.b_dirty_time))
-                               wb_wakeup(&bdi->wb);
+               list_for_each_entry_rcu(wb, &bdi->wb_list, bdi_node)
+                       if (!list_empty(&wb->b_dirty_time))
+                               wb_wakeup(wb);
        }
        rcu_read_unlock();
        schedule_delayed_work(&dirtytime_work, dirtytime_expire_interval * HZ);
index 778a4ddef77a21844b08af82058d3b188371dc01..a7c34274f2076bc36e9cb9797f682988e617417f 100644 (file)
@@ -139,7 +139,8 @@ map_buffer_to_page(struct page *page, struct buffer_head *bh, int page_block)
 static struct bio *
 do_mpage_readpage(struct bio *bio, struct page *page, unsigned nr_pages,
                sector_t *last_block_in_bio, struct buffer_head *map_bh,
-               unsigned long *first_logical_block, get_block_t get_block)
+               unsigned long *first_logical_block, get_block_t get_block,
+               gfp_t gfp)
 {
        struct inode *inode = page->mapping->host;
        const unsigned blkbits = inode->i_blkbits;
@@ -277,8 +278,7 @@ alloc_new:
                                goto out;
                }
                bio = mpage_alloc(bdev, blocks[0] << (blkbits - 9),
-                               min_t(int, nr_pages, BIO_MAX_PAGES),
-                               GFP_KERNEL);
+                               min_t(int, nr_pages, BIO_MAX_PAGES), gfp);
                if (bio == NULL)
                        goto confused;
        }
@@ -361,6 +361,7 @@ mpage_readpages(struct address_space *mapping, struct list_head *pages,
        sector_t last_block_in_bio = 0;
        struct buffer_head map_bh;
        unsigned long first_logical_block = 0;
+       gfp_t gfp = GFP_KERNEL & mapping_gfp_mask(mapping);
 
        map_bh.b_state = 0;
        map_bh.b_size = 0;
@@ -370,12 +371,13 @@ mpage_readpages(struct address_space *mapping, struct list_head *pages,
                prefetchw(&page->flags);
                list_del(&page->lru);
                if (!add_to_page_cache_lru(page, mapping,
-                                       page->index, GFP_KERNEL)) {
+                                       page->index,
+                                       gfp)) {
                        bio = do_mpage_readpage(bio, page,
                                        nr_pages - page_idx,
                                        &last_block_in_bio, &map_bh,
                                        &first_logical_block,
-                                       get_block);
+                                       get_block, gfp);
                }
                page_cache_release(page);
        }
@@ -395,11 +397,12 @@ int mpage_readpage(struct page *page, get_block_t get_block)
        sector_t last_block_in_bio = 0;
        struct buffer_head map_bh;
        unsigned long first_logical_block = 0;
+       gfp_t gfp = GFP_KERNEL & mapping_gfp_mask(page->mapping);
 
        map_bh.b_state = 0;
        map_bh.b_size = 0;
        bio = do_mpage_readpage(bio, page, 1, &last_block_in_bio,
-                       &map_bh, &first_logical_block, get_block);
+                       &map_bh, &first_logical_block, get_block, gfp);
        if (bio)
                mpage_bio_submit(READ, bio);
        return 0;
index 726d211db4842715f71e1911f6940c93b19fe57f..33e9495a31293e2c080b5b0bd2e50523a460ceee 100644 (file)
@@ -1558,8 +1558,6 @@ static int lookup_fast(struct nameidata *nd,
                negative = d_is_negative(dentry);
                if (read_seqcount_retry(&dentry->d_seq, seq))
                        return -ECHILD;
-               if (negative)
-                       return -ENOENT;
 
                /*
                 * This sequence count validates that the parent had no
@@ -1580,6 +1578,12 @@ static int lookup_fast(struct nameidata *nd,
                                goto unlazy;
                        }
                }
+               /*
+                * Note: do negative dentry check after revalidation in
+                * case that drops it.
+                */
+               if (negative)
+                       return -ENOENT;
                path->mnt = mnt;
                path->dentry = dentry;
                if (likely(__follow_mount_rcu(nd, path, inode, seqp)))
index 2714ef835bdd4261cbc301838c050f42896c24c0..be806ead7f4d4abfde04321b78ebace12043925e 100644 (file)
@@ -113,7 +113,8 @@ out:
        return status;
 }
 
-static int nfs_delegation_claim_opens(struct inode *inode, const nfs4_stateid *stateid)
+static int nfs_delegation_claim_opens(struct inode *inode,
+               const nfs4_stateid *stateid, fmode_t type)
 {
        struct nfs_inode *nfsi = NFS_I(inode);
        struct nfs_open_context *ctx;
@@ -140,7 +141,7 @@ again:
                /* Block nfs4_proc_unlck */
                mutex_lock(&sp->so_delegreturn_mutex);
                seq = raw_seqcount_begin(&sp->so_reclaim_seqcount);
-               err = nfs4_open_delegation_recall(ctx, state, stateid);
+               err = nfs4_open_delegation_recall(ctx, state, stateid, type);
                if (!err)
                        err = nfs_delegation_claim_locks(ctx, state, stateid);
                if (!err && read_seqcount_retry(&sp->so_reclaim_seqcount, seq))
@@ -411,7 +412,8 @@ static int nfs_end_delegation_return(struct inode *inode, struct nfs_delegation
        do {
                if (test_bit(NFS_DELEGATION_REVOKED, &delegation->flags))
                        break;
-               err = nfs_delegation_claim_opens(inode, &delegation->stateid);
+               err = nfs_delegation_claim_opens(inode, &delegation->stateid,
+                               delegation->type);
                if (!issync || err != -EAGAIN)
                        break;
                /*
index a44829173e573d1ceca061a9f23b76752f7bb30e..333063e032f01813762bc89f6d6db23ddc696c92 100644 (file)
@@ -54,7 +54,7 @@ void nfs_delegation_reap_unclaimed(struct nfs_client *clp);
 
 /* NFSv4 delegation-related procedures */
 int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid, int issync);
-int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid);
+int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid, fmode_t type);
 int nfs4_lock_delegation_recall(struct file_lock *fl, struct nfs4_state *state, const nfs4_stateid *stateid);
 bool nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode, fmode_t flags);
 
index 38678d9a5cc4a64838e70ff3c915107b828bb65d..4b1d08f56aba7940bf0872265902b2c793b05607 100644 (file)
@@ -166,8 +166,11 @@ nfs_direct_select_verf(struct nfs_direct_req *dreq,
        struct nfs_writeverf *verfp = &dreq->verf;
 
 #ifdef CONFIG_NFS_V4_1
-       if (ds_clp) {
-               /* pNFS is in use, use the DS verf */
+       /*
+        * pNFS is in use, use the DS verf except commit_through_mds is set
+        * for layout segment where nbuckets is zero.
+        */
+       if (ds_clp && dreq->ds_cinfo.nbuckets > 0) {
                if (commit_idx >= 0 && commit_idx < dreq->ds_cinfo.nbuckets)
                        verfp = &dreq->ds_cinfo.buckets[commit_idx].direct_verf;
                else
index b34f2e228601684a7bd9f31d7d8081a8e7623b53..02ec07973bc43003bb76b5aaeb8a950094c9ac60 100644 (file)
@@ -629,23 +629,18 @@ out_put:
        goto out;
 }
 
-static void filelayout_free_fh_array(struct nfs4_filelayout_segment *fl)
+static void _filelayout_free_lseg(struct nfs4_filelayout_segment *fl)
 {
        int i;
 
-       for (i = 0; i < fl->num_fh; i++) {
-               if (!fl->fh_array[i])
-                       break;
-               kfree(fl->fh_array[i]);
+       if (fl->fh_array) {
+               for (i = 0; i < fl->num_fh; i++) {
+                       if (!fl->fh_array[i])
+                               break;
+                       kfree(fl->fh_array[i]);
+               }
+               kfree(fl->fh_array);
        }
-       kfree(fl->fh_array);
-       fl->fh_array = NULL;
-}
-
-static void
-_filelayout_free_lseg(struct nfs4_filelayout_segment *fl)
-{
-       filelayout_free_fh_array(fl);
        kfree(fl);
 }
 
@@ -716,21 +711,21 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo,
                /* Do we want to use a mempool here? */
                fl->fh_array[i] = kmalloc(sizeof(struct nfs_fh), gfp_flags);
                if (!fl->fh_array[i])
-                       goto out_err_free;
+                       goto out_err;
 
                p = xdr_inline_decode(&stream, 4);
                if (unlikely(!p))
-                       goto out_err_free;
+                       goto out_err;
                fl->fh_array[i]->size = be32_to_cpup(p++);
                if (sizeof(struct nfs_fh) < fl->fh_array[i]->size) {
                        printk(KERN_ERR "NFS: Too big fh %d received %d\n",
                               i, fl->fh_array[i]->size);
-                       goto out_err_free;
+                       goto out_err;
                }
 
                p = xdr_inline_decode(&stream, fl->fh_array[i]->size);
                if (unlikely(!p))
-                       goto out_err_free;
+                       goto out_err;
                memcpy(fl->fh_array[i]->data, p, fl->fh_array[i]->size);
                dprintk("DEBUG: %s: fh len %d\n", __func__,
                        fl->fh_array[i]->size);
@@ -739,8 +734,6 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo,
        __free_page(scratch);
        return 0;
 
-out_err_free:
-       filelayout_free_fh_array(fl);
 out_err:
        __free_page(scratch);
        return -EIO;
index d731bbf974aaf1d4bf695c2cb57a99cc586e0258..0f020e4d842168c33a06df276d64c3346472c3b4 100644 (file)
@@ -175,10 +175,12 @@ loff_t nfs42_proc_llseek(struct file *filep, loff_t offset, int whence)
 {
        struct nfs_server *server = NFS_SERVER(file_inode(filep));
        struct nfs4_exception exception = { };
-       int err;
+       loff_t err;
 
        do {
                err = _nfs42_proc_llseek(filep, offset, whence);
+               if (err >= 0)
+                       break;
                if (err == -ENOTSUPP)
                        return -EOPNOTSUPP;
                err = nfs4_handle_exception(server, err, &exception);
index 693b903b48bdfb78808274e90f53971eb1f21244..5133bb18830e8c8b97e68e8f2c55d617ff92a321 100644 (file)
@@ -1127,6 +1127,21 @@ static int nfs4_wait_for_completion_rpc_task(struct rpc_task *task)
        return ret;
 }
 
+static bool nfs4_mode_match_open_stateid(struct nfs4_state *state,
+               fmode_t fmode)
+{
+       switch(fmode & (FMODE_READ|FMODE_WRITE)) {
+       case FMODE_READ|FMODE_WRITE:
+               return state->n_rdwr != 0;
+       case FMODE_WRITE:
+               return state->n_wronly != 0;
+       case FMODE_READ:
+               return state->n_rdonly != 0;
+       }
+       WARN_ON_ONCE(1);
+       return false;
+}
+
 static int can_open_cached(struct nfs4_state *state, fmode_t mode, int open_mode)
 {
        int ret = 0;
@@ -1443,12 +1458,18 @@ nfs4_opendata_check_deleg(struct nfs4_opendata *data, struct nfs4_state *state)
        if (delegation)
                delegation_flags = delegation->flags;
        rcu_read_unlock();
-       if (data->o_arg.claim == NFS4_OPEN_CLAIM_DELEGATE_CUR) {
+       switch (data->o_arg.claim) {
+       default:
+               break;
+       case NFS4_OPEN_CLAIM_DELEGATE_CUR:
+       case NFS4_OPEN_CLAIM_DELEG_CUR_FH:
                pr_err_ratelimited("NFS: Broken NFSv4 server %s is "
                                   "returning a delegation for "
                                   "OPEN(CLAIM_DELEGATE_CUR)\n",
                                   clp->cl_hostname);
-       } else if ((delegation_flags & 1UL<<NFS_DELEGATION_NEED_RECLAIM) == 0)
+               return;
+       }
+       if ((delegation_flags & 1UL<<NFS_DELEGATION_NEED_RECLAIM) == 0)
                nfs_inode_set_delegation(state->inode,
                                         data->owner->so_cred,
                                         &data->o_res);
@@ -1571,17 +1592,13 @@ static struct nfs4_opendata *nfs4_open_recoverdata_alloc(struct nfs_open_context
        return opendata;
 }
 
-static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, fmode_t fmode, struct nfs4_state **res)
+static int nfs4_open_recover_helper(struct nfs4_opendata *opendata,
+               fmode_t fmode)
 {
        struct nfs4_state *newstate;
        int ret;
 
-       if ((opendata->o_arg.claim == NFS4_OPEN_CLAIM_DELEGATE_CUR ||
-            opendata->o_arg.claim == NFS4_OPEN_CLAIM_DELEG_CUR_FH) &&
-           (opendata->o_arg.u.delegation_type & fmode) != fmode)
-               /* This mode can't have been delegated, so we must have
-                * a valid open_stateid to cover it - not need to reclaim.
-                */
+       if (!nfs4_mode_match_open_stateid(opendata->state, fmode))
                return 0;
        opendata->o_arg.open_flags = 0;
        opendata->o_arg.fmode = fmode;
@@ -1597,14 +1614,14 @@ static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, fmode_t fmod
        newstate = nfs4_opendata_to_nfs4_state(opendata);
        if (IS_ERR(newstate))
                return PTR_ERR(newstate);
+       if (newstate != opendata->state)
+               ret = -ESTALE;
        nfs4_close_state(newstate, fmode);
-       *res = newstate;
-       return 0;
+       return ret;
 }
 
 static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *state)
 {
-       struct nfs4_state *newstate;
        int ret;
 
        /* Don't trigger recovery in nfs_test_and_clear_all_open_stateid */
@@ -1615,27 +1632,15 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *
        clear_bit(NFS_DELEGATED_STATE, &state->flags);
        clear_bit(NFS_OPEN_STATE, &state->flags);
        smp_rmb();
-       if (state->n_rdwr != 0) {
-               ret = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE, &newstate);
-               if (ret != 0)
-                       return ret;
-               if (newstate != state)
-                       return -ESTALE;
-       }
-       if (state->n_wronly != 0) {
-               ret = nfs4_open_recover_helper(opendata, FMODE_WRITE, &newstate);
-               if (ret != 0)
-                       return ret;
-               if (newstate != state)
-                       return -ESTALE;
-       }
-       if (state->n_rdonly != 0) {
-               ret = nfs4_open_recover_helper(opendata, FMODE_READ, &newstate);
-               if (ret != 0)
-                       return ret;
-               if (newstate != state)
-                       return -ESTALE;
-       }
+       ret = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE);
+       if (ret != 0)
+               return ret;
+       ret = nfs4_open_recover_helper(opendata, FMODE_WRITE);
+       if (ret != 0)
+               return ret;
+       ret = nfs4_open_recover_helper(opendata, FMODE_READ);
+       if (ret != 0)
+               return ret;
        /*
         * We may have performed cached opens for all three recoveries.
         * Check if we need to update the current stateid.
@@ -1759,18 +1764,35 @@ static int nfs4_handle_delegation_recall_error(struct nfs_server *server, struct
        return err;
 }
 
-int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid)
+int nfs4_open_delegation_recall(struct nfs_open_context *ctx,
+               struct nfs4_state *state, const nfs4_stateid *stateid,
+               fmode_t type)
 {
        struct nfs_server *server = NFS_SERVER(state->inode);
        struct nfs4_opendata *opendata;
-       int err;
+       int err = 0;
 
        opendata = nfs4_open_recoverdata_alloc(ctx, state,
                        NFS4_OPEN_CLAIM_DELEG_CUR_FH);
        if (IS_ERR(opendata))
                return PTR_ERR(opendata);
        nfs4_stateid_copy(&opendata->o_arg.u.delegation, stateid);
-       err = nfs4_open_recover(opendata, state);
+       write_seqlock(&state->seqlock);
+       nfs4_stateid_copy(&state->stateid, &state->open_stateid);
+       write_sequnlock(&state->seqlock);
+       clear_bit(NFS_DELEGATED_STATE, &state->flags);
+       switch (type & (FMODE_READ|FMODE_WRITE)) {
+       case FMODE_READ|FMODE_WRITE:
+       case FMODE_WRITE:
+               err = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE);
+               if (err)
+                       break;
+               err = nfs4_open_recover_helper(opendata, FMODE_WRITE);
+               if (err)
+                       break;
+       case FMODE_READ:
+               err = nfs4_open_recover_helper(opendata, FMODE_READ);
+       }
        nfs4_opendata_put(opendata);
        return nfs4_handle_delegation_recall_error(server, state, stateid, err);
 }
@@ -1850,6 +1872,8 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data)
        data->rpc_done = 0;
        data->rpc_status = 0;
        data->timestamp = jiffies;
+       if (data->is_recover)
+               nfs4_set_sequence_privileged(&data->c_arg.seq_args);
        task = rpc_run_task(&task_setup_data);
        if (IS_ERR(task))
                return PTR_ERR(task);
@@ -2645,6 +2669,15 @@ out:
        return err;
 }
 
+static bool
+nfs4_wait_on_layoutreturn(struct inode *inode, struct rpc_task *task)
+{
+       if (inode == NULL || !nfs_have_layout(inode))
+               return false;
+
+       return pnfs_wait_on_layoutreturn(inode, task);
+}
+
 struct nfs4_closedata {
        struct inode *inode;
        struct nfs4_state *state;
@@ -2763,6 +2796,11 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
                goto out_no_action;
        }
 
+       if (nfs4_wait_on_layoutreturn(inode, task)) {
+               nfs_release_seqid(calldata->arg.seqid);
+               goto out_wait;
+       }
+
        if (calldata->arg.fmode == 0)
                task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE];
        if (calldata->roc)
@@ -5308,6 +5346,9 @@ static void nfs4_delegreturn_prepare(struct rpc_task *task, void *data)
 
        d_data = (struct nfs4_delegreturndata *)data;
 
+       if (nfs4_wait_on_layoutreturn(d_data->inode, task))
+               return;
+
        if (d_data->roc)
                pnfs_roc_get_barrier(d_data->inode, &d_data->roc_barrier);
 
@@ -7800,39 +7841,46 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata)
                        dprintk("%s: NFS4ERR_RECALLCONFLICT waiting %lu\n",
                                __func__, delay);
                        rpc_delay(task, delay);
-                       task->tk_status = 0;
-                       rpc_restart_call_prepare(task);
-                       goto out; /* Do not call nfs4_async_handle_error() */
+                       /* Do not call nfs4_async_handle_error() */
+                       goto out_restart;
                }
                break;
        case -NFS4ERR_EXPIRED:
        case -NFS4ERR_BAD_STATEID:
                spin_lock(&inode->i_lock);
-               lo = NFS_I(inode)->layout;
-               if (!lo || list_empty(&lo->plh_segs)) {
+               if (nfs4_stateid_match(&lgp->args.stateid,
+                                       &lgp->args.ctx->state->stateid)) {
                        spin_unlock(&inode->i_lock);
                        /* If the open stateid was bad, then recover it. */
                        state = lgp->args.ctx->state;
-               } else {
+                       break;
+               }
+               lo = NFS_I(inode)->layout;
+               if (lo && nfs4_stateid_match(&lgp->args.stateid,
+                                       &lo->plh_stateid)) {
                        LIST_HEAD(head);
 
                        /*
                         * Mark the bad layout state as invalid, then retry
                         * with the current stateid.
                         */
+                       set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags);
                        pnfs_mark_matching_lsegs_invalid(lo, &head, NULL);
                        spin_unlock(&inode->i_lock);
                        pnfs_free_lseg_list(&head);
-       
-                       task->tk_status = 0;
-                       rpc_restart_call_prepare(task);
-               }
+               } else
+                       spin_unlock(&inode->i_lock);
+               goto out_restart;
        }
        if (nfs4_async_handle_error(task, server, state, NULL) == -EAGAIN)
-               rpc_restart_call_prepare(task);
+               goto out_restart;
 out:
        dprintk("<-- %s\n", __func__);
        return;
+out_restart:
+       task->tk_status = 0;
+       rpc_restart_call_prepare(task);
+       return;
 out_overflow:
        task->tk_status = -EOVERFLOW;
        goto out;
index da73bc4432385748a5224a4fddf302ab2bb11cfa..d854693a15b0e2443779986552d29d9db3f6cdc2 100644 (file)
@@ -1481,7 +1481,7 @@ restart:
                                        spin_unlock(&state->state_lock);
                                }
                                nfs4_put_open_state(state);
-                               clear_bit(NFS4CLNT_RECLAIM_NOGRACE,
+                               clear_bit(NFS_STATE_RECLAIM_NOGRACE,
                                        &state->flags);
                                spin_lock(&sp->so_lock);
                                goto restart;
@@ -1725,7 +1725,8 @@ restart:
                        if (!test_and_clear_bit(ops->owner_flag_bit,
                                                        &sp->so_flags))
                                continue;
-                       atomic_inc(&sp->so_count);
+                       if (!atomic_inc_not_zero(&sp->so_count))
+                               continue;
                        spin_unlock(&clp->cl_lock);
                        rcu_read_unlock();
 
index 28df12e525bac5857c0d41aba62d558db82f526a..671cf68fe56bed7a457fddd4ccdd5913509ff1bd 100644 (file)
@@ -409,7 +409,7 @@ DECLARE_EVENT_CLASS(nfs4_open_event,
                        __entry->flags = flags;
                        __entry->fmode = (__force unsigned int)ctx->mode;
                        __entry->dev = ctx->dentry->d_sb->s_dev;
-                       if (!IS_ERR(state))
+                       if (!IS_ERR_OR_NULL(state))
                                inode = state->inode;
                        if (inode != NULL) {
                                __entry->fileid = NFS_FILEID(inode);
index 7c5718ba625e28ff661868dd2d32fb438042a7bb..fe3ddd20ff89095331ad854bafb4b26bc019e01e 100644 (file)
@@ -508,7 +508,7 @@ size_t nfs_generic_pg_test(struct nfs_pageio_descriptor *desc,
         * for it without upsetting the slab allocator.
         */
        if (((mirror->pg_count + req->wb_bytes) >> PAGE_SHIFT) *
-                       sizeof(struct page) > PAGE_SIZE)
+                       sizeof(struct page *) > PAGE_SIZE)
                return 0;
 
        return min(mirror->pg_bsize - mirror->pg_count, (size_t)req->wb_bytes);
index ba1246433794f0b917ac84738b2d952fd782b2fd..8abe27165ad044a22ce4079cc410d9052a1c3378 100644 (file)
@@ -1104,20 +1104,15 @@ bool pnfs_roc(struct inode *ino)
                        mark_lseg_invalid(lseg, &tmp_list);
                        found = true;
                }
-       /* pnfs_prepare_layoutreturn() grabs lo ref and it will be put
-        * in pnfs_roc_release(). We don't really send a layoutreturn but
-        * still want others to view us like we are sending one!
-        *
-        * If pnfs_prepare_layoutreturn() fails, it means someone else is doing
-        * LAYOUTRETURN, so we proceed like there are no layouts to return.
-        *
-        * ROC in three conditions:
+       /* ROC in two conditions:
         * 1. there are ROC lsegs
         * 2. we don't send layoutreturn
-        * 3. no others are sending layoutreturn
         */
-       if (found && !layoutreturn && pnfs_prepare_layoutreturn(lo))
+       if (found && !layoutreturn) {
+               /* lo ref dropped in pnfs_roc_release() */
+               pnfs_get_layout_hdr(lo);
                roc = true;
+       }
 
 out_noroc:
        spin_unlock(&ino->i_lock);
@@ -1172,6 +1167,26 @@ void pnfs_roc_get_barrier(struct inode *ino, u32 *barrier)
        spin_unlock(&ino->i_lock);
 }
 
+bool pnfs_wait_on_layoutreturn(struct inode *ino, struct rpc_task *task)
+{
+       struct nfs_inode *nfsi = NFS_I(ino);
+        struct pnfs_layout_hdr *lo;
+        bool sleep = false;
+
+       /* we might not have grabbed lo reference. so need to check under
+        * i_lock */
+        spin_lock(&ino->i_lock);
+        lo = nfsi->layout;
+        if (lo && test_bit(NFS_LAYOUT_RETURN, &lo->plh_flags))
+                sleep = true;
+        spin_unlock(&ino->i_lock);
+
+        if (sleep)
+                rpc_sleep_on(&NFS_SERVER(ino)->roc_rpcwaitq, task, NULL);
+
+        return sleep;
+}
+
 /*
  * Compare two layout segments for sorting into layout cache.
  * We want to preferentially return RW over RO layouts, so ensure those
index 78c9351ff117bdf56e04bbcf1d696ccbbfb6b866..d1990e90e7a02cb048b909d67879198b26e62c08 100644 (file)
@@ -270,6 +270,7 @@ bool pnfs_roc(struct inode *ino);
 void pnfs_roc_release(struct inode *ino);
 void pnfs_roc_set_barrier(struct inode *ino, u32 barrier);
 void pnfs_roc_get_barrier(struct inode *ino, u32 *barrier);
+bool pnfs_wait_on_layoutreturn(struct inode *ino, struct rpc_task *task);
 void pnfs_set_layoutcommit(struct inode *, struct pnfs_layout_segment *, loff_t);
 void pnfs_cleanup_layoutcommit(struct nfs4_layoutcommit_data *data);
 int pnfs_layoutcommit_inode(struct inode *inode, bool sync);
@@ -639,6 +640,12 @@ pnfs_roc_get_barrier(struct inode *ino, u32 *barrier)
 {
 }
 
+static inline bool
+pnfs_wait_on_layoutreturn(struct inode *ino, struct rpc_task *task)
+{
+       return false;
+}
+
 static inline void set_pnfs_layoutdriver(struct nfs_server *s,
                                         const struct nfs_fh *mntfh, u32 id)
 {
index ae0ff7a11b40339a728ca819283400c7f5e25a42..01b8cc8e8cfc436784052bf5e92a7c21a1230012 100644 (file)
@@ -72,6 +72,9 @@ void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio)
 {
        struct nfs_pgio_mirror *mirror;
 
+       if (pgio->pg_ops && pgio->pg_ops->pg_cleanup)
+               pgio->pg_ops->pg_cleanup(pgio);
+
        pgio->pg_ops = &nfs_pgio_rw_ops;
 
        /* read path should never have more than one mirror */
index 388f48079c43839fa9c8222d78556282920858f2..75ab7622e0cc193bab28f2ba5bb56d37e5f49465 100644 (file)
@@ -569,19 +569,17 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
        if (!nfs_pageio_add_request(pgio, req)) {
                nfs_redirty_request(req);
                ret = pgio->pg_error;
-       }
+       } else
+               nfs_add_stats(page_file_mapping(page)->host,
+                               NFSIOS_WRITEPAGES, 1);
 out:
        return ret;
 }
 
 static int nfs_do_writepage(struct page *page, struct writeback_control *wbc, struct nfs_pageio_descriptor *pgio)
 {
-       struct inode *inode = page_file_mapping(page)->host;
        int ret;
 
-       nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGE);
-       nfs_add_stats(inode, NFSIOS_WRITEPAGES, 1);
-
        nfs_pageio_cond_complete(pgio, page_file_index(page));
        ret = nfs_page_async_flush(pgio, page, wbc->sync_mode == WB_SYNC_NONE);
        if (ret == -EAGAIN) {
@@ -597,9 +595,11 @@ static int nfs_do_writepage(struct page *page, struct writeback_control *wbc, st
 static int nfs_writepage_locked(struct page *page, struct writeback_control *wbc)
 {
        struct nfs_pageio_descriptor pgio;
+       struct inode *inode = page_file_mapping(page)->host;
        int err;
 
-       nfs_pageio_init_write(&pgio, page->mapping->host, wb_priority(wbc),
+       nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGE);
+       nfs_pageio_init_write(&pgio, inode, wb_priority(wbc),
                                false, &nfs_async_write_completion_ops);
        err = nfs_do_writepage(page, wbc, &pgio);
        nfs_pageio_complete(&pgio);
@@ -1223,7 +1223,7 @@ static int nfs_can_extend_write(struct file *file, struct page *page, struct ino
                return 1;
        if (!flctx || (list_empty_careful(&flctx->flc_flock) &&
                       list_empty_careful(&flctx->flc_posix)))
-               return 0;
+               return 1;
 
        /* Check to see if there are whole file write locks */
        ret = 0;
@@ -1351,6 +1351,9 @@ void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio)
 {
        struct nfs_pgio_mirror *mirror;
 
+       if (pgio->pg_ops && pgio->pg_ops->pg_cleanup)
+               pgio->pg_ops->pg_cleanup(pgio);
+
        pgio->pg_ops = &nfs_pgio_rw_ops;
 
        nfs_pageio_stop_mirroring(pgio);
index cdefaa331a0719e88df91ef7c04c32706ae199a1..c29d9421bd5e1f8c890178c6ec961899b319ceef 100644 (file)
@@ -56,14 +56,6 @@ nfsd4_block_proc_layoutget(struct inode *inode, const struct svc_fh *fhp,
        u32 device_generation = 0;
        int error;
 
-       /*
-        * We do not attempt to support I/O smaller than the fs block size,
-        * or not aligned to it.
-        */
-       if (args->lg_minlength < block_size) {
-               dprintk("pnfsd: I/O too small\n");
-               goto out_layoutunavailable;
-       }
        if (seg->offset & (block_size - 1)) {
                dprintk("pnfsd: I/O misaligned\n");
                goto out_layoutunavailable;
index 46b8b2bbc95ae7c1ddd776d093215f3557f76cc7..ce38b4ccc9ab6c52c796a148b496bab0d8d46510 100644 (file)
@@ -1439,6 +1439,7 @@ int dlm_master_request_handler(struct o2net_msg *msg, u32 len, void *data,
        int found, ret;
        int set_maybe;
        int dispatch_assert = 0;
+       int dispatched = 0;
 
        if (!dlm_grab(dlm))
                return DLM_MASTER_RESP_NO;
@@ -1657,16 +1658,20 @@ send_response:
                if (ret < 0) {
                        mlog(ML_ERROR, "failed to dispatch assert master work\n");
                        response = DLM_MASTER_RESP_ERROR;
+                       spin_unlock(&res->spinlock);
                        dlm_lockres_put(res);
-               } else
+               } else {
+                       dispatched = 1;
                        __dlm_lockres_grab_inflight_worker(dlm, res);
-               spin_unlock(&res->spinlock);
+                       spin_unlock(&res->spinlock);
+               }
        } else {
                if (res)
                        dlm_lockres_put(res);
        }
 
-       dlm_put(dlm);
+       if (!dispatched)
+               dlm_put(dlm);
        return response;
 }
 
@@ -2090,7 +2095,6 @@ int dlm_dispatch_assert_master(struct dlm_ctxt *dlm,
 
 
        /* queue up work for dlm_assert_master_worker */
-       dlm_grab(dlm);  /* get an extra ref for the work item */
        dlm_init_work_item(dlm, item, dlm_assert_master_worker, NULL);
        item->u.am.lockres = res; /* already have a ref */
        /* can optionally ignore node numbers higher than this node */
index ce12e0b1a31f180371e6ac010cac3e37fdfbad09..58eaa5c0d387051301a089f0d234d4b69bf18d51 100644 (file)
@@ -1694,6 +1694,7 @@ int dlm_master_requery_handler(struct o2net_msg *msg, u32 len, void *data,
        unsigned int hash;
        int master = DLM_LOCK_RES_OWNER_UNKNOWN;
        u32 flags = DLM_ASSERT_MASTER_REQUERY;
+       int dispatched = 0;
 
        if (!dlm_grab(dlm)) {
                /* since the domain has gone away on this
@@ -1719,9 +1720,11 @@ int dlm_master_requery_handler(struct o2net_msg *msg, u32 len, void *data,
                                dlm_put(dlm);
                                /* sender will take care of this and retry */
                                return ret;
-                       } else
+                       } else {
+                               dispatched = 1;
                                __dlm_lockres_grab_inflight_worker(dlm, res);
-                       spin_unlock(&res->spinlock);
+                               spin_unlock(&res->spinlock);
+                       }
                } else {
                        /* put.. incase we are not the master */
                        spin_unlock(&res->spinlock);
@@ -1730,7 +1733,8 @@ int dlm_master_requery_handler(struct o2net_msg *msg, u32 len, void *data,
        }
        spin_unlock(&dlm->spinlock);
 
-       dlm_put(dlm);
+       if (!dispatched)
+               dlm_put(dlm);
        return master;
 }
 
index 84d693d374284b580208fec3b8eb3c57bdd4195c..871fcb67be9741f2aab81f3d6552306dedf4c967 100644 (file)
@@ -81,11 +81,11 @@ static int ovl_copy_up_data(struct path *old, struct path *new, loff_t len)
        if (len == 0)
                return 0;
 
-       old_file = ovl_path_open(old, O_RDONLY);
+       old_file = ovl_path_open(old, O_LARGEFILE | O_RDONLY);
        if (IS_ERR(old_file))
                return PTR_ERR(old_file);
 
-       new_file = ovl_path_open(new, O_WRONLY);
+       new_file = ovl_path_open(new, O_LARGEFILE | O_WRONLY);
        if (IS_ERR(new_file)) {
                error = PTR_ERR(new_file);
                goto out_fput;
@@ -267,7 +267,7 @@ out:
 
 out_cleanup:
        ovl_cleanup(wdir, newdentry);
-       goto out;
+       goto out2;
 }
 
 /*
index d9da5a4e93821ddbee9f2fb449666c207417e523..ec0c2a050043afbb3eff4c7451930dc6d86006ec 100644 (file)
@@ -363,6 +363,9 @@ struct inode *ovl_d_select_inode(struct dentry *dentry, unsigned file_flags)
                ovl_path_upper(dentry, &realpath);
        }
 
+       if (realpath.dentry->d_flags & DCACHE_OP_SELECT_INODE)
+               return realpath.dentry->d_op->d_select_inode(realpath.dentry, file_flags);
+
        return d_backing_inode(realpath.dentry);
 }
 
index 79073d68b475d71b0f87902550b3eeef945885b5..e38ee0fed24a2f7a343f294a793b6abea93f6f97 100644 (file)
@@ -544,6 +544,7 @@ static void ovl_put_super(struct super_block *sb)
        mntput(ufs->upper_mnt);
        for (i = 0; i < ufs->numlower; i++)
                mntput(ufs->lower_mnt[i]);
+       kfree(ufs->lower_mnt);
 
        kfree(ufs->config.lowerdir);
        kfree(ufs->config.upperdir);
@@ -1048,6 +1049,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
                oe->lowerstack[i].dentry = stack[i].dentry;
                oe->lowerstack[i].mnt = ufs->lower_mnt[i];
        }
+       kfree(stack);
 
        root_dentry->d_fsdata = oe;
 
index ba1323a94924962299d27cbe67d76ff4e0056bb9..a586467f6ff6c73a4f31234fd96fce0a7b0dc34b 100644 (file)
@@ -70,6 +70,7 @@ int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize)
        unsigned order;
        void *data;
        int ret;
+       gfp_t gfp = mapping_gfp_mask(inode->i_mapping);
 
        /* make various checks */
        order = get_order(newsize);
@@ -84,7 +85,7 @@ int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize)
 
        /* allocate enough contiguous pages to be able to satisfy the
         * request */
-       pages = alloc_pages(mapping_gfp_mask(inode->i_mapping), order);
+       pages = alloc_pages(gfp, order);
        if (!pages)
                return -ENOMEM;
 
@@ -108,7 +109,7 @@ int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize)
                struct page *page = pages + loop;
 
                ret = add_to_page_cache_lru(page, inode->i_mapping, loop,
-                                       GFP_KERNEL);
+                                       gfp);
                if (ret < 0)
                        goto add_error;
 
index 96f3448b6eb40c0682ec915a71d5030d5bdf4283..fd65b3f1923ccdb609ee29601604624abf32333d 100644 (file)
@@ -652,11 +652,8 @@ int ubifs_init_security(struct inode *dentry, struct inode *inode,
 {
        int err;
 
-       mutex_lock(&inode->i_mutex);
        err = security_inode_init_security(inode, dentry, qstr,
                                           &init_xattrs, 0);
-       mutex_unlock(&inode->i_mutex);
-
        if (err) {
                struct ubifs_info *c = dentry->i_sb->s_fs_info;
                ubifs_err(c, "cannot initialize security for inode %lu, error %d",
index 634e676072cb738467b61064beaa5fa4b98cf672..50311703135bc8c699bcc3d26d0b9aa24b5277f3 100644 (file)
@@ -467,8 +467,8 @@ static int userfaultfd_release(struct inode *inode, struct file *file)
         * the fault_*wqh.
         */
        spin_lock(&ctx->fault_pending_wqh.lock);
-       __wake_up_locked_key(&ctx->fault_pending_wqh, TASK_NORMAL, 0, &range);
-       __wake_up_locked_key(&ctx->fault_wqh, TASK_NORMAL, 0, &range);
+       __wake_up_locked_key(&ctx->fault_pending_wqh, TASK_NORMAL, &range);
+       __wake_up_locked_key(&ctx->fault_wqh, TASK_NORMAL, &range);
        spin_unlock(&ctx->fault_pending_wqh.lock);
 
        wake_up_poll(&ctx->fd_wqh, POLLHUP);
@@ -650,10 +650,10 @@ static void __wake_userfault(struct userfaultfd_ctx *ctx,
        spin_lock(&ctx->fault_pending_wqh.lock);
        /* wake all in the range and autoremove */
        if (waitqueue_active(&ctx->fault_pending_wqh))
-               __wake_up_locked_key(&ctx->fault_pending_wqh, TASK_NORMAL, 0,
+               __wake_up_locked_key(&ctx->fault_pending_wqh, TASK_NORMAL,
                                     range);
        if (waitqueue_active(&ctx->fault_wqh))
-               __wake_up_locked_key(&ctx->fault_wqh, TASK_NORMAL, 0, range);
+               __wake_up_locked_key(&ctx->fault_wqh, TASK_NORMAL, range);
        spin_unlock(&ctx->fault_pending_wqh.lock);
 }
 
@@ -1287,8 +1287,10 @@ static struct file *userfaultfd_file_create(int flags)
 
        file = anon_inode_getfile("[userfaultfd]", &userfaultfd_fops, ctx,
                                  O_RDWR | (flags & UFFD_SHARED_FCNTL_FLAGS));
-       if (IS_ERR(file))
+       if (IS_ERR(file)) {
+               mmput(ctx->mm);
                kmem_cache_free(userfaultfd_ctx_cachep, ctx);
+       }
 out:
        return file;
 }
index 97eea0e4c01675069557019efc2c0fc2ec2873bb..1cad8b2d460c3eabf9a7cf833fa6ece8785fe6e7 100644 (file)
@@ -3,7 +3,7 @@
 
 #include <linux/notifier.h>
 
-#if defined(CONFIG_ACPI_BUTTON) || defined(CONFIG_ACPI_BUTTON_MODULE)
+#if IS_ENABLED(CONFIG_ACPI_BUTTON)
 extern int acpi_lid_notifier_register(struct notifier_block *nb);
 extern int acpi_lid_notifier_unregister(struct notifier_block *nb);
 extern int acpi_lid_open(void);
@@ -20,6 +20,6 @@ static inline int acpi_lid_open(void)
 {
        return 1;
 }
-#endif /* defined(CONFIG_ACPI_BUTTON) || defined(CONFIG_ACPI_BUTTON_MODULE) */
+#endif /* IS_ENABLED(CONFIG_ACPI_BUTTON) */
 
 #endif /* ACPI_BUTTON_H */
index e840b294c6f5beb2f8a178aa0d3bbb8e92040e40..c62392d9b52ad6ee06b98a3fd9e6832c73ebcae1 100644 (file)
@@ -24,7 +24,7 @@ enum acpi_backlight_type {
        acpi_backlight_native,
 };
 
-#if (defined CONFIG_ACPI_VIDEO || defined CONFIG_ACPI_VIDEO_MODULE)
+#if IS_ENABLED(CONFIG_ACPI_VIDEO)
 extern int acpi_video_register(void);
 extern void acpi_video_unregister(void);
 extern int acpi_video_get_edid(struct acpi_device *device, int type,
index f20f407ce45d29fddcf98bd8fcfe270349fd0b92..4b4b056a6eb00ee844a5af970c2ce0c2e86d87d6 100644 (file)
@@ -73,7 +73,7 @@
  * Convert a physical address to a Page Frame Number and back
  */
 #define        __phys_to_pfn(paddr)    ((unsigned long)((paddr) >> PAGE_SHIFT))
-#define        __pfn_to_phys(pfn)      ((pfn) << PAGE_SHIFT)
+#define        __pfn_to_phys(pfn)      PFN_PHYS(pfn)
 
 #define page_to_pfn __page_to_pfn
 #define pfn_to_page __pfn_to_page
index 83bfb87f5bf18e92ea794dd3ca3afec1b1ba6f11..e2aadbc7151f4cd69b8745e80a0af403257f1678 100644 (file)
@@ -111,8 +111,8 @@ static inline void queued_spin_unlock_wait(struct qspinlock *lock)
                cpu_relax();
 }
 
-#ifndef virt_queued_spin_lock
-static __always_inline bool virt_queued_spin_lock(struct qspinlock *lock)
+#ifndef virt_spin_lock
+static __always_inline bool virt_spin_lock(struct qspinlock *lock)
 {
        return false;
 }
index 94f9ea8abcae35af8ca36560403fbd25facb7c65..011dde083f231e763e4c96fcc7fb3cb9b6ce23c7 100644 (file)
@@ -1,15 +1,10 @@
 #ifndef _ASM_WORD_AT_A_TIME_H
 #define _ASM_WORD_AT_A_TIME_H
 
-/*
- * This says "generic", but it's actually big-endian only.
- * Little-endian can use more efficient versions of these
- * interfaces, see for example
- *      arch/x86/include/asm/word-at-a-time.h
- * for those.
- */
-
 #include <linux/kernel.h>
+#include <asm/byteorder.h>
+
+#ifdef __BIG_ENDIAN
 
 struct word_at_a_time {
        const unsigned long high_bits, low_bits;
@@ -53,4 +48,73 @@ static inline bool has_zero(unsigned long val, unsigned long *data, const struct
 #define zero_bytemask(mask) (~1ul << __fls(mask))
 #endif
 
+#else
+
+/*
+ * The optimal byte mask counting is probably going to be something
+ * that is architecture-specific. If you have a reliably fast
+ * bit count instruction, that might be better than the multiply
+ * and shift, for example.
+ */
+struct word_at_a_time {
+       const unsigned long one_bits, high_bits;
+};
+
+#define WORD_AT_A_TIME_CONSTANTS { REPEAT_BYTE(0x01), REPEAT_BYTE(0x80) }
+
+#ifdef CONFIG_64BIT
+
+/*
+ * Jan Achrenius on G+: microoptimized version of
+ * the simpler "(mask & ONEBYTES) * ONEBYTES >> 56"
+ * that works for the bytemasks without having to
+ * mask them first.
+ */
+static inline long count_masked_bytes(unsigned long mask)
+{
+       return mask*0x0001020304050608ul >> 56;
+}
+
+#else  /* 32-bit case */
+
+/* Carl Chatfield / Jan Achrenius G+ version for 32-bit */
+static inline long count_masked_bytes(long mask)
+{
+       /* (000000 0000ff 00ffff ffffff) -> ( 1 1 2 3 ) */
+       long a = (0x0ff0001+mask) >> 23;
+       /* Fix the 1 for 00 case */
+       return a & mask;
+}
+
+#endif
+
+/* Return nonzero if it has a zero */
+static inline unsigned long has_zero(unsigned long a, unsigned long *bits, const struct word_at_a_time *c)
+{
+       unsigned long mask = ((a - c->one_bits) & ~a) & c->high_bits;
+       *bits = mask;
+       return mask;
+}
+
+static inline unsigned long prep_zero_mask(unsigned long a, unsigned long bits, const struct word_at_a_time *c)
+{
+       return bits;
+}
+
+static inline unsigned long create_zero_mask(unsigned long bits)
+{
+       bits = (bits - 1) & ~bits;
+       return bits >> 7;
+}
+
+/* The mask we created is directly usable as a bytemask */
+#define zero_bytemask(mask) (mask)
+
+static inline unsigned long find_zero(unsigned long mask)
+{
+       return count_masked_bytes(mask);
+}
+
+#endif /* __BIG_ENDIAN */
+
 #endif /* _ASM_WORD_AT_A_TIME_H */
index 2a747a91fdede982354438e1c48fc1a332d06885..3febb4b9fce9243793fbaf3e8dbb331fe6adf81d 100644 (file)
@@ -240,5 +240,6 @@ extern void drm_kms_helper_hotplug_event(struct drm_device *dev);
 
 extern void drm_kms_helper_poll_disable(struct drm_device *dev);
 extern void drm_kms_helper_poll_enable(struct drm_device *dev);
+extern void drm_kms_helper_poll_enable_locked(struct drm_device *dev);
 
 #endif
index 499e9f625aeffb2f618458b45121a6a6286e6e3e..0212d139a480909a216da244ffd8aadf6effa630 100644 (file)
 #define MODE_I2C_READ  4
 #define MODE_I2C_STOP  8
 
+/* DP 1.2 MST PORTs - Section 2.5.1 v1.2a spec */
+#define DP_MST_PHYSICAL_PORT_0 0
+#define DP_MST_LOGICAL_PORT_0 8
+
 #define DP_LINK_STATUS_SIZE       6
 bool drm_dp_channel_eq_ok(const u8 link_status[DP_LINK_STATUS_SIZE],
                          int lane_count);
index 86d0b25ed0547db2f63606af97d8bf9e966e39db..5340099741aec8c48575b1c1056f23903e150ed6 100644 (file)
@@ -253,6 +253,7 @@ struct drm_dp_remote_dpcd_write {
        u8 *bytes;
 };
 
+#define DP_REMOTE_I2C_READ_MAX_TRANSACTIONS 4
 struct drm_dp_remote_i2c_read {
        u8 num_transactions;
        u8 port_number;
@@ -262,7 +263,7 @@ struct drm_dp_remote_i2c_read {
                u8 *bytes;
                u8 no_stop_bit;
                u8 i2c_transaction_delay;
-       } transactions[4];
+       } transactions[DP_REMOTE_I2C_READ_MAX_TRANSACTIONS];
        u8 read_i2c_device_id;
        u8 num_bytes_read;
 };
@@ -374,6 +375,7 @@ struct drm_dp_mst_topology_mgr;
 struct drm_dp_mst_topology_cbs {
        /* create a connector for a port */
        struct drm_connector *(*add_connector)(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, const char *path);
+       void (*register_connector)(struct drm_connector *connector);
        void (*destroy_connector)(struct drm_dp_mst_topology_mgr *mgr,
                                  struct drm_connector *connector);
        void (*hotplug)(struct drm_dp_mst_topology_mgr *mgr);
index d901f1a47be6c5e4af71ea7543f7dc7163eca2f9..4e14dac282bb6c963440593090bc060afecf8130 100644 (file)
 #define VGIC_V3_MAX_LRS                16
 #define VGIC_MAX_IRQS          1024
 #define VGIC_V2_MAX_CPUS       8
-
-/* Sanity checks... */
-#if (KVM_MAX_VCPUS > 255)
-#error Too many KVM VCPUs, the VGIC only supports up to 255 VCPUs for now
-#endif
+#define VGIC_V3_MAX_CPUS       255
 
 #if (VGIC_NR_IRQS_LEGACY & 31)
 #error "VGIC_NR_IRQS must be a multiple of 32"
index 7235c4851460e6dc79d6d95a53d368b8f06e3525..43856d19cf4d8abc8942849202485fe76244135d 100644 (file)
@@ -217,6 +217,7 @@ struct pci_dev;
 
 int acpi_pci_irq_enable (struct pci_dev *dev);
 void acpi_penalize_isa_irq(int irq, int active);
+bool acpi_isa_irq_available(int irq);
 void acpi_penalize_sci_irq(int irq, int trigger, int polarity);
 void acpi_pci_irq_disable (struct pci_dev *dev);
 
index a23209b43842106c6a74de8a51d6b4b752613157..1b4d69f68c33cc73ad99a1136b2408c71e763fb8 100644 (file)
@@ -116,6 +116,8 @@ struct bdi_writeback {
        struct list_head work_list;
        struct delayed_work dwork;      /* work item used for writeback */
 
+       struct list_head bdi_node;      /* anchored at bdi->wb_list */
+
 #ifdef CONFIG_CGROUP_WRITEBACK
        struct percpu_ref refcnt;       /* used only for !root wb's */
        struct fprop_local_percpu memcg_completions;
@@ -150,6 +152,7 @@ struct backing_dev_info {
        atomic_long_t tot_write_bandwidth;
 
        struct bdi_writeback wb;  /* the root writeback info for this bdi */
+       struct list_head wb_list; /* list of all wbs */
 #ifdef CONFIG_CGROUP_WRITEBACK
        struct radix_tree_root cgwb_tree; /* radix tree of active cgroup wbs */
        struct rb_root cgwb_congested_tree; /* their congested states */
index 5a5d79ee256f24aa2de8fa92778e8e85cdfcd4b2..c85f74946a8bab65ff3f16cddea6a4446b0a4799 100644 (file)
 #include <linux/sched.h>
 #include <linux/blkdev.h>
 #include <linux/writeback.h>
+#include <linux/memcontrol.h>
 #include <linux/blk-cgroup.h>
 #include <linux/backing-dev-defs.h>
 #include <linux/slab.h>
 
 int __must_check bdi_init(struct backing_dev_info *bdi);
-void bdi_destroy(struct backing_dev_info *bdi);
+void bdi_exit(struct backing_dev_info *bdi);
 
 __printf(3, 4)
 int bdi_register(struct backing_dev_info *bdi, struct device *parent,
                const char *fmt, ...);
 int bdi_register_dev(struct backing_dev_info *bdi, dev_t dev);
+void bdi_unregister(struct backing_dev_info *bdi);
+
 int __must_check bdi_setup_and_register(struct backing_dev_info *, char *);
+void bdi_destroy(struct backing_dev_info *bdi);
+
 void wb_start_writeback(struct bdi_writeback *wb, long nr_pages,
                        bool range_cyclic, enum wb_reason reason);
 void wb_start_background_writeback(struct bdi_writeback *wb);
@@ -252,13 +257,19 @@ int inode_congested(struct inode *inode, int cong_bits);
  * @inode: inode of interest
  *
  * cgroup writeback requires support from both the bdi and filesystem.
- * Test whether @inode has both.
+ * Also, both memcg and iocg have to be on the default hierarchy.  Test
+ * whether all conditions are met.
+ *
+ * Note that the test result may change dynamically on the same inode
+ * depending on how memcg and iocg are configured.
  */
 static inline bool inode_cgwb_enabled(struct inode *inode)
 {
        struct backing_dev_info *bdi = inode_to_bdi(inode);
 
-       return bdi_cap_account_dirty(bdi) &&
+       return cgroup_on_dfl(mem_cgroup_root_css->cgroup) &&
+               cgroup_on_dfl(blkcg_root_css->cgroup) &&
+               bdi_cap_account_dirty(bdi) &&
                (bdi->capabilities & BDI_CAP_CGROUP_WRITEBACK) &&
                (inode->i_sb->s_iflags & SB_I_CGROUPWB);
 }
@@ -401,61 +412,6 @@ static inline void unlocked_inode_to_wb_end(struct inode *inode, bool locked)
        rcu_read_unlock();
 }
 
-struct wb_iter {
-       int                     start_memcg_id;
-       struct radix_tree_iter  tree_iter;
-       void                    **slot;
-};
-
-static inline struct bdi_writeback *__wb_iter_next(struct wb_iter *iter,
-                                                  struct backing_dev_info *bdi)
-{
-       struct radix_tree_iter *titer = &iter->tree_iter;
-
-       WARN_ON_ONCE(!rcu_read_lock_held());
-
-       if (iter->start_memcg_id >= 0) {
-               iter->slot = radix_tree_iter_init(titer, iter->start_memcg_id);
-               iter->start_memcg_id = -1;
-       } else {
-               iter->slot = radix_tree_next_slot(iter->slot, titer, 0);
-       }
-
-       if (!iter->slot)
-               iter->slot = radix_tree_next_chunk(&bdi->cgwb_tree, titer, 0);
-       if (iter->slot)
-               return *iter->slot;
-       return NULL;
-}
-
-static inline struct bdi_writeback *__wb_iter_init(struct wb_iter *iter,
-                                                  struct backing_dev_info *bdi,
-                                                  int start_memcg_id)
-{
-       iter->start_memcg_id = start_memcg_id;
-
-       if (start_memcg_id)
-               return __wb_iter_next(iter, bdi);
-       else
-               return &bdi->wb;
-}
-
-/**
- * bdi_for_each_wb - walk all wb's of a bdi in ascending memcg ID order
- * @wb_cur: cursor struct bdi_writeback pointer
- * @bdi: bdi to walk wb's of
- * @iter: pointer to struct wb_iter to be used as iteration buffer
- * @start_memcg_id: memcg ID to start iteration from
- *
- * Iterate @wb_cur through the wb's (bdi_writeback's) of @bdi in ascending
- * memcg ID order starting from @start_memcg_id.  @iter is struct wb_iter
- * to be used as temp storage during iteration.  rcu_read_lock() must be
- * held throughout iteration.
- */
-#define bdi_for_each_wb(wb_cur, bdi, iter, start_memcg_id)             \
-       for ((wb_cur) = __wb_iter_init(iter, bdi, start_memcg_id);      \
-            (wb_cur); (wb_cur) = __wb_iter_next(iter, bdi))
-
 #else  /* CONFIG_CGROUP_WRITEBACK */
 
 static inline bool inode_cgwb_enabled(struct inode *inode)
@@ -515,14 +471,6 @@ static inline void wb_blkcg_offline(struct blkcg *blkcg)
 {
 }
 
-struct wb_iter {
-       int             next_id;
-};
-
-#define bdi_for_each_wb(wb_cur, bdi, iter, start_blkcg_id)             \
-       for ((iter)->next_id = (start_blkcg_id);                        \
-            ({ (wb_cur) = !(iter)->next_id++ ? &(bdi)->wb : NULL; }); )
-
 static inline int inode_congested(struct inode *inode, int cong_bits)
 {
        return wb_congested(&inode_to_bdi(inode)->wb, cong_bits);
index 0a5cc7a1109b9b2c655020c6c849960506f1cbc6..c02e669945e9279bceb796eb9a1adb938ebf863b 100644 (file)
@@ -713,9 +713,9 @@ static inline bool blkcg_bio_issue_check(struct request_queue *q,
 
        if (!throtl) {
                blkg = blkg ?: q->root_blkg;
-               blkg_rwstat_add(&blkg->stat_bytes, bio->bi_flags,
+               blkg_rwstat_add(&blkg->stat_bytes, bio->bi_rw,
                                bio->bi_iter.bi_size);
-               blkg_rwstat_add(&blkg->stat_ios, bio->bi_flags, 1);
+               blkg_rwstat_add(&blkg->stat_ios, bio->bi_rw, 1);
        }
 
        rcu_read_unlock();
index 37d1602c4f7aa08b464577c675910046a4db3dde..5e7d43ab61c000d894164e093132f607344e9cc0 100644 (file)
@@ -145,7 +145,6 @@ enum {
        BLK_MQ_F_SHOULD_MERGE   = 1 << 0,
        BLK_MQ_F_TAG_SHARED     = 1 << 1,
        BLK_MQ_F_SG_MERGE       = 1 << 2,
-       BLK_MQ_F_SYSFS_UP       = 1 << 3,
        BLK_MQ_F_DEFER_ISSUE    = 1 << 4,
        BLK_MQ_F_ALLOC_POLICY_START_BIT = 8,
        BLK_MQ_F_ALLOC_POLICY_BITS = 1,
@@ -215,7 +214,7 @@ void blk_mq_add_to_requeue_list(struct request *rq, bool at_head);
 void blk_mq_cancel_requeue_work(struct request_queue *q);
 void blk_mq_kick_requeue_list(struct request_queue *q);
 void blk_mq_abort_requeue_list(struct request_queue *q);
-void blk_mq_complete_request(struct request *rq);
+void blk_mq_complete_request(struct request *rq, int error);
 
 void blk_mq_stop_hw_queue(struct blk_mq_hw_ctx *hctx);
 void blk_mq_start_hw_queue(struct blk_mq_hw_ctx *hctx);
@@ -224,8 +223,6 @@ void blk_mq_start_hw_queues(struct request_queue *q);
 void blk_mq_start_stopped_hw_queues(struct request_queue *q, bool async);
 void blk_mq_run_hw_queues(struct request_queue *q, bool async);
 void blk_mq_delay_queue(struct blk_mq_hw_ctx *hctx, unsigned long msecs);
-void blk_mq_tag_busy_iter(struct blk_mq_hw_ctx *hctx, busy_iter_fn *fn,
-               void *priv);
 void blk_mq_all_tag_busy_iter(struct blk_mq_tags *tags, busy_tag_iter_fn *fn,
                void *priv);
 void blk_mq_freeze_queue(struct request_queue *q);
index 38a5ff772a37fbbd841a1152d9f613bb1ffde84c..19c2e947d4d127364887a133d4b0d0ce92090e1c 100644 (file)
@@ -456,6 +456,8 @@ struct request_queue {
        struct blk_mq_tag_set   *tag_set;
        struct list_head        tag_set_list;
        struct bio_set          *bio_split;
+
+       bool                    mq_sysfs_init_done;
 };
 
 #define QUEUE_FLAG_QUEUED      1       /* uses generic tag queueing */
@@ -1368,6 +1370,26 @@ static inline bool bvec_gap_to_prev(struct request_queue *q,
                ((bprv->bv_offset + bprv->bv_len) & queue_virt_boundary(q));
 }
 
+static inline bool bio_will_gap(struct request_queue *q, struct bio *prev,
+                        struct bio *next)
+{
+       if (!bio_has_data(prev))
+               return false;
+
+       return bvec_gap_to_prev(q, &prev->bi_io_vec[prev->bi_vcnt - 1],
+                               next->bi_io_vec[0].bv_offset);
+}
+
+static inline bool req_gap_back_merge(struct request *req, struct bio *bio)
+{
+       return bio_will_gap(req->q, req->biotail, bio);
+}
+
+static inline bool req_gap_front_merge(struct request *req, struct bio *bio)
+{
+       return bio_will_gap(req->q, bio, req->bio);
+}
+
 struct work_struct;
 int kblockd_schedule_work(struct work_struct *work);
 int kblockd_schedule_delayed_work(struct delayed_work *dwork, unsigned long delay);
@@ -1494,6 +1516,26 @@ queue_max_integrity_segments(struct request_queue *q)
        return q->limits.max_integrity_segments;
 }
 
+static inline bool integrity_req_gap_back_merge(struct request *req,
+                                               struct bio *next)
+{
+       struct bio_integrity_payload *bip = bio_integrity(req->bio);
+       struct bio_integrity_payload *bip_next = bio_integrity(next);
+
+       return bvec_gap_to_prev(req->q, &bip->bip_vec[bip->bip_vcnt - 1],
+                               bip_next->bip_vec[0].bv_offset);
+}
+
+static inline bool integrity_req_gap_front_merge(struct request *req,
+                                                struct bio *bio)
+{
+       struct bio_integrity_payload *bip = bio_integrity(bio);
+       struct bio_integrity_payload *bip_next = bio_integrity(req->bio);
+
+       return bvec_gap_to_prev(req->q, &bip->bip_vec[bip->bip_vcnt - 1],
+                               bip_next->bip_vec[0].bv_offset);
+}
+
 #else /* CONFIG_BLK_DEV_INTEGRITY */
 
 struct bio;
@@ -1560,6 +1602,16 @@ static inline bool blk_integrity_is_initialized(struct gendisk *g)
 {
        return 0;
 }
+static inline bool integrity_req_gap_back_merge(struct request *req,
+                                               struct bio *next)
+{
+       return false;
+}
+static inline bool integrity_req_gap_front_merge(struct request *req,
+                                                struct bio *bio)
+{
+       return false;
+}
 
 #endif /* CONFIG_BLK_DEV_INTEGRITY */
 
index 4763ad64e832cb07496bbd14a35c4bcf3825a885..f89b31d45cc894814d409a19e161a29c2c41e832 100644 (file)
@@ -107,6 +107,7 @@ static inline u64 ceph_sanitize_features(u64 features)
         CEPH_FEATURE_OSDMAP_ENC |              \
         CEPH_FEATURE_CRUSH_TUNABLES3 |         \
         CEPH_FEATURE_OSD_PRIMARY_AFFINITY |    \
+        CEPH_FEATURE_MSGR_KEEPALIVE2 |         \
         CEPH_FEATURE_CRUSH_V4)
 
 #define CEPH_FEATURES_REQUIRED_DEFAULT   \
index 7e1252e97a30bc92d4065faf4ee5ab38d7839156..b2371d9b51fac6ea69032576ac1c3cddfc104016 100644 (file)
@@ -238,6 +238,8 @@ struct ceph_connection {
        bool out_kvec_is_msg; /* kvec refers to out_msg */
        int out_more;        /* there is more data after the kvecs */
        __le64 out_temp_ack; /* for writing an ack */
+       struct ceph_timespec out_temp_keepalive2; /* for writing keepalive2
+                                                    stamp */
 
        /* message in temps */
        struct ceph_msg_header in_hdr;
@@ -248,7 +250,7 @@ struct ceph_connection {
        int in_base_pos;     /* bytes read */
        __le64 in_temp_ack;  /* for reading an ack */
 
-       struct timespec last_keepalive_ack;
+       struct timespec last_keepalive_ack; /* keepalive2 ack stamp */
 
        struct delayed_work work;           /* send|recv work */
        unsigned long       delay;          /* current delay interval */
index 4d8fcf2187dcaa822b8f629655e83d667a9913ac..8492721b39be8f0fffa793c5ef39f33d32b5c5fb 100644 (file)
@@ -473,31 +473,8 @@ struct cgroup_subsys {
        unsigned int depends_on;
 };
 
-extern struct percpu_rw_semaphore cgroup_threadgroup_rwsem;
-
-/**
- * cgroup_threadgroup_change_begin - threadgroup exclusion for cgroups
- * @tsk: target task
- *
- * Called from threadgroup_change_begin() and allows cgroup operations to
- * synchronize against threadgroup changes using a percpu_rw_semaphore.
- */
-static inline void cgroup_threadgroup_change_begin(struct task_struct *tsk)
-{
-       percpu_down_read(&cgroup_threadgroup_rwsem);
-}
-
-/**
- * cgroup_threadgroup_change_end - threadgroup exclusion for cgroups
- * @tsk: target task
- *
- * Called from threadgroup_change_end().  Counterpart of
- * cgroup_threadcgroup_change_begin().
- */
-static inline void cgroup_threadgroup_change_end(struct task_struct *tsk)
-{
-       percpu_up_read(&cgroup_threadgroup_rwsem);
-}
+void cgroup_threadgroup_change_begin(struct task_struct *tsk);
+void cgroup_threadgroup_change_end(struct task_struct *tsk);
 
 #else  /* CONFIG_CGROUPS */
 
index 31ce435981feb962b4f1a9a9494ad97913232dcd..bdcf358dfce2a9d0f5420d9fbde6066b1e2dc73b 100644 (file)
 struct clock_event_device;
 struct module;
 
-/* Clock event mode commands for legacy ->set_mode(): OBSOLETE */
-enum clock_event_mode {
-       CLOCK_EVT_MODE_UNUSED,
-       CLOCK_EVT_MODE_SHUTDOWN,
-       CLOCK_EVT_MODE_PERIODIC,
-       CLOCK_EVT_MODE_ONESHOT,
-       CLOCK_EVT_MODE_RESUME,
-};
-
 /*
  * Possible states of a clock event device.
  *
@@ -86,16 +77,14 @@ enum clock_event_state {
  * @min_delta_ns:      minimum delta value in ns
  * @mult:              nanosecond to cycles multiplier
  * @shift:             nanoseconds to cycles divisor (power of two)
- * @mode:              operating mode, relevant only to ->set_mode(), OBSOLETE
  * @state_use_accessors:current state of the device, assigned by the core code
  * @features:          features
  * @retries:           number of forced programming retries
- * @set_mode:          legacy set mode function, only for modes <= CLOCK_EVT_MODE_RESUME.
- * @set_state_periodic:        switch state to periodic, if !set_mode
- * @set_state_oneshot: switch state to oneshot, if !set_mode
- * @set_state_oneshot_stopped: switch state to oneshot_stopped, if !set_mode
- * @set_state_shutdown:        switch state to shutdown, if !set_mode
- * @tick_resume:       resume clkevt device, if !set_mode
+ * @set_state_periodic:        switch state to periodic
+ * @set_state_oneshot: switch state to oneshot
+ * @set_state_oneshot_stopped: switch state to oneshot_stopped
+ * @set_state_shutdown:        switch state to shutdown
+ * @tick_resume:       resume clkevt device
  * @broadcast:         function to broadcast events
  * @min_delta_ticks:   minimum delta value in ticks stored for reconfiguration
  * @max_delta_ticks:   maximum delta value in ticks stored for reconfiguration
@@ -116,18 +105,10 @@ struct clock_event_device {
        u64                     min_delta_ns;
        u32                     mult;
        u32                     shift;
-       enum clock_event_mode   mode;
        enum clock_event_state  state_use_accessors;
        unsigned int            features;
        unsigned long           retries;
 
-       /*
-        * State transition callback(s): Only one of the two groups should be
-        * defined:
-        * - set_mode(), only for modes <= CLOCK_EVT_MODE_RESUME.
-        * - set_state_{shutdown|periodic|oneshot|oneshot_stopped}(), tick_resume().
-        */
-       void                    (*set_mode)(enum clock_event_mode mode, struct clock_event_device *);
        int                     (*set_state_periodic)(struct clock_event_device *);
        int                     (*set_state_oneshot)(struct clock_event_device *);
        int                     (*set_state_oneshot_stopped)(struct clock_event_device *);
index f7ef093ec49a2bbdd637aae6ab0f1bf0fa4e1e32..29f9e774ab76ef5c1deb019a142af3027a43ebce 100644 (file)
@@ -26,6 +26,6 @@ extern int __init cma_declare_contiguous(phys_addr_t base,
 extern int cma_init_reserved_mem(phys_addr_t base, phys_addr_t size,
                                        unsigned int order_per_bit,
                                        struct cma **res_cma);
-extern struct page *cma_alloc(struct cma *cma, unsigned int count, unsigned int align);
+extern struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align);
 extern bool cma_release(struct cma *cma, const struct page *pages, unsigned int count);
 #endif
index dfaa7b3e9ae900676b61dc7c3f693c78de97e8cd..8efb40e61d6e48021d68f93635eea8d3ab3e8c0b 100644 (file)
 #define KASAN_ABI_VERSION 3
 #endif
 
+#if GCC_VERSION >= 40902
+/*
+ * Tell the compiler that address safety instrumentation (KASAN)
+ * should not be applied to that function.
+ * Conflicts with inlining: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67368
+ */
+#define __no_sanitize_address __attribute__((no_sanitize_address))
+#endif
+
 #endif /* gcc version >= 40000 specific checks */
 
 #if !defined(__noclone)
 #define __noclone      /* not needed */
 #endif
 
+#if !defined(__no_sanitize_address)
+#define __no_sanitize_address
+#endif
+
 /*
  * A trick to suppress uninitialized variable warning without generating any
  * code
index c836eb2dc44d5b3a4d5e98dfbbd274c4448daa90..3d7810341b579795398e36cb15597feb344bb912 100644 (file)
@@ -198,19 +198,45 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect);
 
 #include <uapi/linux/types.h>
 
-static __always_inline void __read_once_size(const volatile void *p, void *res, int size)
+#define __READ_ONCE_SIZE                                               \
+({                                                                     \
+       switch (size) {                                                 \
+       case 1: *(__u8 *)res = *(volatile __u8 *)p; break;              \
+       case 2: *(__u16 *)res = *(volatile __u16 *)p; break;            \
+       case 4: *(__u32 *)res = *(volatile __u32 *)p; break;            \
+       case 8: *(__u64 *)res = *(volatile __u64 *)p; break;            \
+       default:                                                        \
+               barrier();                                              \
+               __builtin_memcpy((void *)res, (const void *)p, size);   \
+               barrier();                                              \
+       }                                                               \
+})
+
+static __always_inline
+void __read_once_size(const volatile void *p, void *res, int size)
 {
-       switch (size) {
-       case 1: *(__u8 *)res = *(volatile __u8 *)p; break;
-       case 2: *(__u16 *)res = *(volatile __u16 *)p; break;
-       case 4: *(__u32 *)res = *(volatile __u32 *)p; break;
-       case 8: *(__u64 *)res = *(volatile __u64 *)p; break;
-       default:
-               barrier();
-               __builtin_memcpy((void *)res, (const void *)p, size);
-               barrier();
-       }
+       __READ_ONCE_SIZE;
+}
+
+#ifdef CONFIG_KASAN
+/*
+ * This function is not 'inline' because __no_sanitize_address confilcts
+ * with inlining. Attempt to inline it may cause a build failure.
+ *     https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67368
+ * '__maybe_unused' allows us to avoid defined-but-not-used warnings.
+ */
+static __no_sanitize_address __maybe_unused
+void __read_once_size_nocheck(const volatile void *p, void *res, int size)
+{
+       __READ_ONCE_SIZE;
+}
+#else
+static __always_inline
+void __read_once_size_nocheck(const volatile void *p, void *res, int size)
+{
+       __READ_ONCE_SIZE;
 }
+#endif
 
 static __always_inline void __write_once_size(volatile void *p, void *res, int size)
 {
@@ -248,8 +274,22 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
  * required ordering.
  */
 
-#define READ_ONCE(x) \
-       ({ union { typeof(x) __val; char __c[1]; } __u; __read_once_size(&(x), __u.__c, sizeof(x)); __u.__val; })
+#define __READ_ONCE(x, check)                                          \
+({                                                                     \
+       union { typeof(x) __val; char __c[1]; } __u;                    \
+       if (check)                                                      \
+               __read_once_size(&(x), __u.__c, sizeof(x));             \
+       else                                                            \
+               __read_once_size_nocheck(&(x), __u.__c, sizeof(x));     \
+       __u.__val;                                                      \
+})
+#define READ_ONCE(x) __READ_ONCE(x, 1)
+
+/*
+ * Use READ_ONCE_NOCHECK() instead of READ_ONCE() if you need
+ * to hide memory access from KASAN.
+ */
+#define READ_ONCE_NOCHECK(x) __READ_ONCE(x, 0)
 
 #define WRITE_ONCE(x, val) \
 ({                                                     \
index 430efcbea48e3547d34c76c62e14fe5eb495c6a9..dca22de98d948480141c5806680ef167b35a7555 100644 (file)
@@ -127,9 +127,14 @@ struct cpufreq_policy {
 #define CPUFREQ_SHARED_TYPE_ANY         (3) /* Freq can be set from any dependent CPU*/
 
 #ifdef CONFIG_CPU_FREQ
+struct cpufreq_policy *cpufreq_cpu_get_raw(unsigned int cpu);
 struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu);
 void cpufreq_cpu_put(struct cpufreq_policy *policy);
 #else
+static inline struct cpufreq_policy *cpufreq_cpu_get_raw(unsigned int cpu)
+{
+       return NULL;
+}
 static inline struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
 {
        return NULL;
index ce447f0f1bad49e24351cec2c1ae0e2d2620ad4a..68030e22af3527958ac39006031dd62388228091 100644 (file)
@@ -65,7 +65,10 @@ struct devfreq_dev_status {
  *                     The "flags" parameter's possible values are
  *                     explained above with "DEVFREQ_FLAG_*" macros.
  * @get_dev_status:    The device should provide the current performance
- *                     status to devfreq, which is used by governors.
+ *                     status to devfreq. Governors are recommended not to
+ *                     use this directly. Instead, governors are recommended
+ *                     to use devfreq_update_stats() along with
+ *                     devfreq.last_status.
  * @get_cur_freq:      The device should provide the current frequency
  *                     at which it is operating.
  * @exit:              An optional callback that is called when devfreq
@@ -161,6 +164,7 @@ struct devfreq {
        struct delayed_work work;
 
        unsigned long previous_freq;
+       struct devfreq_dev_status last_status;
 
        void *data; /* private data for governors */
 
@@ -204,6 +208,19 @@ extern int devm_devfreq_register_opp_notifier(struct device *dev,
 extern void devm_devfreq_unregister_opp_notifier(struct device *dev,
                                                struct devfreq *devfreq);
 
+/**
+ * devfreq_update_stats() - update the last_status pointer in struct devfreq
+ * @df:                the devfreq instance whose status needs updating
+ *
+ *  Governors are recommended to use this function along with last_status,
+ * which allows other entities to reuse the last_status without affecting
+ * the values fetched later by governors.
+ */
+static inline int devfreq_update_stats(struct devfreq *df)
+{
+       return df->profile->get_dev_status(df->dev.parent, &df->last_status);
+}
+
 #if IS_ENABLED(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND)
 /**
  * struct devfreq_simple_ondemand_data - void *data fed to struct devfreq
@@ -289,6 +306,11 @@ static inline void devm_devfreq_unregister_opp_notifier(struct device *dev,
                                                        struct devfreq *devfreq)
 {
 }
+
+static inline int devfreq_update_stats(struct devfreq *df)
+{
+       return -EINVAL;
+}
 #endif /* CONFIG_PM_DEVFREQ */
 
 #endif /* __LINUX_DEVFREQ_H__ */
index 569bbd039896f330923d53b4a6231ba1c73e70cc..fec734df1524799e1e7137e943098c907d0fce8c 100644 (file)
@@ -111,7 +111,7 @@ static inline int dma_declare_contiguous(struct device *dev, phys_addr_t size,
        return ret;
 }
 
-struct page *dma_alloc_from_contiguous(struct device *dev, int count,
+struct page *dma_alloc_from_contiguous(struct device *dev, size_t count,
                                       unsigned int order);
 bool dma_release_from_contiguous(struct device *dev, struct page *pages,
                                 int count);
@@ -144,7 +144,7 @@ int dma_declare_contiguous(struct device *dev, phys_addr_t size,
 }
 
 static inline
-struct page *dma_alloc_from_contiguous(struct device *dev, int count,
+struct page *dma_alloc_from_contiguous(struct device *dev, size_t count,
                                       unsigned int order)
 {
        return NULL;
index d0b380ee7d67abbd421bf69fdd63ff10b2aa88b1..e38681f4912d02f9c571dd7d232a4b4bb4911ea4 100644 (file)
 extern struct files_struct init_files;
 extern struct fs_struct init_fs;
 
+#ifdef CONFIG_CGROUPS
+#define INIT_GROUP_RWSEM(sig)                                          \
+       .group_rwsem = __RWSEM_INITIALIZER(sig.group_rwsem),
+#else
+#define INIT_GROUP_RWSEM(sig)
+#endif
+
 #ifdef CONFIG_CPUSETS
 #define INIT_CPUSET_SEQ(tsk)                                                   \
        .mems_allowed_seq = SEQCNT_ZERO(tsk.mems_allowed_seq),
@@ -57,6 +64,7 @@ extern struct fs_struct init_fs;
        INIT_PREV_CPUTIME(sig)                                          \
        .cred_guard_mutex =                                             \
                 __MUTEX_INITIALIZER(sig.cred_guard_mutex),             \
+       INIT_GROUP_RWSEM(sig)                                           \
 }
 
 extern struct nsproxy init_nsproxy;
index 3920a19d819415bc3109a491171e32388f9bda18..92f7177db2ce869a29db8813911c3a8a0c2b86b2 100644 (file)
@@ -68,8 +68,8 @@ static inline unsigned long iova_pfn(struct iova_domain *iovad, dma_addr_t iova)
        return iova >> iova_shift(iovad);
 }
 
-int iommu_iova_cache_init(void);
-void iommu_iova_cache_destroy(void);
+int iova_cache_get(void);
+void iova_cache_put(void);
 
 struct iova *alloc_iova_mem(void);
 void free_iova_mem(struct iova *iova);
index 6f8b340664421bb797fd37488bbd2c97afb6d3d4..11bf09288ddb08ab277b6f213696c1216348155c 100644 (file)
@@ -110,8 +110,8 @@ enum {
 /*
  * Return value for chip->irq_set_affinity()
  *
- * IRQ_SET_MASK_OK     - OK, core updates irq_data.affinity
- * IRQ_SET_MASK_NOCPY  - OK, chip did update irq_data.affinity
+ * IRQ_SET_MASK_OK     - OK, core updates irq_common_data.affinity
+ * IRQ_SET_MASK_NOCPY  - OK, chip did update irq_common_data.affinity
  * IRQ_SET_MASK_OK_DONE        - Same as IRQ_SET_MASK_OK for core. Special code to
  *                       support stacked irqchips, which indicates skipping
  *                       all descendent irqchips.
@@ -129,9 +129,19 @@ struct irq_domain;
  * struct irq_common_data - per irq data shared by all irqchips
  * @state_use_accessors: status information for irq chip functions.
  *                     Use accessor functions to deal with it
+ * @node:              node index useful for balancing
+ * @handler_data:      per-IRQ data for the irq_chip methods
+ * @affinity:          IRQ affinity on SMP
+ * @msi_desc:          MSI descriptor
  */
 struct irq_common_data {
        unsigned int            state_use_accessors;
+#ifdef CONFIG_NUMA
+       unsigned int            node;
+#endif
+       void                    *handler_data;
+       struct msi_desc         *msi_desc;
+       cpumask_var_t           affinity;
 };
 
 /**
@@ -139,38 +149,26 @@ struct irq_common_data {
  * @mask:              precomputed bitmask for accessing the chip registers
  * @irq:               interrupt number
  * @hwirq:             hardware interrupt number, local to the interrupt domain
- * @node:              node index useful for balancing
  * @common:            point to data shared by all irqchips
  * @chip:              low level interrupt hardware access
  * @domain:            Interrupt translation domain; responsible for mapping
  *                     between hwirq number and linux irq number.
  * @parent_data:       pointer to parent struct irq_data to support hierarchy
  *                     irq_domain
- * @handler_data:      per-IRQ data for the irq_chip methods
  * @chip_data:         platform-specific per-chip private data for the chip
  *                     methods, to allow shared chip implementations
- * @msi_desc:          MSI descriptor
- * @affinity:          IRQ affinity on SMP
- *
- * The fields here need to overlay the ones in irq_desc until we
- * cleaned up the direct references and switched everything over to
- * irq_data.
  */
 struct irq_data {
        u32                     mask;
        unsigned int            irq;
        unsigned long           hwirq;
-       unsigned int            node;
        struct irq_common_data  *common;
        struct irq_chip         *chip;
        struct irq_domain       *domain;
 #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
        struct irq_data         *parent_data;
 #endif
-       void                    *handler_data;
        void                    *chip_data;
-       struct msi_desc         *msi_desc;
-       cpumask_var_t           affinity;
 };
 
 /*
@@ -190,6 +188,7 @@ struct irq_data {
  * IRQD_IRQ_MASKED             - Masked state of the interrupt
  * IRQD_IRQ_INPROGRESS         - In progress state of the interrupt
  * IRQD_WAKEUP_ARMED           - Wakeup mode armed
+ * IRQD_FORWARDED_TO_VCPU      - The interrupt is forwarded to a VCPU
  */
 enum {
        IRQD_TRIGGER_MASK               = 0xf,
@@ -204,6 +203,7 @@ enum {
        IRQD_IRQ_MASKED                 = (1 << 17),
        IRQD_IRQ_INPROGRESS             = (1 << 18),
        IRQD_WAKEUP_ARMED               = (1 << 19),
+       IRQD_FORWARDED_TO_VCPU          = (1 << 20),
 };
 
 #define __irqd_to_state(d)             ((d)->common->state_use_accessors)
@@ -282,6 +282,20 @@ static inline bool irqd_is_wakeup_armed(struct irq_data *d)
        return __irqd_to_state(d) & IRQD_WAKEUP_ARMED;
 }
 
+static inline bool irqd_is_forwarded_to_vcpu(struct irq_data *d)
+{
+       return __irqd_to_state(d) & IRQD_FORWARDED_TO_VCPU;
+}
+
+static inline void irqd_set_forwarded_to_vcpu(struct irq_data *d)
+{
+       __irqd_to_state(d) |= IRQD_FORWARDED_TO_VCPU;
+}
+
+static inline void irqd_clr_forwarded_to_vcpu(struct irq_data *d)
+{
+       __irqd_to_state(d) &= ~IRQD_FORWARDED_TO_VCPU;
+}
 
 /*
  * Functions for chained handlers which can be enabled/disabled by the
@@ -461,14 +475,14 @@ static inline int irq_set_parent(int irq, int parent_irq)
  * Built-in IRQ handlers for various IRQ types,
  * callable via desc->handle_irq()
  */
-extern void handle_level_irq(unsigned int irq, struct irq_desc *desc);
-extern void handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc);
-extern void handle_edge_irq(unsigned int irq, struct irq_desc *desc);
-extern void handle_edge_eoi_irq(unsigned int irq, struct irq_desc *desc);
-extern void handle_simple_irq(unsigned int irq, struct irq_desc *desc);
-extern void handle_percpu_irq(unsigned int irq, struct irq_desc *desc);
-extern void handle_percpu_devid_irq(unsigned int irq, struct irq_desc *desc);
-extern void handle_bad_irq(unsigned int irq, struct irq_desc *desc);
+extern void handle_level_irq(struct irq_desc *desc);
+extern void handle_fasteoi_irq(struct irq_desc *desc);
+extern void handle_edge_irq(struct irq_desc *desc);
+extern void handle_edge_eoi_irq(struct irq_desc *desc);
+extern void handle_simple_irq(struct irq_desc *desc);
+extern void handle_percpu_irq(struct irq_desc *desc);
+extern void handle_percpu_devid_irq(struct irq_desc *desc);
+extern void handle_bad_irq(struct irq_desc *desc);
 extern void handle_nested_irq(unsigned int irq);
 
 extern int irq_chip_compose_msi_msg(struct irq_data *data, struct msi_msg *msg);
@@ -627,23 +641,23 @@ static inline void *irq_data_get_irq_chip_data(struct irq_data *d)
 static inline void *irq_get_handler_data(unsigned int irq)
 {
        struct irq_data *d = irq_get_irq_data(irq);
-       return d ? d->handler_data : NULL;
+       return d ? d->common->handler_data : NULL;
 }
 
 static inline void *irq_data_get_irq_handler_data(struct irq_data *d)
 {
-       return d->handler_data;
+       return d->common->handler_data;
 }
 
 static inline struct msi_desc *irq_get_msi_desc(unsigned int irq)
 {
        struct irq_data *d = irq_get_irq_data(irq);
-       return d ? d->msi_desc : NULL;
+       return d ? d->common->msi_desc : NULL;
 }
 
 static inline struct msi_desc *irq_data_get_msi_desc(struct irq_data *d)
 {
-       return d->msi_desc;
+       return d->common->msi_desc;
 }
 
 static inline u32 irq_get_trigger_type(unsigned int irq)
@@ -652,21 +666,30 @@ static inline u32 irq_get_trigger_type(unsigned int irq)
        return d ? irqd_get_trigger_type(d) : 0;
 }
 
-static inline int irq_data_get_node(struct irq_data *d)
+static inline int irq_common_data_get_node(struct irq_common_data *d)
 {
+#ifdef CONFIG_NUMA
        return d->node;
+#else
+       return 0;
+#endif
+}
+
+static inline int irq_data_get_node(struct irq_data *d)
+{
+       return irq_common_data_get_node(d->common);
 }
 
 static inline struct cpumask *irq_get_affinity_mask(int irq)
 {
        struct irq_data *d = irq_get_irq_data(irq);
 
-       return d ? d->affinity : NULL;
+       return d ? d->common->affinity : NULL;
 }
 
 static inline struct cpumask *irq_data_get_affinity_mask(struct irq_data *d)
 {
-       return d->affinity;
+       return d->common->affinity;
 }
 
 unsigned int arch_dynirq_lower_bound(unsigned int from);
index 5acfa26602e1b5839a1916e5f9da8e947a605271..a587a33363c724a10ae12b471658ed2d1800e827 100644 (file)
@@ -98,11 +98,7 @@ extern struct irq_desc irq_desc[NR_IRQS];
 
 static inline struct irq_desc *irq_data_to_desc(struct irq_data *data)
 {
-#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
-       return irq_to_desc(data->irq);
-#else
-       return container_of(data, struct irq_desc, irq_data);
-#endif
+       return container_of(data->common, struct irq_desc, irq_common_data);
 }
 
 static inline unsigned int irq_desc_get_irq(struct irq_desc *desc)
@@ -127,23 +123,21 @@ static inline void *irq_desc_get_chip_data(struct irq_desc *desc)
 
 static inline void *irq_desc_get_handler_data(struct irq_desc *desc)
 {
-       return desc->irq_data.handler_data;
+       return desc->irq_common_data.handler_data;
 }
 
 static inline struct msi_desc *irq_desc_get_msi_desc(struct irq_desc *desc)
 {
-       return desc->irq_data.msi_desc;
+       return desc->irq_common_data.msi_desc;
 }
 
 /*
  * Architectures call this to let the generic IRQ layer
- * handle an interrupt. If the descriptor is attached to an
- * irqchip-style controller then we call the ->handle_irq() handler,
- * and it calls __do_IRQ() if it's attached to an irqtype-style controller.
+ * handle an interrupt.
  */
-static inline void generic_handle_irq_desc(unsigned int irq, struct irq_desc *desc)
+static inline void generic_handle_irq_desc(struct irq_desc *desc)
 {
-       desc->handle_irq(irq, desc);
+       desc->handle_irq(desc);
 }
 
 int generic_handle_irq(unsigned int irq);
@@ -176,29 +170,6 @@ static inline int irq_has_action(unsigned int irq)
        return irq_desc_has_action(irq_to_desc(irq));
 }
 
-/* caller has locked the irq_desc and both params are valid */
-static inline void __irq_set_handler_locked(unsigned int irq,
-                                           irq_flow_handler_t handler)
-{
-       struct irq_desc *desc;
-
-       desc = irq_to_desc(irq);
-       desc->handle_irq = handler;
-}
-
-/* caller has locked the irq_desc and both params are valid */
-static inline void
-__irq_set_chip_handler_name_locked(unsigned int irq, struct irq_chip *chip,
-                                  irq_flow_handler_t handler, const char *name)
-{
-       struct irq_desc *desc;
-
-       desc = irq_to_desc(irq);
-       irq_desc_get_irq_data(desc)->chip = chip;
-       desc->handle_irq = handler;
-       desc->name = name;
-}
-
 /**
  * irq_set_handler_locked - Set irq handler from a locked region
  * @data:      Pointer to the irq_data structure which identifies the irq
index d3ca79236fb00ee5543e507ae9e69bc62b700e43..f644fdb06dd691ba2d218384b1172791100f9aaf 100644 (file)
@@ -161,6 +161,11 @@ enum {
        IRQ_DOMAIN_FLAG_NONCORE         = (1 << 16),
 };
 
+static inline struct device_node *irq_domain_get_of_node(struct irq_domain *d)
+{
+       return d->of_node;
+}
+
 #ifdef CONFIG_IRQ_DOMAIN
 struct irq_domain *__irq_domain_add(struct device_node *of_node, int size,
                                    irq_hw_number_t hwirq_max, int direct_max,
index 62d5430041970c1ad0904098b9055c653dd4b612..661bed0ed1f3124ca2024559f2613507dd22221f 100644 (file)
@@ -8,7 +8,7 @@
 
 struct irq_desc;
 struct irq_data;
-typedef        void (*irq_flow_handler_t)(unsigned int irq, struct irq_desc *desc);
+typedef        void (*irq_flow_handler_t)(struct irq_desc *desc);
 typedef        void (*irq_preflow_handler_t)(struct irq_data *data);
 
 #endif
index 7f653e8f66900049c358ed4907fab8121047dd91..f1094238ab2a0f0fddeb40e3c7aadde7c2a89015 100644 (file)
@@ -21,8 +21,8 @@
  *
  * DEFINE_STATIC_KEY_TRUE(key);
  * DEFINE_STATIC_KEY_FALSE(key);
- * static_key_likely()
- * statick_key_unlikely()
+ * static_branch_likely()
+ * static_branch_unlikely()
  *
  * Jump labels provide an interface to generate dynamic branches using
  * self-modifying code. Assuming toolchain and architecture support, if we
  * statement, setting the key to true requires us to patch in a jump
  * to the out-of-line of true branch.
  *
- * In addtion to static_branch_{enable,disable}, we can also reference count
+ * In addition to static_branch_{enable,disable}, we can also reference count
  * the key or branch direction via static_branch_{inc,dec}. Thus,
  * static_branch_inc() can be thought of as a 'make more true' and
- * static_branch_dec() as a 'make more false'. The inc()/dec()
- * interface is meant to be used exclusively from the inc()/dec() for a given
- * key.
+ * static_branch_dec() as a 'make more false'.
  *
  * Since this relies on modifying code, the branch modifying functions
  * must be considered absolute slow paths (machine wide synchronization etc.).
index ad800e62cb7a603fdd5f7fb1a752edb03417dbb4..3e3318ddfc0e3e09a0e15825f78eb6052d628d78 100644 (file)
@@ -242,7 +242,6 @@ struct mem_cgroup {
         * percpu counter.
         */
        struct mem_cgroup_stat_cpu __percpu *stat;
-       spinlock_t pcp_counter_lock;
 
 #if defined(CONFIG_MEMCG_KMEM) && defined(CONFIG_INET)
        struct cg_proto tcp_mem;
@@ -677,8 +676,9 @@ enum {
 
 struct list_head *mem_cgroup_cgwb_list(struct mem_cgroup *memcg);
 struct wb_domain *mem_cgroup_wb_domain(struct bdi_writeback *wb);
-void mem_cgroup_wb_stats(struct bdi_writeback *wb, unsigned long *pavail,
-                        unsigned long *pdirty, unsigned long *pwriteback);
+void mem_cgroup_wb_stats(struct bdi_writeback *wb, unsigned long *pfilepages,
+                        unsigned long *pheadroom, unsigned long *pdirty,
+                        unsigned long *pwriteback);
 
 #else  /* CONFIG_CGROUP_WRITEBACK */
 
@@ -688,7 +688,8 @@ static inline struct wb_domain *mem_cgroup_wb_domain(struct bdi_writeback *wb)
 }
 
 static inline void mem_cgroup_wb_stats(struct bdi_writeback *wb,
-                                      unsigned long *pavail,
+                                      unsigned long *pfilepages,
+                                      unsigned long *pheadroom,
                                       unsigned long *pdirty,
                                       unsigned long *pwriteback)
 {
index 8eb3b19af2a4bc2ece866e8d07c6243115ce13d4..250b1ff8b48d43c0f9f2479e388b405d8238eb41 100644 (file)
@@ -402,17 +402,6 @@ struct mlx5_cmd_teardown_hca_mbox_out {
        u8                      rsvd[8];
 };
 
-struct mlx5_cmd_query_special_contexts_mbox_in {
-       struct mlx5_inbox_hdr   hdr;
-       u8                      rsvd[8];
-};
-
-struct mlx5_cmd_query_special_contexts_mbox_out {
-       struct mlx5_outbox_hdr  hdr;
-       __be32                  dump_fill_mkey;
-       __be32                  resd_lkey;
-};
-
 struct mlx5_cmd_layout {
        u8              type;
        u8              rsvd0[3];
index 27b53f9a24ad85a4be3928a470ee4627a20859a6..8b6d6f2154a4eaab1cce3db487b92d8d1b36d4a9 100644 (file)
@@ -845,7 +845,6 @@ void *mlx5_get_protocol_dev(struct mlx5_core_dev *mdev, int protocol);
 int mlx5_register_interface(struct mlx5_interface *intf);
 void mlx5_unregister_interface(struct mlx5_interface *intf);
 int mlx5_core_query_vendor_id(struct mlx5_core_dev *mdev, u32 *vendor_id);
-int mlx5_core_query_special_context(struct mlx5_core_dev *dev, u32 *rsvd_lkey);
 
 struct mlx5_profile {
        u64     mask;
index 91c08f6f0dc96dbb7474d3349f62b5d3f723fe80..80001de019ba33d86b90b9922b39722270cb0449 100644 (file)
@@ -905,6 +905,27 @@ static inline void set_page_links(struct page *page, enum zone_type zone,
 #endif
 }
 
+#ifdef CONFIG_MEMCG
+static inline struct mem_cgroup *page_memcg(struct page *page)
+{
+       return page->mem_cgroup;
+}
+
+static inline void set_page_memcg(struct page *page, struct mem_cgroup *memcg)
+{
+       page->mem_cgroup = memcg;
+}
+#else
+static inline struct mem_cgroup *page_memcg(struct page *page)
+{
+       return NULL;
+}
+
+static inline void set_page_memcg(struct page *page, struct mem_cgroup *memcg)
+{
+}
+#endif
+
 /*
  * Some inline functions in vmstat.h depend on page_zone()
  */
index 88a00694eda5fc394bf4e1ef52ac1d51b9f02111..210d11a75e4ff36bcdedb6496c9e5943cb24f465 100644 (file)
@@ -507,6 +507,7 @@ static inline void napi_enable(struct napi_struct *n)
        BUG_ON(!test_bit(NAPI_STATE_SCHED, &n->state));
        smp_mb__before_atomic();
        clear_bit(NAPI_STATE_SCHED, &n->state);
+       clear_bit(NAPI_STATE_NPSVC, &n->state);
 }
 
 #ifdef CONFIG_SMP
@@ -1053,6 +1054,10 @@ typedef u16 (*select_queue_fallback_t)(struct net_device *dev,
  *     This function is used to pass protocol port error state information
  *     to the switch driver. The switch driver can react to the proto_down
  *      by doing a phys down on the associated switch port.
+ * int (*ndo_fill_metadata_dst)(struct net_device *dev, struct sk_buff *skb);
+ *     This function is used to get egress tunnel information for given skb.
+ *     This is useful for retrieving outer tunnel header parameters while
+ *     sampling packet.
  *
  */
 struct net_device_ops {
@@ -1226,6 +1231,8 @@ struct net_device_ops {
        int                     (*ndo_get_iflink)(const struct net_device *dev);
        int                     (*ndo_change_proto_down)(struct net_device *dev,
                                                         bool proto_down);
+       int                     (*ndo_fill_metadata_dst)(struct net_device *dev,
+                                                      struct sk_buff *skb);
 };
 
 /**
@@ -2202,6 +2209,7 @@ void dev_add_offload(struct packet_offload *po);
 void dev_remove_offload(struct packet_offload *po);
 
 int dev_get_iflink(const struct net_device *dev);
+int dev_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb);
 struct net_device *__dev_get_by_flags(struct net *net, unsigned short flags,
                                      unsigned short mask);
 struct net_device *dev_get_by_name(struct net *net, const char *name);
index e5a70132a240f66803a0c27a30eb2375111d97e0..88fa8af2b937c02a7402d5c8b2499009d4d0ff21 100644 (file)
@@ -17,7 +17,7 @@
 
 #include <linux/platform_device.h>
 
-#define INT_DMA_LCD                    25
+#define INT_DMA_LCD                    (NR_IRQS_LEGACY + 25)
 
 #define OMAP1_DMA_TOUT_IRQ             (1 << 0)
 #define OMAP_DMA_DROP_IRQ              (1 << 1)
index 962387a192f1570211db2eb1d8e5e1c1c9031a60..4a4e3a09233762ba0e2d3065a6fa951e352a2869 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/spinlock.h>
 #include <linux/ethtool.h>
 #include <linux/mii.h>
+#include <linux/module.h>
 #include <linux/timer.h>
 #include <linux/workqueue.h>
 #include <linux/mod_devicetable.h>
@@ -153,6 +154,7 @@ struct sk_buff;
  * PHYs should register using this structure
  */
 struct mii_bus {
+       struct module *owner;
        const char *name;
        char id[MII_BUS_ID_SIZE];
        void *priv;
@@ -198,7 +200,8 @@ static inline struct mii_bus *mdiobus_alloc(void)
        return mdiobus_alloc_size(0);
 }
 
-int mdiobus_register(struct mii_bus *bus);
+int __mdiobus_register(struct mii_bus *bus, struct module *owner);
+#define mdiobus_register(bus) __mdiobus_register(bus, THIS_MODULE)
 void mdiobus_unregister(struct mii_bus *bus);
 void mdiobus_free(struct mii_bus *bus);
 struct mii_bus *devm_mdiobus_alloc_size(struct device *dev, int sizeof_priv);
@@ -742,6 +745,7 @@ struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id,
                                     struct phy_c45_device_ids *c45_ids);
 struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45);
 int phy_device_register(struct phy_device *phy);
+void phy_device_remove(struct phy_device *phydev);
 int phy_init_hw(struct phy_device *phydev);
 int phy_suspend(struct phy_device *phydev);
 int phy_resume(struct phy_device *phydev);
index ff476515f7163ab1b0247cfd64c0a4f6a364b2f3..581abf84856691ad2e5ce39f77f9c9112170061c 100644 (file)
@@ -230,12 +230,11 @@ void __wait_rcu_gp(bool checktiny, int n, call_rcu_func_t *crcu_array,
                   struct rcu_synchronize *rs_array);
 
 #define _wait_rcu_gp(checktiny, ...) \
-do { \
-       call_rcu_func_t __crcu_array[] = { __VA_ARGS__ }; \
-       const int __n = ARRAY_SIZE(__crcu_array); \
-       struct rcu_synchronize __rs_array[__n]; \
-       \
-       __wait_rcu_gp(checktiny, __n, __crcu_array, __rs_array); \
+do {                                                                   \
+       call_rcu_func_t __crcu_array[] = { __VA_ARGS__ };               \
+       struct rcu_synchronize __rs_array[ARRAY_SIZE(__crcu_array)];    \
+       __wait_rcu_gp(checktiny, ARRAY_SIZE(__crcu_array),              \
+                       __crcu_array, __rs_array);                      \
 } while (0)
 
 #define wait_rcu_gp(...) _wait_rcu_gp(false, __VA_ARGS__)
index a4ab9daa387c0bbcaca1923620ceb2ed74bfd84e..b7b9501b41af4eab6a096601c3baf85c85854807 100644 (file)
@@ -762,6 +762,18 @@ struct signal_struct {
        unsigned audit_tty_log_passwd;
        struct tty_audit_buf *tty_audit_buf;
 #endif
+#ifdef CONFIG_CGROUPS
+       /*
+        * group_rwsem prevents new tasks from entering the threadgroup and
+        * member tasks from exiting,a more specifically, setting of
+        * PF_EXITING.  fork and exit paths are protected with this rwsem
+        * using threadgroup_change_begin/end().  Users which require
+        * threadgroup to remain stable should use threadgroup_[un]lock()
+        * which also takes care of exec path.  Currently, cgroup is the
+        * only user.
+        */
+       struct rw_semaphore group_rwsem;
+#endif
 
        oom_flags_t oom_flags;
        short oom_score_adj;            /* OOM kill score adjustment */
index 79d85ddf8093c892b3797bd5f8c8bca391f1d5e8..2f4c1f7aa7db7076998762d2772a35c6e16f9547 100644 (file)
@@ -946,7 +946,7 @@ static inline int security_task_prctl(int option, unsigned long arg2,
                                      unsigned long arg4,
                                      unsigned long arg5)
 {
-       return cap_task_prctl(option, arg2, arg3, arg3, arg5);
+       return cap_task_prctl(option, arg2, arg3, arg4, arg5);
 }
 
 static inline void security_task_to_inode(struct task_struct *p, struct inode *inode)
index 2738d355cdf9a33cf3551cc16228c5d0830bab4a..4398411236f16c3f87691162909dc6197fb62b08 100644 (file)
@@ -179,6 +179,9 @@ struct nf_bridge_info {
        u8                      bridged_dnat:1;
        __u16                   frag_max_size;
        struct net_device       *physindev;
+
+       /* always valid & non-NULL from FORWARD on, for physdev match */
+       struct net_device       *physoutdev;
        union {
                /* prerouting: detect dnat in orig/reply direction */
                __be32          ipv4_daddr;
@@ -189,9 +192,6 @@ struct nf_bridge_info {
                 * skb is out in neigh layer.
                 */
                char neigh_header[8];
-
-               /* always valid & non-NULL from FORWARD on, for physdev match */
-               struct net_device *physoutdev;
        };
 };
 #endif
@@ -2707,6 +2707,9 @@ static inline void skb_postpull_rcsum(struct sk_buff *skb,
 {
        if (skb->ip_summed == CHECKSUM_COMPLETE)
                skb->csum = csum_sub(skb->csum, csum_partial(start, len, 0));
+       else if (skb->ip_summed == CHECKSUM_PARTIAL &&
+                skb_checksum_start_offset(skb) < 0)
+               skb->ip_summed = CHECKSUM_NONE;
 }
 
 unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len);
index 269e8afd3e2a5826c38282a3577447f3ff42997b..635bff60eda57cd2eaa7c2c7da46e32f0193d59d 100644 (file)
@@ -34,7 +34,7 @@ extern struct bus_type spi_bus_type;
 
 /**
  * struct spi_statistics - statistics for spi transfers
- * @clock:         lock protecting this structure
+ * @lock:          lock protecting this structure
  *
  * @messages:      number of spi-messages handled
  * @transfers:     number of spi_transfers handled
@@ -51,6 +51,8 @@ extern struct bus_type spi_bus_type;
  * @bytes_tx:      number of bytes sent to device
  * @bytes_rx:      number of bytes received from device
  *
+ * @transfer_bytes_histo:
+ *                 transfer bytes histogramm
  */
 struct spi_statistics {
        spinlock_t              lock; /* lock for the whole structure */
@@ -68,6 +70,8 @@ struct spi_statistics {
        unsigned long long      bytes_rx;
        unsigned long long      bytes_tx;
 
+#define SPI_STATISTICS_HISTO_SIZE 17
+       unsigned long transfer_bytes_histo[SPI_STATISTICS_HISTO_SIZE];
 };
 
 void spi_statistics_add_transfer_stats(struct spi_statistics *stats,
@@ -843,8 +847,10 @@ extern int spi_bus_unlock(struct spi_master *master);
  * @len: data buffer size
  * Context: can sleep
  *
- * This writes the buffer and returns zero or a negative error code.
+ * This function writes the buffer @buf.
  * Callable only from contexts that can sleep.
+ *
+ * Return: zero on success, else a negative error code.
  */
 static inline int
 spi_write(struct spi_device *spi, const void *buf, size_t len)
@@ -867,8 +873,10 @@ spi_write(struct spi_device *spi, const void *buf, size_t len)
  * @len: data buffer size
  * Context: can sleep
  *
- * This reads the buffer and returns zero or a negative error code.
+ * This function reads the buffer @buf.
  * Callable only from contexts that can sleep.
+ *
+ * Return: zero on success, else a negative error code.
  */
 static inline int
 spi_read(struct spi_device *spi, void *buf, size_t len)
@@ -895,7 +903,7 @@ spi_read(struct spi_device *spi, void *buf, size_t len)
  *
  * For more specific semantics see spi_sync().
  *
- * It returns zero on success, else a negative error code.
+ * Return: Return: zero on success, else a negative error code.
  */
 static inline int
 spi_sync_transfer(struct spi_device *spi, struct spi_transfer *xfers,
@@ -919,9 +927,10 @@ extern int spi_write_then_read(struct spi_device *spi,
  * @cmd: command to be written before data is read back
  * Context: can sleep
  *
- * This returns the (unsigned) eight bit number returned by the
- * device, or else a negative error code.  Callable only from
- * contexts that can sleep.
+ * Callable only from contexts that can sleep.
+ *
+ * Return: the (unsigned) eight bit number returned by the
+ * device, or else a negative error code.
  */
 static inline ssize_t spi_w8r8(struct spi_device *spi, u8 cmd)
 {
@@ -940,12 +949,13 @@ static inline ssize_t spi_w8r8(struct spi_device *spi, u8 cmd)
  * @cmd: command to be written before data is read back
  * Context: can sleep
  *
- * This returns the (unsigned) sixteen bit number returned by the
- * device, or else a negative error code.  Callable only from
- * contexts that can sleep.
- *
  * The number is returned in wire-order, which is at least sometimes
  * big-endian.
+ *
+ * Callable only from contexts that can sleep.
+ *
+ * Return: the (unsigned) sixteen bit number returned by the
+ * device, or else a negative error code.
  */
 static inline ssize_t spi_w8r16(struct spi_device *spi, u8 cmd)
 {
@@ -964,13 +974,13 @@ static inline ssize_t spi_w8r16(struct spi_device *spi, u8 cmd)
  * @cmd: command to be written before data is read back
  * Context: can sleep
  *
- * This returns the (unsigned) sixteen bit number returned by the device in cpu
- * endianness, or else a negative error code. Callable only from contexts that
- * can sleep.
- *
  * This function is similar to spi_w8r16, with the exception that it will
  * convert the read 16 bit data word from big-endian to native endianness.
  *
+ * Callable only from contexts that can sleep.
+ *
+ * Return: the (unsigned) sixteen bit number returned by the device in cpu
+ * endianness, or else a negative error code.
  */
 static inline ssize_t spi_w8r16be(struct spi_device *spi, u8 cmd)
 
index 85578d4be0343ce9ac0bd3f1a9bbb2d349533b44..154788ed218c501d515b55b53b5e2ddcbe4f84a0 100644 (file)
@@ -4,7 +4,7 @@
 #include <linux/workqueue.h>
 
 struct spi_bitbang {
-       spinlock_t              lock;
+       struct mutex            lock;
        u8                      busy;
        u8                      use_dma;
        u8                      flags;          /* extra spi->mode support */
index a8d90db9c4b058626b2d5ddcc84f3fa5d16561aa..9ef7795e65e40c5dfbee53726909fbcb2ce341b0 100644 (file)
@@ -25,6 +25,9 @@ extern char * strncpy(char *,const char *, __kernel_size_t);
 #ifndef __HAVE_ARCH_STRLCPY
 size_t strlcpy(char *, const char *, size_t);
 #endif
+#ifndef __HAVE_ARCH_STRSCPY
+ssize_t __must_check strscpy(char *, const char *, size_t);
+#endif
 #ifndef __HAVE_ARCH_STRCAT
 extern char * strcat(char *, const char *);
 #endif
index 7591788e9fbff3533214cf02435c3d7c1bbb1352..357e44c1a46b1b78d401fded6309b7e4b668f6a6 100644 (file)
@@ -42,6 +42,7 @@ struct sock_xprt {
        /*
         * Connection of transports
         */
+       unsigned long           sock_state;
        struct delayed_work     connect_worker;
        struct sockaddr_storage srcaddr;
        unsigned short          srcport;
@@ -76,6 +77,8 @@ struct sock_xprt {
  */
 #define TCP_RPC_REPLY          (1UL << 6)
 
+#define XPRT_SOCK_CONNECTING   1U
+
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_SUNRPC_XPRTSOCK_H */
index 17292fee868659411f6c8797cb540f978921b034..157d366e761b31541a545904783fea3e21628e24 100644 (file)
@@ -360,7 +360,7 @@ static inline struct thermal_zone_device *
 thermal_zone_of_sensor_register(struct device *dev, int id, void *data,
                                const struct thermal_zone_of_device_ops *ops)
 {
-       return NULL;
+       return ERR_PTR(-ENODEV);
 }
 
 static inline
@@ -380,6 +380,8 @@ static inline bool cdev_is_power_actor(struct thermal_cooling_device *cdev)
 
 int power_actor_get_max_power(struct thermal_cooling_device *,
                              struct thermal_zone_device *tz, u32 *max_power);
+int power_actor_get_min_power(struct thermal_cooling_device *,
+                             struct thermal_zone_device *tz, u32 *min_power);
 int power_actor_set_power(struct thermal_cooling_device *,
                          struct thermal_instance *, u32);
 struct thermal_zone_device *thermal_zone_device_register(const char *, int, int,
@@ -415,6 +417,10 @@ static inline bool cdev_is_power_actor(struct thermal_cooling_device *cdev)
 static inline int power_actor_get_max_power(struct thermal_cooling_device *cdev,
                              struct thermal_zone_device *tz, u32 *max_power)
 { return 0; }
+static inline int power_actor_get_min_power(struct thermal_cooling_device *cdev,
+                                           struct thermal_zone_device *tz,
+                                           u32 *min_power)
+{ return -ENODEV; }
 static inline int power_actor_set_power(struct thermal_cooling_device *cdev,
                          struct thermal_instance *tz, u32 power)
 { return 0; }
index 48d901f83f92e4cf78bc932d94142b4594d65d9d..e312219ff8230bb8a4b8fad60ed4fc0e40a6afd3 100644 (file)
@@ -147,11 +147,20 @@ static inline void tick_nohz_full_add_cpus_to(struct cpumask *mask)
                cpumask_or(mask, mask, tick_nohz_full_mask);
 }
 
+static inline int housekeeping_any_cpu(void)
+{
+       return cpumask_any_and(housekeeping_mask, cpu_online_mask);
+}
+
 extern void tick_nohz_full_kick(void);
 extern void tick_nohz_full_kick_cpu(int cpu);
 extern void tick_nohz_full_kick_all(void);
 extern void __tick_nohz_task_switch(void);
 #else
+static inline int housekeeping_any_cpu(void)
+{
+       return smp_processor_id();
+}
 static inline bool tick_nohz_full_enabled(void) { return false; }
 static inline bool tick_nohz_full_cpu(int cpu) { return false; }
 static inline void tick_nohz_full_add_cpus_to(struct cpumask *mask) { }
index 3dd5a781da99f163930e8a0611f269d1946daf6b..bfb74723f151512780ceb404255cb43ef92c764d 100644 (file)
@@ -157,7 +157,7 @@ struct renesas_usbhs_driver_param {
         */
        int pio_dma_border; /* default is 64byte */
 
-       u32 type;
+       uintptr_t type;
        u32 enable_gpio;
 
        /*
index d3d077228d4c155ad4b08a6668dc725679996372..1e1bf9f963a947fc686125d0a2809ad63b8a13ed 100644 (file)
@@ -147,8 +147,7 @@ __remove_wait_queue(wait_queue_head_t *head, wait_queue_t *old)
 
 typedef int wait_bit_action_f(struct wait_bit_key *);
 void __wake_up(wait_queue_head_t *q, unsigned int mode, int nr, void *key);
-void __wake_up_locked_key(wait_queue_head_t *q, unsigned int mode, int nr,
-                         void *key);
+void __wake_up_locked_key(wait_queue_head_t *q, unsigned int mode, void *key);
 void __wake_up_sync_key(wait_queue_head_t *q, unsigned int mode, int nr, void *key);
 void __wake_up_locked(wait_queue_head_t *q, unsigned int mode, int nr);
 void __wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr);
@@ -180,7 +179,7 @@ wait_queue_head_t *bit_waitqueue(void *, int);
 #define wake_up_poll(x, m)                                             \
        __wake_up(x, TASK_NORMAL, 1, (void *) (m))
 #define wake_up_locked_poll(x, m)                                      \
-       __wake_up_locked_key((x), TASK_NORMAL, 1, (void *) (m))
+       __wake_up_locked_key((x), TASK_NORMAL, (void *) (m))
 #define wake_up_interruptible_poll(x, m)                               \
        __wake_up(x, TASK_INTERRUPTIBLE, 1, (void *) (m))
 #define wake_up_interruptible_sync_poll(x, m)                          \
index 4a167b30a12ff0d127cccab36c07669689223441..b36d837c701ec9fe94280a91df3cf1e359ad50af 100644 (file)
@@ -63,7 +63,11 @@ struct unix_sock {
 #define UNIX_GC_MAYBE_CYCLE    1
        struct socket_wq        peer_wq;
 };
-#define unix_sk(__sk) ((struct unix_sock *)__sk)
+
+static inline struct unix_sock *unix_sk(const struct sock *sk)
+{
+       return (struct unix_sock *)sk;
+}
 
 #define peer_wait peer_wq.wait
 
index af9d5382f6cbae8c38d45106f5702bd1e66c5671..ce009710120ca8b541615b237a329ee089ec357b 100644 (file)
@@ -60,6 +60,38 @@ static inline struct metadata_dst *tun_rx_dst(int md_size)
        return tun_dst;
 }
 
+static inline struct metadata_dst *tun_dst_unclone(struct sk_buff *skb)
+{
+       struct metadata_dst *md_dst = skb_metadata_dst(skb);
+       int md_size = md_dst->u.tun_info.options_len;
+       struct metadata_dst *new_md;
+
+       if (!md_dst)
+               return ERR_PTR(-EINVAL);
+
+       new_md = metadata_dst_alloc(md_size, GFP_ATOMIC);
+       if (!new_md)
+               return ERR_PTR(-ENOMEM);
+
+       memcpy(&new_md->u.tun_info, &md_dst->u.tun_info,
+              sizeof(struct ip_tunnel_info) + md_size);
+       skb_dst_drop(skb);
+       dst_hold(&new_md->dst);
+       skb_dst_set(skb, &new_md->dst);
+       return new_md;
+}
+
+static inline struct ip_tunnel_info *skb_tunnel_info_unclone(struct sk_buff *skb)
+{
+       struct metadata_dst *dst;
+
+       dst = tun_dst_unclone(skb);
+       if (IS_ERR(dst))
+               return NULL;
+
+       return &dst->u.tun_info;
+}
+
 static inline struct metadata_dst *ip_tun_rx_dst(struct sk_buff *skb,
                                                 __be16 flags,
                                                 __be64 tunnel_id,
index acd6a096250e65e149db68d18b22d8dd320b6b39..9b85db85f13cfc2c11713da810260d4da554bde3 100644 (file)
@@ -35,6 +35,7 @@ struct flowi_common {
 #define FLOWI_FLAG_ANYSRC              0x01
 #define FLOWI_FLAG_KNOWN_NH            0x02
 #define FLOWI_FLAG_VRFSRC              0x04
+#define FLOWI_FLAG_SKIP_NH_OIF         0x08
        __u32   flowic_secid;
        struct flowi_tunnel flowic_tun_key;
 };
index 879d6e5a973b4ae1af54d6b0c6103c02ee774991..fc19376986259de8faf9c2be4c5c3376780e54ff 100644 (file)
@@ -110,7 +110,19 @@ struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk,
 void __inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk,
                           struct inet_hashinfo *hashinfo);
 
-void inet_twsk_schedule(struct inet_timewait_sock *tw, const int timeo);
+void __inet_twsk_schedule(struct inet_timewait_sock *tw, int timeo,
+                         bool rearm);
+
+static inline void inet_twsk_schedule(struct inet_timewait_sock *tw, int timeo)
+{
+       __inet_twsk_schedule(tw, timeo, false);
+}
+
+static inline void inet_twsk_reschedule(struct inet_timewait_sock *tw, int timeo)
+{
+       __inet_twsk_schedule(tw, timeo, true);
+}
+
 void inet_twsk_deschedule_put(struct inet_timewait_sock *tw);
 
 void inet_twsk_purge(struct inet_hashinfo *hashinfo,
index 063d30474cf66077a7491ac8efbf4d400070c49e..aaf9700fc9e5f8279a172a7ee447cf4f9b5b6ffe 100644 (file)
@@ -275,7 +275,8 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt,
             struct nl_info *info, struct mx6_config *mxc);
 int fib6_del(struct rt6_info *rt, struct nl_info *info);
 
-void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info);
+void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info,
+                    unsigned int flags);
 
 void fib6_run_gc(unsigned long expires, struct net *net, bool force);
 
index b8529aa1dae7a0b601008afd18a8218c41ab10ff..fa915fa0f703dc03d21ae51b50cbd11c7fb74561 100644 (file)
@@ -32,6 +32,12 @@ struct __ip6_tnl_parm {
        __be32                  o_key;
 };
 
+struct ip6_tnl_dst {
+       seqlock_t lock;
+       struct dst_entry __rcu *dst;
+       u32 cookie;
+};
+
 /* IPv6 tunnel */
 struct ip6_tnl {
        struct ip6_tnl __rcu *next;     /* next tunnel in list */
@@ -39,8 +45,7 @@ struct ip6_tnl {
        struct net *net;        /* netns for packet i/o */
        struct __ip6_tnl_parm parms;    /* tunnel configuration parameters */
        struct flowi fl;        /* flowi template for xmit */
-       struct dst_entry *dst_cache;    /* cached dst */
-       u32 dst_cookie;
+       struct ip6_tnl_dst __percpu *dst_cache; /* cached dst */
 
        int err_count;
        unsigned long err_time;
@@ -60,9 +65,11 @@ struct ipv6_tlv_tnl_enc_lim {
        __u8 encap_limit;       /* tunnel encapsulation limit   */
 } __packed;
 
-struct dst_entry *ip6_tnl_dst_check(struct ip6_tnl *t);
+struct dst_entry *ip6_tnl_dst_get(struct ip6_tnl *t);
+int ip6_tnl_dst_init(struct ip6_tnl *t);
+void ip6_tnl_dst_destroy(struct ip6_tnl *t);
 void ip6_tnl_dst_reset(struct ip6_tnl *t);
-void ip6_tnl_dst_store(struct ip6_tnl *t, struct dst_entry *dst);
+void ip6_tnl_dst_set(struct ip6_tnl *t, struct dst_entry *dst);
 int ip6_tnl_rcv_ctl(struct ip6_tnl *t, const struct in6_addr *laddr,
                const struct in6_addr *raddr);
 int ip6_tnl_xmit_ctl(struct ip6_tnl *t, const struct in6_addr *laddr,
@@ -79,7 +86,7 @@ static inline void ip6tunnel_xmit(struct sock *sk, struct sk_buff *skb,
        struct net_device_stats *stats = &dev->stats;
        int pkt_len, err;
 
-       pkt_len = skb->len;
+       pkt_len = skb->len - skb_inner_network_offset(skb);
        err = ip6_local_out_sk(sk, skb);
 
        if (net_xmit_eval(err) == 0) {
index a37d0432bebda440708516c7f270f931764676dd..727d6e9a96856b4fde184a188e1aec003ed4bfa9 100644 (file)
@@ -236,8 +236,11 @@ static inline int fib_lookup(struct net *net, const struct flowi4 *flp,
        rcu_read_lock();
 
        tb = fib_get_table(net, RT_TABLE_MAIN);
-       if (tb && !fib_table_lookup(tb, flp, res, flags | FIB_LOOKUP_NOREF))
-               err = 0;
+       if (tb)
+               err = fib_table_lookup(tb, flp, res, flags | FIB_LOOKUP_NOREF);
+
+       if (err == -EAGAIN)
+               err = -ENETUNREACH;
 
        rcu_read_unlock();
 
@@ -258,7 +261,7 @@ static inline int fib_lookup(struct net *net, struct flowi4 *flp,
                             struct fib_result *res, unsigned int flags)
 {
        struct fib_table *tb;
-       int err;
+       int err = -ENETUNREACH;
 
        flags |= FIB_LOOKUP_NOREF;
        if (net->ipv4.fib_has_custom_rules)
@@ -268,15 +271,20 @@ static inline int fib_lookup(struct net *net, struct flowi4 *flp,
 
        res->tclassid = 0;
 
-       for (err = 0; !err; err = -ENETUNREACH) {
-               tb = rcu_dereference_rtnl(net->ipv4.fib_main);
-               if (tb && !fib_table_lookup(tb, flp, res, flags))
-                       break;
+       tb = rcu_dereference_rtnl(net->ipv4.fib_main);
+       if (tb)
+               err = fib_table_lookup(tb, flp, res, flags);
+
+       if (!err)
+               goto out;
+
+       tb = rcu_dereference_rtnl(net->ipv4.fib_default);
+       if (tb)
+               err = fib_table_lookup(tb, flp, res, flags);
 
-               tb = rcu_dereference_rtnl(net->ipv4.fib_default);
-               if (tb && !fib_table_lookup(tb, flp, res, flags))
-                       break;
-       }
+out:
+       if (err == -EAGAIN)
+               err = -ENETUNREACH;
 
        rcu_read_unlock();
 
index 9a6a3ba888e8d48e9cd706f48f045113e79d19f4..f6dafec9102c5f03e08fdd7fc3efc4812e4137ce 100644 (file)
@@ -276,6 +276,8 @@ int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto);
 int iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb,
                  __be32 src, __be32 dst, u8 proto,
                  u8 tos, u8 ttl, __be16 df, bool xnet);
+struct metadata_dst *iptunnel_metadata_reply(struct metadata_dst *md,
+                                            gfp_t flags);
 
 struct sk_buff *iptunnel_handle_offloads(struct sk_buff *skb, bool gre_csum,
                                         int gso_type_mask);
index cc61cb95f059152bc8cc58c0a2cacb2d9099e103..f46af256880cd9ff0f9fccc503d7cdc83ef3cbd3 100644 (file)
@@ -255,7 +255,7 @@ static inline void ip_route_connect_init(struct flowi4 *fl4, __be32 dst, __be32
                flow_flags |= FLOWI_FLAG_ANYSRC;
 
        if (netif_index_is_vrf(sock_net(sk), oif))
-               flow_flags |= FLOWI_FLAG_VRFSRC;
+               flow_flags |= FLOWI_FLAG_VRFSRC | FLOWI_FLAG_SKIP_NH_OIF;
 
        flowi4_init_output(fl4, oif, sk->sk_mark, tos, RT_SCOPE_UNIVERSE,
                           protocol, flow_flags, dst, src, dport, sport);
index 7aa78440559a47db8e5ccc8ea69a34f87b90c125..e23717013a4e6cb1ef84e6b8ba6654b011ee8670 100644 (file)
@@ -828,6 +828,14 @@ static inline __must_check int sk_add_backlog(struct sock *sk, struct sk_buff *s
        if (sk_rcvqueues_full(sk, limit))
                return -ENOBUFS;
 
+       /*
+        * If the skb was allocated from pfmemalloc reserves, only
+        * allow SOCK_MEMALLOC sockets to use it as this socket is
+        * helping free memory
+        */
+       if (skb_pfmemalloc(skb) && !sock_flag(sk, SOCK_MEMALLOC))
+               return -ENOMEM;
+
        __sk_add_backlog(sk, skb);
        sk->sk_backlog.len += skb->truesize;
        return 0;
index 391dae1931c082d85f4023ff83a2f51aa0a7052d..a0fa975cd1c1c94f8e0c77991557a7ed87efb83e 100644 (file)
@@ -294,8 +294,8 @@ struct opa_port_states {
 
 struct opa_port_state_info {
        struct opa_port_states port_states;
-       u16 link_width_downgrade_tx_active;
-       u16 link_width_downgrade_rx_active;
+       __be16 link_width_downgrade_tx_active;
+       __be16 link_width_downgrade_rx_active;
 };
 
 struct opa_port_info {
index 884e728b09d9a57e8a56ac8ea224b3f873cb81c3..26ede14597daba32f8bf2cfcc84a821d094cc3d3 100644 (file)
@@ -86,7 +86,7 @@
        .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
        SNDRV_CTL_ELEM_ACCESS_READWRITE, \
        .tlv.p  = (tlv_array),\
-       .info = snd_soc_info_volsw, \
+       .info = snd_soc_info_volsw_sx, \
        .get = snd_soc_get_volsw_sx,\
        .put = snd_soc_put_volsw_sx, \
        .private_value = (unsigned long)&(struct soc_mixer_control) \
        .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
        SNDRV_CTL_ELEM_ACCESS_READWRITE, \
        .tlv.p  = (tlv_array), \
-       .info = snd_soc_info_volsw, \
+       .info = snd_soc_info_volsw_sx, \
        .get = snd_soc_get_volsw_sx, \
        .put = snd_soc_put_volsw_sx, \
        .private_value = (unsigned long)&(struct soc_mixer_control) \
@@ -574,6 +574,8 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol);
 int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_info *uinfo);
+int snd_soc_info_volsw_sx(struct snd_kcontrol *kcontrol,
+                         struct snd_ctl_elem_info *uinfo);
 #define snd_soc_info_bool_ext          snd_ctl_boolean_mono_info
 int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol);
index 898be3a8db9aecfc8c9e942e03053b582be3af2a..6d8f8fba33414a40cefc344811ec3acfecd72f01 100644 (file)
 #define WM8904_MIC_REGS  2
 #define WM8904_GPIO_REGS 4
 #define WM8904_DRC_REGS  4
-#define WM8904_EQ_REGS   25
+#define WM8904_EQ_REGS   24
 
 /**
  * DRC configurations are specified with a label and a set of register
index ac9bf1c0e42d851a6059224cbea852b5d7b9bd44..5f48754dc36ae0e15e06527c0cb63dc29324721e 100644 (file)
@@ -730,6 +730,7 @@ struct se_device {
 #define DF_EMULATED_VPD_UNIT_SERIAL            0x00000004
 #define DF_USING_UDEV_PATH                     0x00000008
 #define DF_USING_ALIAS                         0x00000010
+#define DF_READ_ONLY                           0x00000020
        /* Physical device queue depth */
        u32                     queue_depth;
        /* Used for SPC-2 reservations enforce of ISIDs */
index 9df61f1edb0f8048472bee5136f81097e47ac569..3094618d382f4d661dd14f9ceb4f4180a8f2c39d 100644 (file)
  *     SA_RESTORER     0x04000000
  */
 
+#if !defined MINSIGSTKSZ || !defined SIGSTKSZ
 #define MINSIGSTKSZ    2048
 #define SIGSTKSZ       8192
+#endif
 
 #ifndef __ASSEMBLY__
 typedef struct {
index 8da542a2874d6c3490860eec0092ac26998a303d..ee124009e12adb073ec17221bc570da60cf5eaea 100644 (file)
@@ -709,17 +709,19 @@ __SYSCALL(__NR_memfd_create, sys_memfd_create)
 __SYSCALL(__NR_bpf, sys_bpf)
 #define __NR_execveat 281
 __SC_COMP(__NR_execveat, sys_execveat, compat_sys_execveat)
-#define __NR_membarrier 282
+#define __NR_userfaultfd 282
+__SYSCALL(__NR_userfaultfd, sys_userfaultfd)
+#define __NR_membarrier 283
 __SYSCALL(__NR_membarrier, sys_membarrier)
 
 #undef __NR_syscalls
-#define __NR_syscalls 283
+#define __NR_syscalls 284
 
 /*
  * All syscalls below here should go away really,
  * these are provided for both review and as a porting
  * help for the C library version.
-*
+ *
  * Last chance: are any of these important enough to
  * enable by default?
  */
index 34141a5dfe745877d1e3905373a2255e93b888ab..f8b01887a4958097c9c2fede065391c553683e80 100644 (file)
@@ -21,8 +21,6 @@ enum lwtunnel_ip_t {
        LWTUNNEL_IP_SRC,
        LWTUNNEL_IP_TTL,
        LWTUNNEL_IP_TOS,
-       LWTUNNEL_IP_SPORT,
-       LWTUNNEL_IP_DPORT,
        LWTUNNEL_IP_FLAGS,
        __LWTUNNEL_IP_MAX,
 };
@@ -36,8 +34,6 @@ enum lwtunnel_ip6_t {
        LWTUNNEL_IP6_SRC,
        LWTUNNEL_IP6_HOPLIMIT,
        LWTUNNEL_IP6_TC,
-       LWTUNNEL_IP6_SPORT,
-       LWTUNNEL_IP6_DPORT,
        LWTUNNEL_IP6_FLAGS,
        __LWTUNNEL_IP6_MAX,
 };
index 32e07d8cbaf47cf80841adf0e872d85c26c8c708..e663627a8ef36530b4dc658e9d30d4b7bc32a90a 100644 (file)
@@ -323,10 +323,10 @@ enum ovs_key_attr {
        OVS_KEY_ATTR_MPLS,      /* array of struct ovs_key_mpls.
                                 * The implementation may restrict
                                 * the accepted length of the array. */
-       OVS_KEY_ATTR_CT_STATE,  /* u8 bitmask of OVS_CS_F_* */
+       OVS_KEY_ATTR_CT_STATE,  /* u32 bitmask of OVS_CS_F_* */
        OVS_KEY_ATTR_CT_ZONE,   /* u16 connection tracking zone. */
        OVS_KEY_ATTR_CT_MARK,   /* u32 connection tracking mark */
-       OVS_KEY_ATTR_CT_LABEL /* 16-octet connection tracking label */
+       OVS_KEY_ATTR_CT_LABELS, /* 16-octet connection tracking label */
 
 #ifdef __KERNEL__
        OVS_KEY_ATTR_TUNNEL_INFO,  /* struct ip_tunnel_info */
@@ -439,9 +439,9 @@ struct ovs_key_nd {
        __u8    nd_tll[ETH_ALEN];
 };
 
-#define OVS_CT_LABEL_LEN       16
-struct ovs_key_ct_label {
-       __u8    ct_label[OVS_CT_LABEL_LEN];
+#define OVS_CT_LABELS_LEN      16
+struct ovs_key_ct_labels {
+       __u8    ct_labels[OVS_CT_LABELS_LEN];
 };
 
 /* OVS_KEY_ATTR_CT_STATE flags */
@@ -449,9 +449,9 @@ struct ovs_key_ct_label {
 #define OVS_CS_F_ESTABLISHED       0x02 /* Part of an existing connection. */
 #define OVS_CS_F_RELATED           0x04 /* Related to an established
                                         * connection. */
-#define OVS_CS_F_INVALID           0x20 /* Could not track connection. */
-#define OVS_CS_F_REPLY_DIR         0x40 /* Flow is in the reply direction. */
-#define OVS_CS_F_TRACKED           0x80 /* Conntrack has occurred. */
+#define OVS_CS_F_REPLY_DIR         0x08 /* Flow is in the reply direction. */
+#define OVS_CS_F_INVALID           0x10 /* Could not track connection. */
+#define OVS_CS_F_TRACKED           0x20 /* Conntrack has occurred. */
 
 /**
  * enum ovs_flow_attr - attributes for %OVS_FLOW_* commands.
@@ -618,22 +618,25 @@ struct ovs_action_hash {
 
 /**
  * enum ovs_ct_attr - Attributes for %OVS_ACTION_ATTR_CT action.
- * @OVS_CT_ATTR_FLAGS: u32 connection tracking flags.
+ * @OVS_CT_ATTR_COMMIT: If present, commits the connection to the conntrack
+ * table. This allows future packets for the same connection to be identified
+ * as 'established' or 'related'. The flow key for the current packet will
+ * retain the pre-commit connection state.
  * @OVS_CT_ATTR_ZONE: u16 connection tracking zone.
  * @OVS_CT_ATTR_MARK: u32 value followed by u32 mask. For each bit set in the
  * mask, the corresponding bit in the value is copied to the connection
  * tracking mark field in the connection.
- * @OVS_CT_ATTR_LABEL: %OVS_CT_LABEL_LEN value followed by %OVS_CT_LABEL_LEN
+ * @OVS_CT_ATTR_LABEL: %OVS_CT_LABELS_LEN value followed by %OVS_CT_LABELS_LEN
  * mask. For each bit set in the mask, the corresponding bit in the value is
  * copied to the connection tracking label field in the connection.
  * @OVS_CT_ATTR_HELPER: variable length string defining conntrack ALG.
  */
 enum ovs_ct_attr {
        OVS_CT_ATTR_UNSPEC,
-       OVS_CT_ATTR_FLAGS,      /* u8 bitmask of OVS_CT_F_*. */
+       OVS_CT_ATTR_COMMIT,     /* No argument, commits connection. */
        OVS_CT_ATTR_ZONE,       /* u16 zone id. */
        OVS_CT_ATTR_MARK,       /* mark to associate with this connection. */
-       OVS_CT_ATTR_LABEL,      /* label to associate with this connection. */
+       OVS_CT_ATTR_LABELS,     /* labels to associate with this connection. */
        OVS_CT_ATTR_HELPER,     /* netlink helper to assist detection of
                                   related connections. */
        __OVS_CT_ATTR_MAX
@@ -641,14 +644,6 @@ enum ovs_ct_attr {
 
 #define OVS_CT_ATTR_MAX (__OVS_CT_ATTR_MAX - 1)
 
-/*
- * OVS_CT_ATTR_FLAGS flags - bitmask of %OVS_CT_F_*
- * @OVS_CT_F_COMMIT: Commits the flow to the conntrack table. This allows
- * future packets for the same connection to be identified as 'established'
- * or 'related'.
- */
-#define OVS_CT_F_COMMIT                0x01
-
 /**
  * enum ovs_action_attr - Action types.
  *
@@ -705,7 +700,7 @@ enum ovs_action_attr {
                                       * data immediately followed by a mask.
                                       * The data must be zero for the unmasked
                                       * bits. */
-       OVS_ACTION_ATTR_CT,           /* One nested OVS_CT_ATTR_* . */
+       OVS_ACTION_ATTR_CT,           /* Nested OVS_CT_ATTR_* . */
 
        __OVS_ACTION_ATTR_MAX,        /* Nothing past this will be accepted
                                       * from userspace. */
index 702024769c74bc39f1e9f8400b23ec5bbd7a8ffb..9d8f5d10c1e553122be08d3407434ea24d19c136 100644 (file)
@@ -160,7 +160,7 @@ struct rtattr {
 
 /* Macros to handle rtattributes */
 
-#define RTA_ALIGNTO    4
+#define RTA_ALIGNTO    4U
 #define RTA_ALIGN(len) ( ((len)+RTA_ALIGNTO-1) & ~(RTA_ALIGNTO-1) )
 #define RTA_OK(rta,len) ((len) >= (int)sizeof(struct rtattr) && \
                         (rta)->rta_len >= sizeof(struct rtattr) && \
index df0e09bb7dd5a20f068b6b2a916d6a33a3ccf5ef..9057d7af3ae145ba711c837f4bcbe58e851f2320 100644 (file)
@@ -11,8 +11,6 @@
 
 #include <linux/types.h>
 
-#include <linux/compiler.h>
-
 #define UFFD_API ((__u64)0xAA)
 /*
  * After implementing the respective features it will become:
index 9ce083960a2575df0bd2a4e31ac3c8b881012880..f18490985fc8e5f39d10ed442d302293ac0e7699 100644 (file)
@@ -107,5 +107,13 @@ struct sched_watchdog {
 #define SHUTDOWN_suspend    2  /* Clean up, save suspend info, kill.         */
 #define SHUTDOWN_crash      3  /* Tell controller we've crashed.             */
 #define SHUTDOWN_watchdog   4  /* Restart because watchdog time expired.     */
+/*
+ * Domain asked to perform 'soft reset' for it. The expected behavior is to
+ * reset internal Xen state for the domain returning it to the point where it
+ * was created but leaving the domain's memory contents and vCPU contexts
+ * intact. This will allow the domain to start over and set up all Xen specific
+ * interfaces again.
+ */
+#define SHUTDOWN_soft_reset 5
 
 #endif /* __XEN_PUBLIC_SCHED_H__ */
index 66c4f567eb7368d21ff11377f629c53cc169bc8b..1471db9a7e6112b3316ae887b50c6d8d1352f171 100644 (file)
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -137,13 +137,6 @@ static int newque(struct ipc_namespace *ns, struct ipc_params *params)
                return retval;
        }
 
-       /* ipc_addid() locks msq upon success. */
-       id = ipc_addid(&msg_ids(ns), &msq->q_perm, ns->msg_ctlmni);
-       if (id < 0) {
-               ipc_rcu_putref(msq, msg_rcu_free);
-               return id;
-       }
-
        msq->q_stime = msq->q_rtime = 0;
        msq->q_ctime = get_seconds();
        msq->q_cbytes = msq->q_qnum = 0;
@@ -153,6 +146,13 @@ static int newque(struct ipc_namespace *ns, struct ipc_params *params)
        INIT_LIST_HEAD(&msq->q_receivers);
        INIT_LIST_HEAD(&msq->q_senders);
 
+       /* ipc_addid() locks msq upon success. */
+       id = ipc_addid(&msg_ids(ns), &msq->q_perm, ns->msg_ctlmni);
+       if (id < 0) {
+               ipc_rcu_putref(msq, msg_rcu_free);
+               return id;
+       }
+
        ipc_unlock_object(&msq->q_perm);
        rcu_read_unlock();
 
index 222131e8e38f334547004bf0830b26bf808cc6a2..41787276e14170af7de8261181721991fde528bf 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -551,12 +551,6 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
        if (IS_ERR(file))
                goto no_file;
 
-       id = ipc_addid(&shm_ids(ns), &shp->shm_perm, ns->shm_ctlmni);
-       if (id < 0) {
-               error = id;
-               goto no_id;
-       }
-
        shp->shm_cprid = task_tgid_vnr(current);
        shp->shm_lprid = 0;
        shp->shm_atim = shp->shm_dtim = 0;
@@ -565,6 +559,13 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
        shp->shm_nattch = 0;
        shp->shm_file = file;
        shp->shm_creator = current;
+
+       id = ipc_addid(&shm_ids(ns), &shp->shm_perm, ns->shm_ctlmni);
+       if (id < 0) {
+               error = id;
+               goto no_id;
+       }
+
        list_add(&shp->shm_clist, &current->sysvshm.shm_clist);
 
        /*
index be4230020a1f718c31b02012554600c710b928b9..0f401d94b7c657d5e7126fe78f149c94ffea8e24 100644 (file)
@@ -237,6 +237,10 @@ int ipc_addid(struct ipc_ids *ids, struct kern_ipc_perm *new, int size)
        rcu_read_lock();
        spin_lock(&new->lock);
 
+       current_euid_egid(&euid, &egid);
+       new->cuid = new->uid = euid;
+       new->gid = new->cgid = egid;
+
        id = idr_alloc(&ids->ipcs_idr, new,
                       (next_id < 0) ? 0 : ipcid_to_idx(next_id), 0,
                       GFP_NOWAIT);
@@ -249,10 +253,6 @@ int ipc_addid(struct ipc_ids *ids, struct kern_ipc_perm *new, int size)
 
        ids->in_use++;
 
-       current_euid_egid(&euid, &egid);
-       new->cuid = new->uid = euid;
-       new->gid = new->cgid = egid;
-
        if (next_id < 0) {
                new->seq = ids->seq++;
                if (ids->seq > IPCID_SEQ_MAX)
index 2cf0f79f1fc9014cffce5ed79969bbcdaa3b9f90..2c9eae6ad9704d3278557f6c692d2ef0027b587b 100644 (file)
@@ -46,7 +46,6 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/rwsem.h>
-#include <linux/percpu-rwsem.h>
 #include <linux/string.h>
 #include <linux/sort.h>
 #include <linux/kmod.h>
@@ -104,8 +103,6 @@ static DEFINE_SPINLOCK(cgroup_idr_lock);
  */
 static DEFINE_SPINLOCK(release_agent_path_lock);
 
-struct percpu_rw_semaphore cgroup_threadgroup_rwsem;
-
 #define cgroup_assert_mutex_or_rcu_locked()                            \
        RCU_LOCKDEP_WARN(!rcu_read_lock_held() &&                       \
                           !lockdep_is_held(&cgroup_mutex),             \
@@ -874,6 +871,48 @@ static struct css_set *find_css_set(struct css_set *old_cset,
        return cset;
 }
 
+void cgroup_threadgroup_change_begin(struct task_struct *tsk)
+{
+       down_read(&tsk->signal->group_rwsem);
+}
+
+void cgroup_threadgroup_change_end(struct task_struct *tsk)
+{
+       up_read(&tsk->signal->group_rwsem);
+}
+
+/**
+ * threadgroup_lock - lock threadgroup
+ * @tsk: member task of the threadgroup to lock
+ *
+ * Lock the threadgroup @tsk belongs to.  No new task is allowed to enter
+ * and member tasks aren't allowed to exit (as indicated by PF_EXITING) or
+ * change ->group_leader/pid.  This is useful for cases where the threadgroup
+ * needs to stay stable across blockable operations.
+ *
+ * fork and exit explicitly call threadgroup_change_{begin|end}() for
+ * synchronization.  While held, no new task will be added to threadgroup
+ * and no existing live task will have its PF_EXITING set.
+ *
+ * de_thread() does threadgroup_change_{begin|end}() when a non-leader
+ * sub-thread becomes a new leader.
+ */
+static void threadgroup_lock(struct task_struct *tsk)
+{
+       down_write(&tsk->signal->group_rwsem);
+}
+
+/**
+ * threadgroup_unlock - unlock threadgroup
+ * @tsk: member task of the threadgroup to unlock
+ *
+ * Reverse threadgroup_lock().
+ */
+static inline void threadgroup_unlock(struct task_struct *tsk)
+{
+       up_write(&tsk->signal->group_rwsem);
+}
+
 static struct cgroup_root *cgroup_root_from_kf(struct kernfs_root *kf_root)
 {
        struct cgroup *root_cgrp = kf_root->kn->priv;
@@ -2074,9 +2113,9 @@ static void cgroup_task_migrate(struct cgroup *old_cgrp,
        lockdep_assert_held(&css_set_rwsem);
 
        /*
-        * We are synchronized through cgroup_threadgroup_rwsem against
-        * PF_EXITING setting such that we can't race against cgroup_exit()
-        * changing the css_set to init_css_set and dropping the old one.
+        * We are synchronized through threadgroup_lock() against PF_EXITING
+        * setting such that we can't race against cgroup_exit() changing the
+        * css_set to init_css_set and dropping the old one.
         */
        WARN_ON_ONCE(tsk->flags & PF_EXITING);
        old_cset = task_css_set(tsk);
@@ -2133,11 +2172,10 @@ static void cgroup_migrate_finish(struct list_head *preloaded_csets)
  * @src_cset and add it to @preloaded_csets, which should later be cleaned
  * up by cgroup_migrate_finish().
  *
- * This function may be called without holding cgroup_threadgroup_rwsem
- * even if the target is a process.  Threads may be created and destroyed
- * but as long as cgroup_mutex is not dropped, no new css_set can be put
- * into play and the preloaded css_sets are guaranteed to cover all
- * migrations.
+ * This function may be called without holding threadgroup_lock even if the
+ * target is a process.  Threads may be created and destroyed but as long
+ * as cgroup_mutex is not dropped, no new css_set can be put into play and
+ * the preloaded css_sets are guaranteed to cover all migrations.
  */
 static void cgroup_migrate_add_src(struct css_set *src_cset,
                                   struct cgroup *dst_cgrp,
@@ -2240,7 +2278,7 @@ err:
  * @threadgroup: whether @leader points to the whole process or a single task
  *
  * Migrate a process or task denoted by @leader to @cgrp.  If migrating a
- * process, the caller must be holding cgroup_threadgroup_rwsem.  The
+ * process, the caller must be holding threadgroup_lock of @leader.  The
  * caller is also responsible for invoking cgroup_migrate_add_src() and
  * cgroup_migrate_prepare_dst() on the targets before invoking this
  * function and following up with cgroup_migrate_finish().
@@ -2368,7 +2406,7 @@ out_release_tset:
  * @leader: the task or the leader of the threadgroup to be attached
  * @threadgroup: attach the whole threadgroup?
  *
- * Call holding cgroup_mutex and cgroup_threadgroup_rwsem.
+ * Call holding cgroup_mutex and threadgroup_lock of @leader.
  */
 static int cgroup_attach_task(struct cgroup *dst_cgrp,
                              struct task_struct *leader, bool threadgroup)
@@ -2460,13 +2498,14 @@ static ssize_t __cgroup_procs_write(struct kernfs_open_file *of, char *buf,
        if (!cgrp)
                return -ENODEV;
 
-       percpu_down_write(&cgroup_threadgroup_rwsem);
+retry_find_task:
        rcu_read_lock();
        if (pid) {
                tsk = find_task_by_vpid(pid);
                if (!tsk) {
+                       rcu_read_unlock();
                        ret = -ESRCH;
-                       goto out_unlock_rcu;
+                       goto out_unlock_cgroup;
                }
        } else {
                tsk = current;
@@ -2482,23 +2521,37 @@ static ssize_t __cgroup_procs_write(struct kernfs_open_file *of, char *buf,
         */
        if (tsk == kthreadd_task || (tsk->flags & PF_NO_SETAFFINITY)) {
                ret = -EINVAL;
-               goto out_unlock_rcu;
+               rcu_read_unlock();
+               goto out_unlock_cgroup;
        }
 
        get_task_struct(tsk);
        rcu_read_unlock();
 
+       threadgroup_lock(tsk);
+       if (threadgroup) {
+               if (!thread_group_leader(tsk)) {
+                       /*
+                        * a race with de_thread from another thread's exec()
+                        * may strip us of our leadership, if this happens,
+                        * there is no choice but to throw this task away and
+                        * try again; this is
+                        * "double-double-toil-and-trouble-check locking".
+                        */
+                       threadgroup_unlock(tsk);
+                       put_task_struct(tsk);
+                       goto retry_find_task;
+               }
+       }
+
        ret = cgroup_procs_write_permission(tsk, cgrp, of);
        if (!ret)
                ret = cgroup_attach_task(cgrp, tsk, threadgroup);
 
-       put_task_struct(tsk);
-       goto out_unlock_threadgroup;
+       threadgroup_unlock(tsk);
 
-out_unlock_rcu:
-       rcu_read_unlock();
-out_unlock_threadgroup:
-       percpu_up_write(&cgroup_threadgroup_rwsem);
+       put_task_struct(tsk);
+out_unlock_cgroup:
        cgroup_kn_unlock(of->kn);
        return ret ?: nbytes;
 }
@@ -2643,8 +2696,6 @@ static int cgroup_update_dfl_csses(struct cgroup *cgrp)
 
        lockdep_assert_held(&cgroup_mutex);
 
-       percpu_down_write(&cgroup_threadgroup_rwsem);
-
        /* look up all csses currently attached to @cgrp's subtree */
        down_read(&css_set_rwsem);
        css_for_each_descendant_pre(css, cgroup_css(cgrp, NULL)) {
@@ -2700,8 +2751,17 @@ static int cgroup_update_dfl_csses(struct cgroup *cgrp)
                                goto out_finish;
                        last_task = task;
 
+                       threadgroup_lock(task);
+                       /* raced against de_thread() from another thread? */
+                       if (!thread_group_leader(task)) {
+                               threadgroup_unlock(task);
+                               put_task_struct(task);
+                               continue;
+                       }
+
                        ret = cgroup_migrate(src_cset->dfl_cgrp, task, true);
 
+                       threadgroup_unlock(task);
                        put_task_struct(task);
 
                        if (WARN(ret, "cgroup: failed to update controllers for the default hierarchy (%d), further operations may crash or hang\n", ret))
@@ -2711,7 +2771,6 @@ static int cgroup_update_dfl_csses(struct cgroup *cgrp)
 
 out_finish:
        cgroup_migrate_finish(&preloaded_csets);
-       percpu_up_write(&cgroup_threadgroup_rwsem);
        return ret;
 }
 
@@ -5024,7 +5083,6 @@ int __init cgroup_init(void)
        unsigned long key;
        int ssid, err;
 
-       BUG_ON(percpu_init_rwsem(&cgroup_threadgroup_rwsem));
        BUG_ON(cgroup_init_cftypes(NULL, cgroup_dfl_base_files));
        BUG_ON(cgroup_init_cftypes(NULL, cgroup_legacy_base_files));
 
index f548f69c4299dd1ee44bfdc1f84d79d655d0d6d7..b11756f9b6dcfdf2673b2a396ac0e0de5c980101 100644 (file)
@@ -1243,11 +1243,7 @@ static inline void perf_event__state_init(struct perf_event *event)
                                              PERF_EVENT_STATE_INACTIVE;
 }
 
-/*
- * Called at perf_event creation and when events are attached/detached from a
- * group.
- */
-static void perf_event__read_size(struct perf_event *event)
+static void __perf_event_read_size(struct perf_event *event, int nr_siblings)
 {
        int entry = sizeof(u64); /* value */
        int size = 0;
@@ -1263,7 +1259,7 @@ static void perf_event__read_size(struct perf_event *event)
                entry += sizeof(u64);
 
        if (event->attr.read_format & PERF_FORMAT_GROUP) {
-               nr += event->group_leader->nr_siblings;
+               nr += nr_siblings;
                size += sizeof(u64);
        }
 
@@ -1271,14 +1267,11 @@ static void perf_event__read_size(struct perf_event *event)
        event->read_size = size;
 }
 
-static void perf_event__header_size(struct perf_event *event)
+static void __perf_event_header_size(struct perf_event *event, u64 sample_type)
 {
        struct perf_sample_data *data;
-       u64 sample_type = event->attr.sample_type;
        u16 size = 0;
 
-       perf_event__read_size(event);
-
        if (sample_type & PERF_SAMPLE_IP)
                size += sizeof(data->ip);
 
@@ -1303,6 +1296,17 @@ static void perf_event__header_size(struct perf_event *event)
        event->header_size = size;
 }
 
+/*
+ * Called at perf_event creation and when events are attached/detached from a
+ * group.
+ */
+static void perf_event__header_size(struct perf_event *event)
+{
+       __perf_event_read_size(event,
+                              event->group_leader->nr_siblings);
+       __perf_event_header_size(event, event->attr.sample_type);
+}
+
 static void perf_event__id_header_size(struct perf_event *event)
 {
        struct perf_sample_data *data;
@@ -1330,6 +1334,27 @@ static void perf_event__id_header_size(struct perf_event *event)
        event->id_header_size = size;
 }
 
+static bool perf_event_validate_size(struct perf_event *event)
+{
+       /*
+        * The values computed here will be over-written when we actually
+        * attach the event.
+        */
+       __perf_event_read_size(event, event->group_leader->nr_siblings + 1);
+       __perf_event_header_size(event, event->attr.sample_type & ~PERF_SAMPLE_READ);
+       perf_event__id_header_size(event);
+
+       /*
+        * Sum the lot; should not exceed the 64k limit we have on records.
+        * Conservative limit to allow for callchains and other variable fields.
+        */
+       if (event->read_size + event->header_size +
+           event->id_header_size + sizeof(struct perf_event_header) >= 16*1024)
+               return false;
+
+       return true;
+}
+
 static void perf_group_attach(struct perf_event *event)
 {
        struct perf_event *group_leader = event->group_leader, *pos;
@@ -8297,13 +8322,35 @@ SYSCALL_DEFINE5(perf_event_open,
 
        if (move_group) {
                gctx = group_leader->ctx;
+               mutex_lock_double(&gctx->mutex, &ctx->mutex);
+       } else {
+               mutex_lock(&ctx->mutex);
+       }
 
+       if (!perf_event_validate_size(event)) {
+               err = -E2BIG;
+               goto err_locked;
+       }
+
+       /*
+        * Must be under the same ctx::mutex as perf_install_in_context(),
+        * because we need to serialize with concurrent event creation.
+        */
+       if (!exclusive_event_installable(event, ctx)) {
+               /* exclusive and group stuff are assumed mutually exclusive */
+               WARN_ON_ONCE(move_group);
+
+               err = -EBUSY;
+               goto err_locked;
+       }
+
+       WARN_ON_ONCE(ctx->parent_ctx);
+
+       if (move_group) {
                /*
                 * See perf_event_ctx_lock() for comments on the details
                 * of swizzling perf_event::ctx.
                 */
-               mutex_lock_double(&gctx->mutex, &ctx->mutex);
-
                perf_remove_from_context(group_leader, false);
 
                list_for_each_entry(sibling, &group_leader->sibling_list,
@@ -8311,13 +8358,7 @@ SYSCALL_DEFINE5(perf_event_open,
                        perf_remove_from_context(sibling, false);
                        put_ctx(gctx);
                }
-       } else {
-               mutex_lock(&ctx->mutex);
-       }
 
-       WARN_ON_ONCE(ctx->parent_ctx);
-
-       if (move_group) {
                /*
                 * Wait for everybody to stop referencing the events through
                 * the old lists, before installing it on new lists.
@@ -8349,22 +8390,29 @@ SYSCALL_DEFINE5(perf_event_open,
                perf_event__state_init(group_leader);
                perf_install_in_context(ctx, group_leader, group_leader->cpu);
                get_ctx(ctx);
-       }
 
-       if (!exclusive_event_installable(event, ctx)) {
-               err = -EBUSY;
-               mutex_unlock(&ctx->mutex);
-               fput(event_file);
-               goto err_context;
+               /*
+                * Now that all events are installed in @ctx, nothing
+                * references @gctx anymore, so drop the last reference we have
+                * on it.
+                */
+               put_ctx(gctx);
        }
 
+       /*
+        * Precalculate sample_data sizes; do while holding ctx::mutex such
+        * that we're serialized against further additions and before
+        * perf_install_in_context() which is the point the event is active and
+        * can use these values.
+        */
+       perf_event__header_size(event);
+       perf_event__id_header_size(event);
+
        perf_install_in_context(ctx, event, event->cpu);
        perf_unpin_context(ctx);
 
-       if (move_group) {
+       if (move_group)
                mutex_unlock(&gctx->mutex);
-               put_ctx(gctx);
-       }
        mutex_unlock(&ctx->mutex);
 
        put_online_cpus();
@@ -8375,12 +8423,6 @@ SYSCALL_DEFINE5(perf_event_open,
        list_add_tail(&event->owner_entry, &current->perf_event_list);
        mutex_unlock(&current->perf_event_mutex);
 
-       /*
-        * Precalculate sample_data sizes
-        */
-       perf_event__header_size(event);
-       perf_event__id_header_size(event);
-
        /*
         * Drop the reference on the group_event after placing the
         * new event on the sibling_list. This ensures destruction
@@ -8391,6 +8433,12 @@ SYSCALL_DEFINE5(perf_event_open,
        fd_install(event_fd, event_file);
        return event_fd;
 
+err_locked:
+       if (move_group)
+               mutex_unlock(&gctx->mutex);
+       mutex_unlock(&ctx->mutex);
+/* err_file: */
+       fput(event_file);
 err_context:
        perf_unpin_context(ctx);
        put_ctx(ctx);
index 7d5f0f118a6348f81f08f10dd7dbb499f89dd243..2845623fb58264eec28a8b99b48d4511856e718d 100644 (file)
@@ -1149,6 +1149,10 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
        tty_audit_fork(sig);
        sched_autogroup_fork(sig);
 
+#ifdef CONFIG_CGROUPS
+       init_rwsem(&sig->group_rwsem);
+#endif
+
        sig->oom_score_adj = current->signal->oom_score_adj;
        sig->oom_score_adj_min = current->signal->oom_score_adj_min;
 
index 6e40a9539763f48efc695c2b780a29f61b760f9f..e28169dd1c36a51f92523208984ec4c7a4b5b251 100644 (file)
@@ -83,7 +83,7 @@ int irq_set_handler_data(unsigned int irq, void *data)
 
        if (!desc)
                return -EINVAL;
-       desc->irq_data.handler_data = data;
+       desc->irq_common_data.handler_data = data;
        irq_put_desc_unlock(desc, flags);
        return 0;
 }
@@ -105,7 +105,7 @@ int irq_set_msi_desc_off(unsigned int irq_base, unsigned int irq_offset,
 
        if (!desc)
                return -EINVAL;
-       desc->irq_data.msi_desc = entry;
+       desc->irq_common_data.msi_desc = entry;
        if (entry && !irq_offset)
                entry->irq = irq_base;
        irq_put_desc_unlock(desc, flags);
@@ -372,7 +372,6 @@ static bool irq_may_run(struct irq_desc *desc)
 
 /**
  *     handle_simple_irq - Simple and software-decoded IRQs.
- *     @irq:   the interrupt number
  *     @desc:  the interrupt description structure for this irq
  *
  *     Simple interrupts are either sent from a demultiplexing interrupt
@@ -382,8 +381,7 @@ static bool irq_may_run(struct irq_desc *desc)
  *     Note: The caller is expected to handle the ack, clear, mask and
  *     unmask issues if necessary.
  */
-void
-handle_simple_irq(unsigned int irq, struct irq_desc *desc)
+void handle_simple_irq(struct irq_desc *desc)
 {
        raw_spin_lock(&desc->lock);
 
@@ -425,7 +423,6 @@ static void cond_unmask_irq(struct irq_desc *desc)
 
 /**
  *     handle_level_irq - Level type irq handler
- *     @irq:   the interrupt number
  *     @desc:  the interrupt description structure for this irq
  *
  *     Level type interrupts are active as long as the hardware line has
@@ -433,8 +430,7 @@ static void cond_unmask_irq(struct irq_desc *desc)
  *     it after the associated handler has acknowledged the device, so the
  *     interrupt line is back to inactive.
  */
-void
-handle_level_irq(unsigned int irq, struct irq_desc *desc)
+void handle_level_irq(struct irq_desc *desc)
 {
        raw_spin_lock(&desc->lock);
        mask_ack_irq(desc);
@@ -496,7 +492,6 @@ static void cond_unmask_eoi_irq(struct irq_desc *desc, struct irq_chip *chip)
 
 /**
  *     handle_fasteoi_irq - irq handler for transparent controllers
- *     @irq:   the interrupt number
  *     @desc:  the interrupt description structure for this irq
  *
  *     Only a single callback will be issued to the chip: an ->eoi()
@@ -504,8 +499,7 @@ static void cond_unmask_eoi_irq(struct irq_desc *desc, struct irq_chip *chip)
  *     for modern forms of interrupt handlers, which handle the flow
  *     details in hardware, transparently.
  */
-void
-handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
+void handle_fasteoi_irq(struct irq_desc *desc)
 {
        struct irq_chip *chip = desc->irq_data.chip;
 
@@ -546,7 +540,6 @@ EXPORT_SYMBOL_GPL(handle_fasteoi_irq);
 
 /**
  *     handle_edge_irq - edge type IRQ handler
- *     @irq:   the interrupt number
  *     @desc:  the interrupt description structure for this irq
  *
  *     Interrupt occures on the falling and/or rising edge of a hardware
@@ -560,8 +553,7 @@ EXPORT_SYMBOL_GPL(handle_fasteoi_irq);
  *     the handler was running. If all pending interrupts are handled, the
  *     loop is left.
  */
-void
-handle_edge_irq(unsigned int irq, struct irq_desc *desc)
+void handle_edge_irq(struct irq_desc *desc)
 {
        raw_spin_lock(&desc->lock);
 
@@ -618,13 +610,12 @@ EXPORT_SYMBOL(handle_edge_irq);
 #ifdef CONFIG_IRQ_EDGE_EOI_HANDLER
 /**
  *     handle_edge_eoi_irq - edge eoi type IRQ handler
- *     @irq:   the interrupt number
  *     @desc:  the interrupt description structure for this irq
  *
  * Similar as the above handle_edge_irq, but using eoi and w/o the
  * mask/unmask logic.
  */
-void handle_edge_eoi_irq(unsigned int irq, struct irq_desc *desc)
+void handle_edge_eoi_irq(struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_desc_get_chip(desc);
 
@@ -665,13 +656,11 @@ out_eoi:
 
 /**
  *     handle_percpu_irq - Per CPU local irq handler
- *     @irq:   the interrupt number
  *     @desc:  the interrupt description structure for this irq
  *
  *     Per CPU interrupts on SMP machines without locking requirements
  */
-void
-handle_percpu_irq(unsigned int irq, struct irq_desc *desc)
+void handle_percpu_irq(struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_desc_get_chip(desc);
 
@@ -688,7 +677,6 @@ handle_percpu_irq(unsigned int irq, struct irq_desc *desc)
 
 /**
  * handle_percpu_devid_irq - Per CPU local irq handler with per cpu dev ids
- * @irq:       the interrupt number
  * @desc:      the interrupt description structure for this irq
  *
  * Per CPU interrupts on SMP machines without locking requirements. Same as
@@ -698,11 +686,12 @@ handle_percpu_irq(unsigned int irq, struct irq_desc *desc)
  * contain the real device id for the cpu on which this handler is
  * called
  */
-void handle_percpu_devid_irq(unsigned int irq, struct irq_desc *desc)
+void handle_percpu_devid_irq(struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_desc_get_chip(desc);
        struct irqaction *action = desc->action;
        void *dev_id = raw_cpu_ptr(action->percpu_dev_id);
+       unsigned int irq = irq_desc_get_irq(desc);
        irqreturn_t res;
 
        kstat_incr_irqs_this_cpu(desc);
@@ -796,7 +785,7 @@ irq_set_chained_handler_and_data(unsigned int irq, irq_flow_handler_t handle,
                return;
 
        __irq_do_set_handler(desc, handle, 1, NULL);
-       desc->irq_data.handler_data = data;
+       desc->irq_common_data.handler_data = data;
 
        irq_put_desc_busunlock(desc, flags);
 }
index b6eeea8a80c5bbb7143b41ebcaa6f1132eedc7b4..e25a83b67ccea18568f932636b72bd0e9ba182d0 100644 (file)
 
 /**
  * handle_bad_irq - handle spurious and unhandled irqs
- * @irq:       the interrupt number
  * @desc:      description of the interrupt
  *
  * Handles spurious and unhandled IRQ's. It also prints a debugmessage.
  */
-void handle_bad_irq(unsigned int irq, struct irq_desc *desc)
+void handle_bad_irq(struct irq_desc *desc)
 {
+       unsigned int irq = irq_desc_get_irq(desc);
+
        print_irq_desc(irq, desc);
        kstat_incr_irqs_this_cpu(desc);
        ack_bad_irq(irq);
 }
+EXPORT_SYMBOL_GPL(handle_bad_irq);
 
 /*
  * Special, empty irq handler:
index eee4b385cffb46f260db19bfd9f9f5fbf7044224..5ef0c2dbe9302a846e724d5106c01a8eec248fda 100644 (file)
@@ -194,7 +194,7 @@ static inline void kstat_incr_irqs_this_cpu(struct irq_desc *desc)
 
 static inline int irq_desc_get_node(struct irq_desc *desc)
 {
-       return irq_data_get_node(&desc->irq_data);
+       return irq_common_data_get_node(&desc->irq_common_data);
 }
 
 #ifdef CONFIG_PM_SLEEP
index 0a2a4b697bcbffcc219b024a04113e1358d109d9..239e2ae2c947df31d26def1d26da430d144165e8 100644 (file)
@@ -38,12 +38,13 @@ static void __init init_irq_default_affinity(void)
 #ifdef CONFIG_SMP
 static int alloc_masks(struct irq_desc *desc, gfp_t gfp, int node)
 {
-       if (!zalloc_cpumask_var_node(&desc->irq_data.affinity, gfp, node))
+       if (!zalloc_cpumask_var_node(&desc->irq_common_data.affinity,
+                                    gfp, node))
                return -ENOMEM;
 
 #ifdef CONFIG_GENERIC_PENDING_IRQ
        if (!zalloc_cpumask_var_node(&desc->pending_mask, gfp, node)) {
-               free_cpumask_var(desc->irq_data.affinity);
+               free_cpumask_var(desc->irq_common_data.affinity);
                return -ENOMEM;
        }
 #endif
@@ -52,11 +53,13 @@ static int alloc_masks(struct irq_desc *desc, gfp_t gfp, int node)
 
 static void desc_smp_init(struct irq_desc *desc, int node)
 {
-       desc->irq_data.node = node;
-       cpumask_copy(desc->irq_data.affinity, irq_default_affinity);
+       cpumask_copy(desc->irq_common_data.affinity, irq_default_affinity);
 #ifdef CONFIG_GENERIC_PENDING_IRQ
        cpumask_clear(desc->pending_mask);
 #endif
+#ifdef CONFIG_NUMA
+       desc->irq_common_data.node = node;
+#endif
 }
 
 #else
@@ -70,12 +73,13 @@ static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node,
 {
        int cpu;
 
+       desc->irq_common_data.handler_data = NULL;
+       desc->irq_common_data.msi_desc = NULL;
+
        desc->irq_data.common = &desc->irq_common_data;
        desc->irq_data.irq = irq;
        desc->irq_data.chip = &no_irq_chip;
        desc->irq_data.chip_data = NULL;
-       desc->irq_data.handler_data = NULL;
-       desc->irq_data.msi_desc = NULL;
        irq_settings_clr_and_set(desc, ~0, _IRQ_DEFAULT_INIT_FLAGS);
        irqd_set(&desc->irq_data, IRQD_IRQ_DISABLED);
        desc->handle_irq = handle_bad_irq;
@@ -121,7 +125,7 @@ static void free_masks(struct irq_desc *desc)
 #ifdef CONFIG_GENERIC_PENDING_IRQ
        free_cpumask_var(desc->pending_mask);
 #endif
-       free_cpumask_var(desc->irq_data.affinity);
+       free_cpumask_var(desc->irq_common_data.affinity);
 }
 #else
 static inline void free_masks(struct irq_desc *desc) { }
@@ -343,7 +347,7 @@ int generic_handle_irq(unsigned int irq)
 
        if (!desc)
                return -EINVAL;
-       generic_handle_irq_desc(irq, desc);
+       generic_handle_irq_desc(desc);
        return 0;
 }
 EXPORT_SYMBOL_GPL(generic_handle_irq);
index 79baaf8a7813a601659d1316becba1fe0fd9807c..dc9d27c0c1589e58bb14a15e3442ed2ff0d091a4 100644 (file)
@@ -844,7 +844,6 @@ static struct irq_data *irq_domain_insert_irq_data(struct irq_domain *domain,
                child->parent_data = irq_data;
                irq_data->irq = child->irq;
                irq_data->common = child->common;
-               irq_data->node = child->node;
                irq_data->domain = domain;
        }
 
index ad1b064f94fee7cf19e1d6c5592832184fcda3ff..f9a59f6cabd2d3a96f8cd9bee179b6ab4214b83e 100644 (file)
@@ -192,7 +192,7 @@ int irq_do_set_affinity(struct irq_data *data, const struct cpumask *mask,
        switch (ret) {
        case IRQ_SET_MASK_OK:
        case IRQ_SET_MASK_OK_DONE:
-               cpumask_copy(data->affinity, mask);
+               cpumask_copy(desc->irq_common_data.affinity, mask);
        case IRQ_SET_MASK_OK_NOCOPY:
                irq_set_thread_affinity(desc);
                ret = 0;
@@ -304,7 +304,7 @@ static void irq_affinity_notify(struct work_struct *work)
        if (irq_move_pending(&desc->irq_data))
                irq_get_pending(cpumask, desc);
        else
-               cpumask_copy(cpumask, desc->irq_data.affinity);
+               cpumask_copy(cpumask, desc->irq_common_data.affinity);
        raw_spin_unlock_irqrestore(&desc->lock, flags);
 
        notify->notify(notify, cpumask);
@@ -375,9 +375,9 @@ static int setup_affinity(struct irq_desc *desc, struct cpumask *mask)
         * one of the targets is online.
         */
        if (irqd_has_set(&desc->irq_data, IRQD_AFFINITY_SET)) {
-               if (cpumask_intersects(desc->irq_data.affinity,
+               if (cpumask_intersects(desc->irq_common_data.affinity,
                                       cpu_online_mask))
-                       set = desc->irq_data.affinity;
+                       set = desc->irq_common_data.affinity;
                else
                        irqd_clear(&desc->irq_data, IRQD_AFFINITY_SET);
        }
@@ -829,8 +829,8 @@ irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action)
         * This code is triggered unconditionally. Check the affinity
         * mask pointer. For CPU_MASK_OFFSTACK=n this is optimized out.
         */
-       if (desc->irq_data.affinity)
-               cpumask_copy(mask, desc->irq_data.affinity);
+       if (desc->irq_common_data.affinity)
+               cpumask_copy(mask, desc->irq_common_data.affinity);
        else
                valid = false;
        raw_spin_unlock_irq(&desc->lock);
index 7e6512b9dc1ff2682394cdd0fea9a8c6d01cf6e9..be9149f62eb86e63ac06194d4eeaa4065823ea62 100644 (file)
@@ -228,11 +228,7 @@ static void msi_domain_update_chip_ops(struct msi_domain_info *info)
 {
        struct irq_chip *chip = info->chip;
 
-       BUG_ON(!chip);
-       if (!chip->irq_mask)
-               chip->irq_mask = pci_msi_mask_irq;
-       if (!chip->irq_unmask)
-               chip->irq_unmask = pci_msi_unmask_irq;
+       BUG_ON(!chip || !chip->irq_mask || !chip->irq_unmask);
        if (!chip->irq_set_affinity)
                chip->irq_set_affinity = msi_domain_set_affinity;
 }
index 0e97c142ce402b0492c876b909c40ac10d40c779..a50ddc9417ff5fbdccf837f9f43b716200ceb013 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/seq_file.h>
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
+#include <linux/mutex.h>
 
 #include "internals.h"
 
@@ -39,7 +40,7 @@ static struct proc_dir_entry *root_irq_dir;
 static int show_irq_affinity(int type, struct seq_file *m, void *v)
 {
        struct irq_desc *desc = irq_to_desc((long)m->private);
-       const struct cpumask *mask = desc->irq_data.affinity;
+       const struct cpumask *mask = desc->irq_common_data.affinity;
 
 #ifdef CONFIG_GENERIC_PENDING_IRQ
        if (irqd_is_setaffinity_pending(&desc->irq_data))
@@ -323,18 +324,29 @@ void register_handler_proc(unsigned int irq, struct irqaction *action)
 
 void register_irq_proc(unsigned int irq, struct irq_desc *desc)
 {
+       static DEFINE_MUTEX(register_lock);
        char name [MAX_NAMELEN];
 
-       if (!root_irq_dir || (desc->irq_data.chip == &no_irq_chip) || desc->dir)
+       if (!root_irq_dir || (desc->irq_data.chip == &no_irq_chip))
                return;
 
+       /*
+        * irq directories are registered only when a handler is
+        * added, not when the descriptor is created, so multiple
+        * tasks might try to register at the same time.
+        */
+       mutex_lock(&register_lock);
+
+       if (desc->dir)
+               goto out_unlock;
+
        memset(name, 0, MAX_NAMELEN);
        sprintf(name, "%d", irq);
 
        /* create /proc/irq/1234 */
        desc->dir = proc_mkdir(name, root_irq_dir);
        if (!desc->dir)
-               return;
+               goto out_unlock;
 
 #ifdef CONFIG_SMP
        /* create /proc/irq/<irq>/smp_affinity */
@@ -355,6 +367,9 @@ void register_irq_proc(unsigned int irq, struct irq_desc *desc)
 
        proc_create_data("spurious", 0444, desc->dir,
                         &irq_spurious_proc_fops, (void *)(long)irq);
+
+out_unlock:
+       mutex_unlock(&register_lock);
 }
 
 void unregister_irq_proc(unsigned int irq, struct irq_desc *desc)
index dd95f44f99b226d8f44f3a2a3ba5284e2f6ecdf5..b86886beee4f2e21c0f3dacf0aed0370ce79ebcc 100644 (file)
@@ -38,7 +38,7 @@ static void resend_irqs(unsigned long arg)
                clear_bit(irq, irqs_resend);
                desc = irq_to_desc(irq);
                local_irq_disable();
-               desc->handle_irq(irq, desc);
+               desc->handle_irq(desc);
                local_irq_enable();
        }
 }
index da98d0593de24206d68222d787d059a5a2b025a1..0277d1216f80ae1adeed84a686ed34c9b2931fc2 100644 (file)
@@ -327,9 +327,13 @@ static void call_usermodehelper_exec_work(struct work_struct *work)
                call_usermodehelper_exec_sync(sub_info);
        } else {
                pid_t pid;
-
+               /*
+                * Use CLONE_PARENT to reparent it to kthreadd; we do not
+                * want to pollute current->children, and we need a parent
+                * that always ignores SIGCHLD to ensure auto-reaping.
+                */
                pid = kernel_thread(call_usermodehelper_exec_async, sub_info,
-                                   SIGCHLD);
+                                   CLONE_PARENT | SIGCHLD);
                if (pid < 0) {
                        sub_info->retval = pid;
                        umh_complete(sub_info);
index 8acfbf773e0623f187b8c6677ed48d63b6bd7eef..4e49cc4c9952ca82eff8a2b5e5e61765d48ea96f 100644 (file)
@@ -3068,7 +3068,7 @@ static int __lock_is_held(struct lockdep_map *lock);
 static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass,
                          int trylock, int read, int check, int hardirqs_off,
                          struct lockdep_map *nest_lock, unsigned long ip,
-                         int references)
+                         int references, int pin_count)
 {
        struct task_struct *curr = current;
        struct lock_class *class = NULL;
@@ -3157,7 +3157,7 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass,
        hlock->waittime_stamp = 0;
        hlock->holdtime_stamp = lockstat_clock();
 #endif
-       hlock->pin_count = 0;
+       hlock->pin_count = pin_count;
 
        if (check && !mark_irqflags(curr, hlock))
                return 0;
@@ -3343,7 +3343,7 @@ found_it:
                        hlock_class(hlock)->subclass, hlock->trylock,
                                hlock->read, hlock->check, hlock->hardirqs_off,
                                hlock->nest_lock, hlock->acquire_ip,
-                               hlock->references))
+                               hlock->references, hlock->pin_count))
                        return 0;
        }
 
@@ -3433,7 +3433,7 @@ found_it:
                        hlock_class(hlock)->subclass, hlock->trylock,
                                hlock->read, hlock->check, hlock->hardirqs_off,
                                hlock->nest_lock, hlock->acquire_ip,
-                               hlock->references))
+                               hlock->references, hlock->pin_count))
                        return 0;
        }
 
@@ -3583,7 +3583,7 @@ void lock_acquire(struct lockdep_map *lock, unsigned int subclass,
        current->lockdep_recursion = 1;
        trace_lock_acquire(lock, subclass, trylock, read, check, nest_lock, ip);
        __lock_acquire(lock, subclass, trylock, read, check,
-                      irqs_disabled_flags(flags), nest_lock, ip, 0);
+                      irqs_disabled_flags(flags), nest_lock, ip, 0, 0);
        current->lockdep_recursion = 0;
        raw_local_irq_restore(flags);
 }
index 337c8818541d339aac3fd1e3e6af32dac6dff4c9..87e9ce6a63c5d0e78a17977e2e9271ffaf0bb946 100644 (file)
@@ -289,7 +289,7 @@ void queued_spin_lock_slowpath(struct qspinlock *lock, u32 val)
        if (pv_enabled())
                goto queue;
 
-       if (virt_queued_spin_lock(lock))
+       if (virt_spin_lock(lock))
                return;
 
        /*
index 72b0c66628b6b3db589ad0cd6ed6533edb68a9ea..9d6b55587eaa59a25c38776e43aeff51ba682c40 100644 (file)
@@ -24,6 +24,16 @@ __weak void __iomem *ioremap_cache(resource_size_t offset, unsigned long size)
 }
 #endif
 
+static void *try_ram_remap(resource_size_t offset, size_t size)
+{
+       struct page *page = pfn_to_page(offset >> PAGE_SHIFT);
+
+       /* In the simple case just return the existing linear address */
+       if (!PageHighMem(page))
+               return __va(offset);
+       return NULL; /* fallback to ioremap_cache */
+}
+
 /**
  * memremap() - remap an iomem_resource as cacheable memory
  * @offset: iomem resource start address
@@ -66,8 +76,8 @@ void *memremap(resource_size_t offset, size_t size, unsigned long flags)
                 * the requested range is potentially in "System RAM"
                 */
                if (is_ram == REGION_INTERSECTS)
-                       addr = __va(offset);
-               else
+                       addr = try_ram_remap(offset, size);
+               if (!addr)
                        addr = ioremap_cache(offset, size);
        }
 
index b86b7bf1be388d72fe92fb6038b4a67b4710df1f..8f051a106676fb8f2d5457a9104340cce81ce37a 100644 (file)
@@ -1063,11 +1063,15 @@ void symbol_put_addr(void *addr)
        if (core_kernel_text(a))
                return;
 
-       /* module_text_address is safe here: we're supposed to have reference
-        * to module from symbol_get, so it can't go away. */
+       /*
+        * Even though we hold a reference on the module; we still need to
+        * disable preemption in order to safely traverse the data structure.
+        */
+       preempt_disable();
        modaddr = __module_text_address(a);
        BUG_ON(!modaddr);
        module_put(modaddr);
+       preempt_enable();
 }
 EXPORT_SYMBOL_GPL(symbol_put_addr);
 
index 9f75f25cc5d92667c27d70dd1b1a6091b42fbceb..775d36cc00506620829bd2ca14b5da21e4de79e3 100644 (file)
@@ -3868,6 +3868,7 @@ static void rcu_init_new_rnp(struct rcu_node *rnp_leaf)
 static void __init
 rcu_boot_init_percpu_data(int cpu, struct rcu_state *rsp)
 {
+       static struct lock_class_key rcu_exp_sched_rdp_class;
        unsigned long flags;
        struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu);
        struct rcu_node *rnp = rcu_get_root(rsp);
@@ -3883,6 +3884,10 @@ rcu_boot_init_percpu_data(int cpu, struct rcu_state *rsp)
        mutex_init(&rdp->exp_funnel_mutex);
        rcu_boot_init_nocb_percpu_data(rdp);
        raw_spin_unlock_irqrestore(&rnp->lock, flags);
+       if (rsp == &rcu_sched_state)
+               lockdep_set_class_and_name(&rdp->exp_funnel_mutex,
+                                          &rcu_exp_sched_rdp_class,
+                                          "rcu_data_exp_sched");
 }
 
 /*
index 3595403921bd5be10c3e5e591bf04916e654423d..bcd214e4b4d630eb3304f6000a220dc881bafc24 100644 (file)
@@ -621,18 +621,21 @@ int get_nohz_timer_target(void)
        int i, cpu = smp_processor_id();
        struct sched_domain *sd;
 
-       if (!idle_cpu(cpu))
+       if (!idle_cpu(cpu) && is_housekeeping_cpu(cpu))
                return cpu;
 
        rcu_read_lock();
        for_each_domain(cpu, sd) {
                for_each_cpu(i, sched_domain_span(sd)) {
-                       if (!idle_cpu(i)) {
+                       if (!idle_cpu(i) && is_housekeeping_cpu(cpu)) {
                                cpu = i;
                                goto unlock;
                        }
                }
        }
+
+       if (!is_housekeeping_cpu(cpu))
+               cpu = housekeeping_any_cpu();
 unlock:
        rcu_read_unlock();
        return cpu;
@@ -2363,8 +2366,15 @@ void wake_up_new_task(struct task_struct *p)
        trace_sched_wakeup_new(p);
        check_preempt_curr(rq, p, WF_FORK);
 #ifdef CONFIG_SMP
-       if (p->sched_class->task_woken)
+       if (p->sched_class->task_woken) {
+               /*
+                * Nothing relies on rq->lock after this, so its fine to
+                * drop it.
+                */
+               lockdep_unpin_lock(&rq->lock);
                p->sched_class->task_woken(rq, p);
+               lockdep_pin_lock(&rq->lock);
+       }
 #endif
        task_rq_unlock(rq, p, &flags);
 }
@@ -2514,11 +2524,11 @@ static struct rq *finish_task_switch(struct task_struct *prev)
         * If a task dies, then it sets TASK_DEAD in tsk->state and calls
         * schedule one last time. The schedule call will never return, and
         * the scheduled task must drop that reference.
-        * The test for TASK_DEAD must occur while the runqueue locks are
-        * still held, otherwise prev could be scheduled on another cpu, die
-        * there before we look at prev->state, and then the reference would
-        * be dropped twice.
-        *              Manfred Spraul <manfred@colorfullife.com>
+        *
+        * We must observe prev->state before clearing prev->on_cpu (in
+        * finish_lock_switch), otherwise a concurrent wakeup can get prev
+        * running on another CPU and we could rave with its RUNNING -> DEAD
+        * transition, resulting in a double drop.
         */
        prev_state = prev->state;
        vtime_task_switch(prev);
@@ -2666,13 +2676,20 @@ unsigned long nr_running(void)
 
 /*
  * Check if only the current task is running on the cpu.
+ *
+ * Caution: this function does not check that the caller has disabled
+ * preemption, thus the result might have a time-of-check-to-time-of-use
+ * race.  The caller is responsible to use it correctly, for example:
+ *
+ * - from a non-preemptable section (of course)
+ *
+ * - from a thread that is bound to a single CPU
+ *
+ * - in a loop with very short iterations (e.g. a polling loop)
  */
 bool single_task_running(void)
 {
-       if (cpu_rq(smp_processor_id())->nr_running == 1)
-               return true;
-       else
-               return false;
+       return raw_rq()->nr_running == 1;
 }
 EXPORT_SYMBOL(single_task_running);
 
@@ -4924,7 +4941,15 @@ void init_idle(struct task_struct *idle, int cpu)
        idle->state = TASK_RUNNING;
        idle->se.exec_start = sched_clock();
 
-       do_set_cpus_allowed(idle, cpumask_of(cpu));
+#ifdef CONFIG_SMP
+       /*
+        * Its possible that init_idle() gets called multiple times on a task,
+        * in that case do_set_cpus_allowed() will not do the right thing.
+        *
+        * And since this is boot we can forgo the serialization.
+        */
+       set_cpus_allowed_common(idle, cpumask_of(cpu));
+#endif
        /*
         * We're having a chicken and egg problem, even though we are
         * holding rq->lock, the cpu isn't yet set to this cpu so the
@@ -4941,7 +4966,7 @@ void init_idle(struct task_struct *idle, int cpu)
 
        rq->curr = rq->idle = idle;
        idle->on_rq = TASK_ON_RQ_QUEUED;
-#if defined(CONFIG_SMP)
+#ifdef CONFIG_SMP
        idle->on_cpu = 1;
 #endif
        raw_spin_unlock(&rq->lock);
@@ -4956,7 +4981,7 @@ void init_idle(struct task_struct *idle, int cpu)
        idle->sched_class = &idle_sched_class;
        ftrace_graph_init_idle_task(idle, cpu);
        vtime_init_idle(idle, cpu);
-#if defined(CONFIG_SMP)
+#ifdef CONFIG_SMP
        sprintf(idle->comm, "%s/%d", INIT_TASK_COMM, cpu);
 #endif
 }
@@ -5178,24 +5203,47 @@ static void migrate_tasks(struct rq *dead_rq)
                        break;
 
                /*
-                * Ensure rq->lock covers the entire task selection
-                * until the migration.
+                * pick_next_task assumes pinned rq->lock.
                 */
                lockdep_pin_lock(&rq->lock);
                next = pick_next_task(rq, &fake_task);
                BUG_ON(!next);
                next->sched_class->put_prev_task(rq, next);
 
+               /*
+                * Rules for changing task_struct::cpus_allowed are holding
+                * both pi_lock and rq->lock, such that holding either
+                * stabilizes the mask.
+                *
+                * Drop rq->lock is not quite as disastrous as it usually is
+                * because !cpu_active at this point, which means load-balance
+                * will not interfere. Also, stop-machine.
+                */
+               lockdep_unpin_lock(&rq->lock);
+               raw_spin_unlock(&rq->lock);
+               raw_spin_lock(&next->pi_lock);
+               raw_spin_lock(&rq->lock);
+
+               /*
+                * Since we're inside stop-machine, _nothing_ should have
+                * changed the task, WARN if weird stuff happened, because in
+                * that case the above rq->lock drop is a fail too.
+                */
+               if (WARN_ON(task_rq(next) != rq || !task_on_rq_queued(next))) {
+                       raw_spin_unlock(&next->pi_lock);
+                       continue;
+               }
+
                /* Find suitable destination for @next, with force if needed. */
                dest_cpu = select_fallback_rq(dead_rq->cpu, next);
 
-               lockdep_unpin_lock(&rq->lock);
                rq = __migrate_task(rq, next, dest_cpu);
                if (rq != dead_rq) {
                        raw_spin_unlock(&rq->lock);
                        rq = dead_rq;
                        raw_spin_lock(&rq->lock);
                }
+               raw_spin_unlock(&next->pi_lock);
        }
 
        rq->stop = stop;
@@ -7197,9 +7245,6 @@ void __init sched_init_smp(void)
        alloc_cpumask_var(&non_isolated_cpus, GFP_KERNEL);
        alloc_cpumask_var(&fallback_doms, GFP_KERNEL);
 
-       /* nohz_full won't take effect without isolating the cpus. */
-       tick_nohz_full_add_cpus_to(cpu_isolated_map);
-
        sched_init_numa();
 
        /*
index fc8f01083527a570af73a8f8b4c6e586e7e332f9..8b0a15e285f9121ccd5540fa11eef49c94f017c1 100644 (file)
@@ -668,8 +668,15 @@ static enum hrtimer_restart dl_task_timer(struct hrtimer *timer)
         * Queueing this task back might have overloaded rq, check if we need
         * to kick someone away.
         */
-       if (has_pushable_dl_tasks(rq))
+       if (has_pushable_dl_tasks(rq)) {
+               /*
+                * Nothing relies on rq->lock after this, so its safe to drop
+                * rq->lock.
+                */
+               lockdep_unpin_lock(&rq->lock);
                push_dl_task(rq);
+               lockdep_pin_lock(&rq->lock);
+       }
 #endif
 
 unlock:
@@ -1066,8 +1073,9 @@ select_task_rq_dl(struct task_struct *p, int cpu, int sd_flag, int flags)
                int target = find_later_rq(p);
 
                if (target != -1 &&
-                               dl_time_before(p->dl.deadline,
-                                       cpu_rq(target)->dl.earliest_dl.curr))
+                               (dl_time_before(p->dl.deadline,
+                                       cpu_rq(target)->dl.earliest_dl.curr) ||
+                               (cpu_rq(target)->dl.dl_nr_running == 0)))
                        cpu = target;
        }
        rcu_read_unlock();
@@ -1417,7 +1425,8 @@ static struct rq *find_lock_later_rq(struct task_struct *task, struct rq *rq)
 
                later_rq = cpu_rq(cpu);
 
-               if (!dl_time_before(task->dl.deadline,
+               if (later_rq->dl.dl_nr_running &&
+                   !dl_time_before(task->dl.deadline,
                                        later_rq->dl.earliest_dl.curr)) {
                        /*
                         * Target rq has tasks of equal or earlier deadline,
index 6e2e3483b1ecff588e76103e0b7b7d673f16d2a5..9a5e60fe721a5e7e8036508f61950eeb0c8dea31 100644 (file)
@@ -2363,7 +2363,7 @@ static inline long calc_tg_weight(struct task_group *tg, struct cfs_rq *cfs_rq)
         */
        tg_weight = atomic_long_read(&tg->load_avg);
        tg_weight -= cfs_rq->tg_load_avg_contrib;
-       tg_weight += cfs_rq_load_avg(cfs_rq);
+       tg_weight += cfs_rq->load.weight;
 
        return tg_weight;
 }
@@ -2373,7 +2373,7 @@ static long calc_cfs_shares(struct cfs_rq *cfs_rq, struct task_group *tg)
        long tg_weight, load, shares;
 
        tg_weight = calc_tg_weight(tg, cfs_rq);
-       load = cfs_rq_load_avg(cfs_rq);
+       load = cfs_rq->load.weight;
 
        shares = (tg->shares * load);
        if (tg_weight)
@@ -2664,13 +2664,14 @@ static inline u64 cfs_rq_clock_task(struct cfs_rq *cfs_rq);
 /* Group cfs_rq's load_avg is used for task_h_load and update_cfs_share */
 static inline int update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq)
 {
-       int decayed;
        struct sched_avg *sa = &cfs_rq->avg;
+       int decayed, removed = 0;
 
        if (atomic_long_read(&cfs_rq->removed_load_avg)) {
                long r = atomic_long_xchg(&cfs_rq->removed_load_avg, 0);
                sa->load_avg = max_t(long, sa->load_avg - r, 0);
                sa->load_sum = max_t(s64, sa->load_sum - r * LOAD_AVG_MAX, 0);
+               removed = 1;
        }
 
        if (atomic_long_read(&cfs_rq->removed_util_avg)) {
@@ -2688,7 +2689,7 @@ static inline int update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq)
        cfs_rq->load_last_update_time_copy = sa->last_update_time;
 #endif
 
-       return decayed;
+       return decayed || removed;
 }
 
 /* Update task and its cfs_rq load average */
index 8f177c73ae199ba41878fea8de9a5b0a7196620a..4a2ef5a02fd3f91d7c4228378c23d5606bb73812 100644 (file)
@@ -57,9 +57,11 @@ static inline int cpu_idle_poll(void)
        rcu_idle_enter();
        trace_cpu_idle_rcuidle(0, smp_processor_id());
        local_irq_enable();
+       stop_critical_timings();
        while (!tif_need_resched() &&
                (cpu_idle_force_poll || tick_check_broadcast_expired()))
                cpu_relax();
+       start_critical_timings();
        trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id());
        rcu_idle_exit();
        return 1;
index 68cda117574c3aed0e1849a6c07eb28e1f3369c9..6d2a119c7ad9f63338ffb0e9e92efcbc269c2141 100644 (file)
@@ -1078,9 +1078,10 @@ static inline void finish_lock_switch(struct rq *rq, struct task_struct *prev)
         * After ->on_cpu is cleared, the task can be moved to a different CPU.
         * We must ensure this doesn't happen until the switch is completely
         * finished.
+        *
+        * Pairs with the control dependency and rmb in try_to_wake_up().
         */
-       smp_wmb();
-       prev->on_cpu = 0;
+       smp_store_release(&prev->on_cpu, 0);
 #endif
 #ifdef CONFIG_DEBUG_SPINLOCK
        /* this is a valid case when another task releases the spinlock */
index 272d9322bc5dfb6b82e650950e16ab89b572f442..052e02672d12428ce1e9e1f7266c7cd754ace5af 100644 (file)
@@ -106,10 +106,9 @@ void __wake_up_locked(wait_queue_head_t *q, unsigned int mode, int nr)
 }
 EXPORT_SYMBOL_GPL(__wake_up_locked);
 
-void __wake_up_locked_key(wait_queue_head_t *q, unsigned int mode, int nr,
-                         void *key)
+void __wake_up_locked_key(wait_queue_head_t *q, unsigned int mode, void *key)
 {
-       __wake_up_common(q, mode, nr, 0, key);
+       __wake_up_common(q, mode, 1, 0, key);
 }
 EXPORT_SYMBOL_GPL(__wake_up_locked_key);
 
@@ -284,7 +283,7 @@ void abort_exclusive_wait(wait_queue_head_t *q, wait_queue_t *wait,
        if (!list_empty(&wait->task_list))
                list_del_init(&wait->task_list);
        else if (waitqueue_active(q))
-               __wake_up_locked_key(q, mode, 1, key);
+               __wake_up_locked_key(q, mode, key);
        spin_unlock_irqrestore(&q->lock, flags);
 }
 EXPORT_SYMBOL(abort_exclusive_wait);
index 50eb107f119877ab0762bb671a69cf9c0cd418bc..a9b76a40319e86b5d545621d274c262bc69c7c70 100644 (file)
@@ -97,20 +97,6 @@ EXPORT_SYMBOL_GPL(clockevent_delta2ns);
 static int __clockevents_switch_state(struct clock_event_device *dev,
                                      enum clock_event_state state)
 {
-       /* Transition with legacy set_mode() callback */
-       if (dev->set_mode) {
-               /* Legacy callback doesn't support new modes */
-               if (state > CLOCK_EVT_STATE_ONESHOT)
-                       return -ENOSYS;
-               /*
-                * 'clock_event_state' and 'clock_event_mode' have 1-to-1
-                * mapping until *_ONESHOT, and so a simple cast will work.
-                */
-               dev->set_mode((enum clock_event_mode)state, dev);
-               dev->mode = (enum clock_event_mode)state;
-               return 0;
-       }
-
        if (dev->features & CLOCK_EVT_FEAT_DUMMY)
                return 0;
 
@@ -204,12 +190,8 @@ int clockevents_tick_resume(struct clock_event_device *dev)
 {
        int ret = 0;
 
-       if (dev->set_mode) {
-               dev->set_mode(CLOCK_EVT_MODE_RESUME, dev);
-               dev->mode = CLOCK_EVT_MODE_RESUME;
-       } else if (dev->tick_resume) {
+       if (dev->tick_resume)
                ret = dev->tick_resume(dev);
-       }
 
        return ret;
 }
@@ -460,26 +442,6 @@ int clockevents_unbind_device(struct clock_event_device *ced, int cpu)
 }
 EXPORT_SYMBOL_GPL(clockevents_unbind_device);
 
-/* Sanity check of state transition callbacks */
-static int clockevents_sanity_check(struct clock_event_device *dev)
-{
-       /* Legacy set_mode() callback */
-       if (dev->set_mode) {
-               /* We shouldn't be supporting new modes now */
-               WARN_ON(dev->set_state_periodic || dev->set_state_oneshot ||
-                       dev->set_state_shutdown || dev->tick_resume ||
-                       dev->set_state_oneshot_stopped);
-
-               BUG_ON(dev->mode != CLOCK_EVT_MODE_UNUSED);
-               return 0;
-       }
-
-       if (dev->features & CLOCK_EVT_FEAT_DUMMY)
-               return 0;
-
-       return 0;
-}
-
 /**
  * clockevents_register_device - register a clock event device
  * @dev:       device to register
@@ -488,8 +450,6 @@ void clockevents_register_device(struct clock_event_device *dev)
 {
        unsigned long flags;
 
-       BUG_ON(clockevents_sanity_check(dev));
-
        /* Initialize state to DETACHED */
        clockevent_set_state(dev, CLOCK_EVT_STATE_DETACHED);
 
index 841b72f720e88041a99ded8852381555c307fb43..3a38775b50c2243ea83341a9034a0eb4e3a502a3 100644 (file)
@@ -217,7 +217,7 @@ static void clocksource_watchdog(unsigned long data)
                        continue;
 
                /* Check the deviation from the watchdog clocksource. */
-               if ((abs(cs_nsec - wd_nsec) > WATCHDOG_THRESHOLD)) {
+               if (abs64(cs_nsec - wd_nsec) > WATCHDOG_THRESHOLD) {
                        pr_warn("timekeeping watchdog: Marking clocksource '%s' as unstable because the skew is too large:\n",
                                cs->name);
                        pr_warn("                      '%s' wd_now: %llx wd_last: %llx mask: %llx\n",
index d11c55b6ab7db3585d449ac2a9a5c55ad4a0dd12..4fcd99e12aa01ce3ce0fa24fb219d644a68417a3 100644 (file)
@@ -398,7 +398,6 @@ void tick_shutdown(unsigned int cpu)
                 * the set mode function!
                 */
                clockevent_set_state(dev, CLOCK_EVT_STATE_DETACHED);
-               dev->mode = CLOCK_EVT_MODE_UNUSED;
                clockevents_exchange_device(dev, NULL);
                dev->event_handler = clockevents_handle_noop;
                td->evtdev = NULL;
index 3319e16f31e58ed69534ab2fa7e5cd05d7b90d8f..7c7ec45159834a1b25576fbed037c9951f3c076f 100644 (file)
@@ -290,16 +290,17 @@ static int __init tick_nohz_full_setup(char *str)
 __setup("nohz_full=", tick_nohz_full_setup);
 
 static int tick_nohz_cpu_down_callback(struct notifier_block *nfb,
-                                                unsigned long action,
-                                                void *hcpu)
+                                      unsigned long action,
+                                      void *hcpu)
 {
        unsigned int cpu = (unsigned long)hcpu;
 
        switch (action & ~CPU_TASKS_FROZEN) {
        case CPU_DOWN_PREPARE:
                /*
-                * If we handle the timekeeping duty for full dynticks CPUs,
-                * we can't safely shutdown that CPU.
+                * The boot CPU handles housekeeping duty (unbound timers,
+                * workqueues, timekeeping, ...) on behalf of full dynticks
+                * CPUs. It must remain online when nohz full is enabled.
                 */
                if (tick_nohz_full_running && tick_do_timer_cpu == cpu)
                        return NOTIFY_BAD;
@@ -370,6 +371,12 @@ void __init tick_nohz_init(void)
        cpu_notifier(tick_nohz_cpu_down_callback, 0);
        pr_info("NO_HZ: Full dynticks CPUs: %*pbl.\n",
                cpumask_pr_args(tick_nohz_full_mask));
+
+       /*
+        * We need at least one CPU to handle housekeeping work such
+        * as timekeeping, unbound timers, workqueues, ...
+        */
+       WARN_ON_ONCE(cpumask_empty(housekeeping_mask));
 }
 #endif
 
index f6ee2e6b6f5dcd53a451caf2a9dc83278df481c6..44d2cc0436f4968a32fb61772e19ca701fccbfb0 100644 (file)
@@ -1251,7 +1251,7 @@ void __init timekeeping_init(void)
        set_normalized_timespec64(&tmp, -boot.tv_sec, -boot.tv_nsec);
        tk_set_wall_to_mono(tk, tmp);
 
-       timekeeping_update(tk, TK_MIRROR);
+       timekeeping_update(tk, TK_MIRROR | TK_CLOCK_WAS_SET);
 
        write_seqcount_end(&tk_core.seq);
        raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
@@ -1614,7 +1614,7 @@ static __always_inline void timekeeping_freqadjust(struct timekeeper *tk,
        negative = (tick_error < 0);
 
        /* Sort out the magnitude of the correction */
-       tick_error = abs(tick_error);
+       tick_error = abs64(tick_error);
        for (adj = 0; tick_error > interval; adj++)
                tick_error >>= 1;
 
index 129c96033e466cea9e804cb2136348f6eb335e7c..f75e35b6014900da71ffa438a507c34f19e36e3a 100644 (file)
@@ -225,7 +225,7 @@ print_tickdevice(struct seq_file *m, struct tick_device *td, int cpu)
                   (unsigned long long) dev->min_delta_ns);
        SEQ_printf(m, " mult:           %u\n", dev->mult);
        SEQ_printf(m, " shift:          %u\n", dev->shift);
-       SEQ_printf(m, " mode:           %d\n", dev->mode);
+       SEQ_printf(m, " mode:           %d\n", clockevent_get_state(dev));
        SEQ_printf(m, " next_event:     %Ld nsecs\n",
                   (unsigned long long) ktime_to_ns(dev->next_event));
 
@@ -233,40 +233,34 @@ print_tickdevice(struct seq_file *m, struct tick_device *td, int cpu)
        print_name_offset(m, dev->set_next_event);
        SEQ_printf(m, "\n");
 
-       if (dev->set_mode) {
-               SEQ_printf(m, " set_mode:       ");
-               print_name_offset(m, dev->set_mode);
+       if (dev->set_state_shutdown) {
+               SEQ_printf(m, " shutdown: ");
+               print_name_offset(m, dev->set_state_shutdown);
                SEQ_printf(m, "\n");
-       } else {
-               if (dev->set_state_shutdown) {
-                       SEQ_printf(m, " shutdown: ");
-                       print_name_offset(m, dev->set_state_shutdown);
-                       SEQ_printf(m, "\n");
-               }
+       }
 
-               if (dev->set_state_periodic) {
-                       SEQ_printf(m, " periodic: ");
-                       print_name_offset(m, dev->set_state_periodic);
-                       SEQ_printf(m, "\n");
-               }
+       if (dev->set_state_periodic) {
+               SEQ_printf(m, " periodic: ");
+               print_name_offset(m, dev->set_state_periodic);
+               SEQ_printf(m, "\n");
+       }
 
-               if (dev->set_state_oneshot) {
-                       SEQ_printf(m, " oneshot:  ");
-                       print_name_offset(m, dev->set_state_oneshot);
-                       SEQ_printf(m, "\n");
-               }
+       if (dev->set_state_oneshot) {
+               SEQ_printf(m, " oneshot:  ");
+               print_name_offset(m, dev->set_state_oneshot);
+               SEQ_printf(m, "\n");
+       }
 
-               if (dev->set_state_oneshot_stopped) {
-                       SEQ_printf(m, " oneshot stopped: ");
-                       print_name_offset(m, dev->set_state_oneshot_stopped);
-                       SEQ_printf(m, "\n");
-               }
+       if (dev->set_state_oneshot_stopped) {
+               SEQ_printf(m, " oneshot stopped: ");
+               print_name_offset(m, dev->set_state_oneshot_stopped);
+               SEQ_printf(m, "\n");
+       }
 
-               if (dev->tick_resume) {
-                       SEQ_printf(m, " resume:   ");
-                       print_name_offset(m, dev->tick_resume);
-                       SEQ_printf(m, "\n");
-               }
+       if (dev->tick_resume) {
+               SEQ_printf(m, " resume:   ");
+               print_name_offset(m, dev->tick_resume);
+               SEQ_printf(m, "\n");
        }
 
        SEQ_printf(m, " event_handler:  ");
index b746399ab59c01e422da63468aa370b1b642a860..8abf1ba18085742af78176dbc514095a47643c9c 100644 (file)
@@ -85,9 +85,19 @@ check_stack(unsigned long ip, unsigned long *stack)
        if (!object_is_on_stack(stack))
                return;
 
+       /* Can't do this from NMI context (can cause deadlocks) */
+       if (in_nmi())
+               return;
+
        local_irq_save(flags);
        arch_spin_lock(&max_stack_lock);
 
+       /*
+        * RCU may not be watching, make it see us.
+        * The stack trace code uses rcu_sched.
+        */
+       rcu_irq_enter();
+
        /* In case another CPU set the tracer_frame on us */
        if (unlikely(!frame_size))
                this_size -= tracer_frame;
@@ -169,6 +179,7 @@ check_stack(unsigned long ip, unsigned long *stack)
        }
 
  out:
+       rcu_irq_exit();
        arch_spin_unlock(&max_stack_lock);
        local_irq_restore(flags);
 }
index ca71582fcfab29ec708746eab636c325b9caef15..bcb14cafe007148b15edb5cfed5adc041a6d966c 100644 (file)
@@ -1458,13 +1458,13 @@ static void __queue_delayed_work(int cpu, struct workqueue_struct *wq,
        timer_stats_timer_set_start_info(&dwork->timer);
 
        dwork->wq = wq;
+       /* timer isn't guaranteed to run in this cpu, record earlier */
+       if (cpu == WORK_CPU_UNBOUND)
+               cpu = raw_smp_processor_id();
        dwork->cpu = cpu;
        timer->expires = jiffies + delay;
 
-       if (unlikely(cpu != WORK_CPU_UNBOUND))
-               add_timer_on(timer, cpu);
-       else
-               add_timer(timer);
+       add_timer_on(timer, cpu);
 }
 
 /**
index 2e491ac15622a559c88ba12a4067eeb5ca704115..f0df318104e7272ef97641421c938069a047a85e 100644 (file)
@@ -220,6 +220,7 @@ config ZLIB_INFLATE
 
 config ZLIB_DEFLATE
        tristate
+       select BITREVERSE
 
 config LZO_COMPRESS
        tristate
index ab76b99adc857fb38c2e4677b6ab34d6a01fa786..1d1521c26302a2510e873d49a8b6bb525f399d66 100644 (file)
@@ -197,6 +197,7 @@ config ENABLE_MUST_CHECK
 config FRAME_WARN
        int "Warn for stack frames larger than (needs gcc 4.4)"
        range 0 8192
+       default 0 if KASAN
        default 1024 if !64BIT
        default 2048 if 64BIT
        help
index f1cdeb024d172a488e1ed44f70ce1e090ee5e541..6a823a53e357bc83e84476d93cc2c155f0adfee5 100644 (file)
@@ -44,7 +44,7 @@ static void fail_dump(struct fault_attr *attr)
                printk(KERN_NOTICE "FAULT_INJECTION: forcing a failure.\n"
                       "name %pd, interval %lu, probability %lu, "
                       "space %d, times %d\n", attr->dname,
-                      attr->probability, attr->interval,
+                      attr->interval, attr->probability,
                       atomic_read(&attr->space),
                       atomic_read(&attr->times));
                if (attr->verbose > 1)
index ff19f66d3f7fbd635a44cc03614b5fbe4485cc56..b1c93e94ca7a430ea68c717e0e26d56057d75636 100644 (file)
@@ -21,8 +21,7 @@ static        DEFINE_PER_CPU(unsigned int, iommu_hash_common);
 
 static inline bool need_flush(struct iommu_map_table *iommu)
 {
-       return (iommu->lazy_flush != NULL &&
-               (iommu->flags & IOMMU_NEED_FLUSH) != 0);
+       return ((iommu->flags & IOMMU_NEED_FLUSH) != 0);
 }
 
 static inline void set_flush(struct iommu_map_table *iommu)
@@ -211,7 +210,8 @@ unsigned long iommu_tbl_range_alloc(struct device *dev,
                        goto bail;
                }
        }
-       if (n < pool->hint || need_flush(iommu)) {
+       if (iommu->lazy_flush &&
+           (n < pool->hint || need_flush(iommu))) {
                clear_flush(iommu);
                iommu->lazy_flush(iommu);
        }
index cc0c69710dcf8a2c7474b759be72e8fa22c2ca1f..a54ff8949f9116184631414086a9fa2d956c8031 100644 (file)
@@ -187,10 +187,7 @@ static int rhashtable_rehash_one(struct rhashtable *ht, unsigned int old_hash)
        head = rht_dereference_bucket(new_tbl->buckets[new_hash],
                                      new_tbl, new_hash);
 
-       if (rht_is_a_nulls(head))
-               INIT_RHT_NULLS_HEAD(entry->next, ht, new_hash);
-       else
-               RCU_INIT_POINTER(entry->next, head);
+       RCU_INIT_POINTER(entry->next, head);
 
        rcu_assign_pointer(new_tbl->buckets[new_hash], entry);
        spin_unlock(new_bucket_lock);
index 13d1e84ddb80e983a325011fb8dd8b6ff9ce0600..84775ba873b9efd978fa006be56e58057b34031f 100644 (file)
 #include <linux/bug.h>
 #include <linux/errno.h>
 
+#include <asm/byteorder.h>
+#include <asm/word-at-a-time.h>
+#include <asm/page.h>
+
 #ifndef __HAVE_ARCH_STRNCASECMP
 /**
  * strncasecmp - Case insensitive, length-limited string comparison
@@ -146,6 +150,91 @@ size_t strlcpy(char *dest, const char *src, size_t size)
 EXPORT_SYMBOL(strlcpy);
 #endif
 
+#ifndef __HAVE_ARCH_STRSCPY
+/**
+ * strscpy - Copy a C-string into a sized buffer
+ * @dest: Where to copy the string to
+ * @src: Where to copy the string from
+ * @count: Size of destination buffer
+ *
+ * Copy the string, or as much of it as fits, into the dest buffer.
+ * The routine returns the number of characters copied (not including
+ * the trailing NUL) or -E2BIG if the destination buffer wasn't big enough.
+ * The behavior is undefined if the string buffers overlap.
+ * The destination buffer is always NUL terminated, unless it's zero-sized.
+ *
+ * Preferred to strlcpy() since the API doesn't require reading memory
+ * from the src string beyond the specified "count" bytes, and since
+ * the return value is easier to error-check than strlcpy()'s.
+ * In addition, the implementation is robust to the string changing out
+ * from underneath it, unlike the current strlcpy() implementation.
+ *
+ * Preferred to strncpy() since it always returns a valid string, and
+ * doesn't unnecessarily force the tail of the destination buffer to be
+ * zeroed.  If the zeroing is desired, it's likely cleaner to use strscpy()
+ * with an overflow test, then just memset() the tail of the dest buffer.
+ */
+ssize_t strscpy(char *dest, const char *src, size_t count)
+{
+       const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS;
+       size_t max = count;
+       long res = 0;
+
+       if (count == 0)
+               return -E2BIG;
+
+#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+       /*
+        * If src is unaligned, don't cross a page boundary,
+        * since we don't know if the next page is mapped.
+        */
+       if ((long)src & (sizeof(long) - 1)) {
+               size_t limit = PAGE_SIZE - ((long)src & (PAGE_SIZE - 1));
+               if (limit < max)
+                       max = limit;
+       }
+#else
+       /* If src or dest is unaligned, don't do word-at-a-time. */
+       if (((long) dest | (long) src) & (sizeof(long) - 1))
+               max = 0;
+#endif
+
+       while (max >= sizeof(unsigned long)) {
+               unsigned long c, data;
+
+               c = *(unsigned long *)(src+res);
+               if (has_zero(c, &data, &constants)) {
+                       data = prep_zero_mask(c, data, &constants);
+                       data = create_zero_mask(data);
+                       *(unsigned long *)(dest+res) = c & zero_bytemask(data);
+                       return res + find_zero(data);
+               }
+               *(unsigned long *)(dest+res) = c;
+               res += sizeof(unsigned long);
+               count -= sizeof(unsigned long);
+               max -= sizeof(unsigned long);
+       }
+
+       while (count) {
+               char c;
+
+               c = src[res];
+               dest[res] = c;
+               if (!c)
+                       return res;
+               res++;
+               count--;
+       }
+
+       /* Hit buffer length without finding a NUL; force NUL-termination. */
+       if (res)
+               dest[res-1] = '\0';
+
+       return -E2BIG;
+}
+EXPORT_SYMBOL(strscpy);
+#endif
+
 #ifndef __HAVE_ARCH_STRCAT
 /**
  * strcat - Append one %NUL-terminated string to another
index 54036ce2e2dd0a4ab042c9c19b2d54fa41a34115..5939f63d90cde79fe1e09814765539a7e43a3c28 100644 (file)
@@ -59,7 +59,11 @@ void string_get_size(u64 size, u64 blk_size, const enum string_size_units units,
        }
 
        exp = divisor[units] / (u32)blk_size;
-       if (size >= exp) {
+       /*
+        * size must be strictly greater than exp here to ensure that remainder
+        * is greater than divisor[units] coming out of the if below.
+        */
+       if (size > exp) {
                remainder = do_div(size, divisor[units]);
                remainder *= blk_size;
                i++;
index 2df8ddcb0ca0a7f7a055456de4b46a8c55bbfdf1..619984fc07ec32792349c7fe8aec7c8b56e3d2a3 100644 (file)
@@ -480,6 +480,10 @@ static void cgwb_release_workfn(struct work_struct *work)
                                                release_work);
        struct backing_dev_info *bdi = wb->bdi;
 
+       spin_lock_irq(&cgwb_lock);
+       list_del_rcu(&wb->bdi_node);
+       spin_unlock_irq(&cgwb_lock);
+
        wb_shutdown(wb);
 
        css_put(wb->memcg_css);
@@ -575,6 +579,7 @@ static int cgwb_create(struct backing_dev_info *bdi,
                ret = radix_tree_insert(&bdi->cgwb_tree, memcg_css->id, wb);
                if (!ret) {
                        atomic_inc(&bdi->usage_cnt);
+                       list_add_tail_rcu(&wb->bdi_node, &bdi->wb_list);
                        list_add(&wb->memcg_node, memcg_cgwb_list);
                        list_add(&wb->blkcg_node, blkcg_cgwb_list);
                        css_get(memcg_css);
@@ -676,7 +681,7 @@ static int cgwb_bdi_init(struct backing_dev_info *bdi)
 static void cgwb_bdi_destroy(struct backing_dev_info *bdi)
 {
        struct radix_tree_iter iter;
-       struct bdi_writeback_congested *congested, *congested_n;
+       struct rb_node *rbn;
        void **slot;
 
        WARN_ON(test_bit(WB_registered, &bdi->wb.state));
@@ -686,9 +691,11 @@ static void cgwb_bdi_destroy(struct backing_dev_info *bdi)
        radix_tree_for_each_slot(slot, &bdi->cgwb_tree, &iter, 0)
                cgwb_kill(*slot);
 
-       rbtree_postorder_for_each_entry_safe(congested, congested_n,
-                                       &bdi->cgwb_congested_tree, rb_node) {
-               rb_erase(&congested->rb_node, &bdi->cgwb_congested_tree);
+       while ((rbn = rb_first(&bdi->cgwb_congested_tree))) {
+               struct bdi_writeback_congested *congested =
+                       rb_entry(rbn, struct bdi_writeback_congested, rb_node);
+
+               rb_erase(rbn, &bdi->cgwb_congested_tree);
                congested->bdi = NULL;  /* mark @congested unlinked */
        }
 
@@ -764,15 +771,22 @@ static void cgwb_bdi_destroy(struct backing_dev_info *bdi) { }
 
 int bdi_init(struct backing_dev_info *bdi)
 {
+       int ret;
+
        bdi->dev = NULL;
 
        bdi->min_ratio = 0;
        bdi->max_ratio = 100;
        bdi->max_prop_frac = FPROP_FRAC_BASE;
        INIT_LIST_HEAD(&bdi->bdi_list);
+       INIT_LIST_HEAD(&bdi->wb_list);
        init_waitqueue_head(&bdi->wb_waitq);
 
-       return cgwb_bdi_init(bdi);
+       ret = cgwb_bdi_init(bdi);
+
+       list_add_tail_rcu(&bdi->wb.bdi_node, &bdi->wb_list);
+
+       return ret;
 }
 EXPORT_SYMBOL(bdi_init);
 
@@ -823,7 +837,7 @@ static void bdi_remove_from_list(struct backing_dev_info *bdi)
        synchronize_rcu_expedited();
 }
 
-void bdi_destroy(struct backing_dev_info *bdi)
+void bdi_unregister(struct backing_dev_info *bdi)
 {
        /* make sure nobody finds us on the bdi_list anymore */
        bdi_remove_from_list(bdi);
@@ -835,9 +849,19 @@ void bdi_destroy(struct backing_dev_info *bdi)
                device_unregister(bdi->dev);
                bdi->dev = NULL;
        }
+}
 
+void bdi_exit(struct backing_dev_info *bdi)
+{
+       WARN_ON_ONCE(bdi->dev);
        wb_exit(&bdi->wb);
 }
+
+void bdi_destroy(struct backing_dev_info *bdi)
+{
+       bdi_unregister(bdi);
+       bdi_exit(bdi);
+}
 EXPORT_SYMBOL(bdi_destroy);
 
 /*
index e7d1db5330254da4a8d265b8784d1eb645693447..4eb56badf37e60e63a5a1badd093d1934a21ad35 100644 (file)
--- a/mm/cma.c
+++ b/mm/cma.c
@@ -361,7 +361,7 @@ err:
  * This function allocates part of contiguous memory on specific
  * contiguous memory area.
  */
-struct page *cma_alloc(struct cma *cma, unsigned int count, unsigned int align)
+struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align)
 {
        unsigned long mask, offset, pfn, start = 0;
        unsigned long bitmap_maxno, bitmap_no, bitmap_count;
@@ -371,7 +371,7 @@ struct page *cma_alloc(struct cma *cma, unsigned int count, unsigned int align)
        if (!cma || !cma->count)
                return NULL;
 
-       pr_debug("%s(cma %p, count %d, align %d)\n", __func__, (void *)cma,
+       pr_debug("%s(cma %p, count %zu, align %d)\n", __func__, (void *)cma,
                 count, align);
 
        if (!count)
index 71a8998cd03a6b8b0d2dbfe36a24ce70766047e8..312a716fa14c2ef0d2780832bc378c05a3d08d16 100644 (file)
@@ -394,7 +394,7 @@ static struct dma_page *pool_find_page(struct dma_pool *pool, dma_addr_t dma)
        list_for_each_entry(page, &pool->page_list, page_list) {
                if (dma < page->dma)
                        continue;
-               if (dma < (page->dma + pool->allocation))
+               if ((dma - page->dma) < pool->allocation)
                        return page;
        }
        return NULL;
index 72940fb38666811b80c146bc085a1c84fc0e7ecc..327910c2400c6ce36f440383147fdc768cf14692 100644 (file)
@@ -2473,6 +2473,26 @@ ssize_t generic_perform_write(struct file *file,
                                                iov_iter_count(i));
 
 again:
+               /*
+                * Bring in the user page that we will copy from _first_.
+                * Otherwise there's a nasty deadlock on copying from the
+                * same page as we're writing to, without it being marked
+                * up-to-date.
+                *
+                * Not only is this an optimisation, but it is also required
+                * to check that the address is actually valid, when atomic
+                * usercopies are used, below.
+                */
+               if (unlikely(iov_iter_fault_in_readable(i, bytes))) {
+                       status = -EFAULT;
+                       break;
+               }
+
+               if (fatal_signal_pending(current)) {
+                       status = -EINTR;
+                       break;
+               }
+
                status = a_ops->write_begin(file, mapping, pos, bytes, flags,
                                                &page, &fsdata);
                if (unlikely(status < 0))
@@ -2480,17 +2500,8 @@ again:
 
                if (mapping_writably_mapped(mapping))
                        flush_dcache_page(page);
-               /*
-                * 'page' is now locked.  If we are trying to copy from a
-                * mapping of 'page' in userspace, the copy might fault and
-                * would need PageUptodate() to complete.  But, page can not be
-                * made Uptodate without acquiring the page lock, which we hold.
-                * Deadlock.  Avoid with pagefault_disable().  Fix up below with
-                * iov_iter_fault_in_readable().
-                */
-               pagefault_disable();
+
                copied = iov_iter_copy_from_user_atomic(page, i, offset, bytes);
-               pagefault_enable();
                flush_dcache_page(page);
 
                status = a_ops->write_end(file, mapping, pos, bytes, copied,
@@ -2513,24 +2524,12 @@ again:
                         */
                        bytes = min_t(unsigned long, PAGE_CACHE_SIZE - offset,
                                                iov_iter_single_seg_count(i));
-                       /*
-                        * This is the fallback to recover if the copy from
-                        * userspace above faults.
-                        */
-                       if (unlikely(iov_iter_fault_in_readable(i, bytes))) {
-                               status = -EFAULT;
-                               break;
-                       }
                        goto again;
                }
                pos += copied;
                written += copied;
 
                balance_dirty_pages_ratelimited(mapping);
-               if (fatal_signal_pending(current)) {
-                       status = -EINTR;
-                       break;
-               }
        } while (iov_iter_count(i));
 
        return written ? written : status;
index 4b06b8db9df23c8f33406586507bbaecf7f5444c..bbac913f96bc1662ac3d7ef37c82080d9c17562f 100644 (file)
@@ -2206,7 +2206,8 @@ static int __collapse_huge_page_isolate(struct vm_area_struct *vma,
        for (_pte = pte; _pte < pte+HPAGE_PMD_NR;
             _pte++, address += PAGE_SIZE) {
                pte_t pteval = *_pte;
-               if (pte_none(pteval) || is_zero_pfn(pte_pfn(pteval))) {
+               if (pte_none(pteval) || (pte_present(pteval) &&
+                               is_zero_pfn(pte_pfn(pteval)))) {
                        if (!userfaultfd_armed(vma) &&
                            ++none_or_zero <= khugepaged_max_ptes_none)
                                continue;
index 999fb0aef8f16f9a126579e54fca79ad8e4f6487..9cc773483624e4cbb1592ddde74f9c8faa21ef87 100644 (file)
@@ -3201,6 +3201,14 @@ static void unmap_ref_private(struct mm_struct *mm, struct vm_area_struct *vma,
                if (iter_vma == vma)
                        continue;
 
+               /*
+                * Shared VMAs have their own reserves and do not affect
+                * MAP_PRIVATE accounting but it is possible that a shared
+                * VMA is using the same page so check and skip such VMAs.
+                */
+               if (iter_vma->vm_flags & VM_MAYSHARE)
+                       continue;
+
                /*
                 * Unmap the page from other VMAs without their own reserves.
                 * They get marked to be SIGKILLed if they fault in these
index 7b28e9cdf1c7686428fe49802fced44088043555..8da211411b57f1b0db116d8d67401bae30628ec8 100644 (file)
@@ -135,12 +135,11 @@ static __always_inline bool memory_is_poisoned_16(unsigned long addr)
 
        if (unlikely(*shadow_addr)) {
                u16 shadow_first_bytes = *(u16 *)shadow_addr;
-               s8 last_byte = (addr + 15) & KASAN_SHADOW_MASK;
 
                if (unlikely(shadow_first_bytes))
                        return true;
 
-               if (likely(!last_byte))
+               if (likely(IS_ALIGNED(addr, 8)))
                        return false;
 
                return memory_is_poisoned_1(addr + 15);
index 6ddaeba34e097a7553d33b8add26e26a27d3c81a..c57c4423c68837d14816c5ff230435e1567e7c20 100644 (file)
@@ -644,12 +644,14 @@ mem_cgroup_largest_soft_limit_node(struct mem_cgroup_tree_per_zone *mctz)
 }
 
 /*
+ * Return page count for single (non recursive) @memcg.
+ *
  * Implementation Note: reading percpu statistics for memcg.
  *
  * Both of vmstat[] and percpu_counter has threshold and do periodic
  * synchronization to implement "quick" read. There are trade-off between
  * reading cost and precision of value. Then, we may have a chance to implement
- * a periodic synchronizion of counter in memcg's counter.
+ * a periodic synchronization of counter in memcg's counter.
  *
  * But this _read() function is used for user interface now. The user accounts
  * memory usage by memory cgroup and he _always_ requires exact value because
@@ -659,17 +661,24 @@ mem_cgroup_largest_soft_limit_node(struct mem_cgroup_tree_per_zone *mctz)
  *
  * If there are kernel internal actions which can make use of some not-exact
  * value, and reading all cpu value can be performance bottleneck in some
- * common workload, threashold and synchonization as vmstat[] should be
+ * common workload, threshold and synchronization as vmstat[] should be
  * implemented.
  */
-static long mem_cgroup_read_stat(struct mem_cgroup *memcg,
-                                enum mem_cgroup_stat_index idx)
+static unsigned long
+mem_cgroup_read_stat(struct mem_cgroup *memcg, enum mem_cgroup_stat_index idx)
 {
        long val = 0;
        int cpu;
 
+       /* Per-cpu values can be negative, use a signed accumulator */
        for_each_possible_cpu(cpu)
                val += per_cpu(memcg->stat->count[idx], cpu);
+       /*
+        * Summing races with updates, so val may be negative.  Avoid exposing
+        * transient negative values.
+        */
+       if (val < 0)
+               val = 0;
        return val;
 }
 
@@ -1254,7 +1263,7 @@ void mem_cgroup_print_oom_info(struct mem_cgroup *memcg, struct task_struct *p)
                for (i = 0; i < MEM_CGROUP_STAT_NSTATS; i++) {
                        if (i == MEM_CGROUP_STAT_SWAP && !do_swap_account)
                                continue;
-                       pr_cont(" %s:%ldKB", mem_cgroup_stat_names[i],
+                       pr_cont(" %s:%luKB", mem_cgroup_stat_names[i],
                                K(mem_cgroup_read_stat(iter, i)));
                }
 
@@ -2819,14 +2828,11 @@ static unsigned long tree_stat(struct mem_cgroup *memcg,
                               enum mem_cgroup_stat_index idx)
 {
        struct mem_cgroup *iter;
-       long val = 0;
+       unsigned long val = 0;
 
-       /* Per-cpu values can be negative, use a signed accumulator */
        for_each_mem_cgroup_tree(iter, memcg)
                val += mem_cgroup_read_stat(iter, idx);
 
-       if (val < 0) /* race ? */
-               val = 0;
        return val;
 }
 
@@ -3169,7 +3175,7 @@ static int memcg_stat_show(struct seq_file *m, void *v)
        for (i = 0; i < MEM_CGROUP_STAT_NSTATS; i++) {
                if (i == MEM_CGROUP_STAT_SWAP && !do_swap_account)
                        continue;
-               seq_printf(m, "%s %ld\n", mem_cgroup_stat_names[i],
+               seq_printf(m, "%s %lu\n", mem_cgroup_stat_names[i],
                           mem_cgroup_read_stat(memcg, i) * PAGE_SIZE);
        }
 
@@ -3194,13 +3200,13 @@ static int memcg_stat_show(struct seq_file *m, void *v)
                           (u64)memsw * PAGE_SIZE);
 
        for (i = 0; i < MEM_CGROUP_STAT_NSTATS; i++) {
-               long long val = 0;
+               unsigned long long val = 0;
 
                if (i == MEM_CGROUP_STAT_SWAP && !do_swap_account)
                        continue;
                for_each_mem_cgroup_tree(mi, memcg)
                        val += mem_cgroup_read_stat(mi, i) * PAGE_SIZE;
-               seq_printf(m, "total_%s %lld\n", mem_cgroup_stat_names[i], val);
+               seq_printf(m, "total_%s %llu\n", mem_cgroup_stat_names[i], val);
        }
 
        for (i = 0; i < MEM_CGROUP_EVENTS_NSTATS; i++) {
@@ -3381,6 +3387,7 @@ static int __mem_cgroup_usage_register_event(struct mem_cgroup *memcg,
        ret = page_counter_memparse(args, "-1", &threshold);
        if (ret)
                return ret;
+       threshold <<= PAGE_SHIFT;
 
        mutex_lock(&memcg->thresholds_lock);
 
@@ -3734,44 +3741,43 @@ struct wb_domain *mem_cgroup_wb_domain(struct bdi_writeback *wb)
 /**
  * mem_cgroup_wb_stats - retrieve writeback related stats from its memcg
  * @wb: bdi_writeback in question
- * @pavail: out parameter for number of available pages
+ * @pfilepages: out parameter for number of file pages
+ * @pheadroom: out parameter for number of allocatable pages according to memcg
  * @pdirty: out parameter for number of dirty pages
  * @pwriteback: out parameter for number of pages under writeback
  *
- * Determine the numbers of available, dirty, and writeback pages in @wb's
- * memcg.  Dirty and writeback are self-explanatory.  Available is a bit
- * more involved.
+ * Determine the numbers of file, headroom, dirty, and writeback pages in
+ * @wb's memcg.  File, dirty and writeback are self-explanatory.  Headroom
+ * is a bit more involved.
  *
- * A memcg's headroom is "min(max, high) - used".  The available memory is
- * calculated as the lowest headroom of itself and the ancestors plus the
- * number of pages already being used for file pages.  Note that this
- * doesn't consider the actual amount of available memory in the system.
- * The caller should further cap *@pavail accordingly.
+ * A memcg's headroom is "min(max, high) - used".  In the hierarchy, the
+ * headroom is calculated as the lowest headroom of itself and the
+ * ancestors.  Note that this doesn't consider the actual amount of
+ * available memory in the system.  The caller should further cap
+ * *@pheadroom accordingly.
  */
-void mem_cgroup_wb_stats(struct bdi_writeback *wb, unsigned long *pavail,
-                        unsigned long *pdirty, unsigned long *pwriteback)
+void mem_cgroup_wb_stats(struct bdi_writeback *wb, unsigned long *pfilepages,
+                        unsigned long *pheadroom, unsigned long *pdirty,
+                        unsigned long *pwriteback)
 {
        struct mem_cgroup *memcg = mem_cgroup_from_css(wb->memcg_css);
        struct mem_cgroup *parent;
-       unsigned long head_room = PAGE_COUNTER_MAX;
-       unsigned long file_pages;
 
        *pdirty = mem_cgroup_read_stat(memcg, MEM_CGROUP_STAT_DIRTY);
 
        /* this should eventually include NR_UNSTABLE_NFS */
        *pwriteback = mem_cgroup_read_stat(memcg, MEM_CGROUP_STAT_WRITEBACK);
+       *pfilepages = mem_cgroup_nr_lru_pages(memcg, (1 << LRU_INACTIVE_FILE) |
+                                                    (1 << LRU_ACTIVE_FILE));
+       *pheadroom = PAGE_COUNTER_MAX;
 
-       file_pages = mem_cgroup_nr_lru_pages(memcg, (1 << LRU_INACTIVE_FILE) |
-                                                   (1 << LRU_ACTIVE_FILE));
        while ((parent = parent_mem_cgroup(memcg))) {
                unsigned long ceiling = min(memcg->memory.limit, memcg->high);
                unsigned long used = page_counter_read(&memcg->memory);
 
-               head_room = min(head_room, ceiling - min(ceiling, used));
+               *pheadroom = min(*pheadroom, ceiling - min(ceiling, used));
                memcg = parent;
        }
-
-       *pavail = file_pages + head_room;
 }
 
 #else  /* CONFIG_CGROUP_WRITEBACK */
@@ -4179,7 +4185,6 @@ static struct mem_cgroup *mem_cgroup_alloc(void)
        if (memcg_wb_domain_init(memcg, GFP_KERNEL))
                goto out_free_stat;
 
-       spin_lock_init(&memcg->pcp_counter_lock);
        return memcg;
 
 out_free_stat:
index 9cb27470fee991cb874676bb0cbc0f694b5e1d36..deb679c31f2ab897cafebf72643aec4f66233308 100644 (file)
@@ -2426,6 +2426,8 @@ void unmap_mapping_range(struct address_space *mapping,
        if (details.last_index < details.first_index)
                details.last_index = ULONG_MAX;
 
+
+       /* DAX uses i_mmap_lock to serialise file truncate vs page fault */
        i_mmap_lock_write(mapping);
        if (unlikely(!RB_EMPTY_ROOT(&mapping->i_mmap)))
                unmap_mapping_range_tree(&mapping->i_mmap, &details);
index c3cb566af3e273a92e8353835b1cd6d03d64c7e3..842ecd7aaf7fa6ac1371f6137dc155c91851505c 100644 (file)
@@ -740,6 +740,15 @@ static int move_to_new_page(struct page *newpage, struct page *page,
        if (PageSwapBacked(page))
                SetPageSwapBacked(newpage);
 
+       /*
+        * Indirectly called below, migrate_page_copy() copies PG_dirty and thus
+        * needs newpage's memcg set to transfer memcg dirty page accounting.
+        * So perform memcg migration in two steps:
+        * 1. set newpage->mem_cgroup (here)
+        * 2. clear page->mem_cgroup (below)
+        */
+       set_page_memcg(newpage, page_memcg(page));
+
        mapping = page_mapping(page);
        if (!mapping)
                rc = migrate_page(mapping, newpage, page, mode);
@@ -756,9 +765,10 @@ static int move_to_new_page(struct page *newpage, struct page *page,
                rc = fallback_migrate_page(mapping, newpage, page, mode);
 
        if (rc != MIGRATEPAGE_SUCCESS) {
+               set_page_memcg(newpage, NULL);
                newpage->mapping = NULL;
        } else {
-               mem_cgroup_migrate(page, newpage, false);
+               set_page_memcg(page, NULL);
                if (page_was_mapped)
                        remove_migration_ptes(page, newpage);
                page->mapping = NULL;
@@ -1075,7 +1085,7 @@ out:
        if (rc != MIGRATEPAGE_SUCCESS && put_new_page)
                put_new_page(new_hpage, private);
        else
-               put_page(new_hpage);
+               putback_active_hugepage(new_hpage);
 
        if (result) {
                if (rc)
index 971dd2cb77d227b792f29f0f0cdc5d3d8aa16634..79bcc9f92e482de9047c3927e068ff392db5c1bc 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -612,8 +612,6 @@ static unsigned long count_vma_pages_range(struct mm_struct *mm,
 void __vma_link_rb(struct mm_struct *mm, struct vm_area_struct *vma,
                struct rb_node **rb_link, struct rb_node *rb_parent)
 {
-       WARN_ONCE(vma->vm_file && !vma->vm_ops, "missing vma->vm_ops");
-
        /* Update tracking information for the gap following the new vma. */
        if (vma->vm_next)
                vma_gap_update(vma->vm_next);
@@ -1492,13 +1490,14 @@ SYSCALL_DEFINE1(old_mmap, struct mmap_arg_struct __user *, arg)
 int vma_wants_writenotify(struct vm_area_struct *vma)
 {
        vm_flags_t vm_flags = vma->vm_flags;
+       const struct vm_operations_struct *vm_ops = vma->vm_ops;
 
        /* If it was private or non-writable, the write bit is already clear */
        if ((vm_flags & (VM_WRITE|VM_SHARED)) != ((VM_WRITE|VM_SHARED)))
                return 0;
 
        /* The backer wishes to know when pages are first written to? */
-       if (vma->vm_ops && vma->vm_ops->page_mkwrite)
+       if (vm_ops && (vm_ops->page_mkwrite || vm_ops->pfn_mkwrite))
                return 1;
 
        /* The open routine did something to the protections that pgprot_modify
@@ -1638,12 +1637,6 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
                 */
                WARN_ON_ONCE(addr != vma->vm_start);
 
-               /* All file mapping must have ->vm_ops set */
-               if (!vma->vm_ops) {
-                       static const struct vm_operations_struct dummy_ops = {};
-                       vma->vm_ops = &dummy_ops;
-               }
-
                addr = vma->vm_start;
                vm_flags = vma->vm_flags;
        } else if (vm_flags & VM_SHARED) {
index 0a931cdd4f6baaa96cdfab2e0dd668c0abef8809..2c90357c34ea4c4d81521b7bf14d669d6565cc07 100644 (file)
@@ -145,9 +145,6 @@ struct dirty_throttle_control {
        unsigned long           pos_ratio;
 };
 
-#define DTC_INIT_COMMON(__wb)  .wb = (__wb),                           \
-                               .wb_completions = &(__wb)->completions
-
 /*
  * Length of period for aging writeout fractions of bdis. This is an
  * arbitrarily chosen number. The longer the period, the slower fractions will
@@ -157,12 +154,16 @@ struct dirty_throttle_control {
 
 #ifdef CONFIG_CGROUP_WRITEBACK
 
-#define GDTC_INIT(__wb)                .dom = &global_wb_domain,               \
-                               DTC_INIT_COMMON(__wb)
+#define GDTC_INIT(__wb)                .wb = (__wb),                           \
+                               .dom = &global_wb_domain,               \
+                               .wb_completions = &(__wb)->completions
+
 #define GDTC_INIT_NO_WB                .dom = &global_wb_domain
-#define MDTC_INIT(__wb, __gdtc)        .dom = mem_cgroup_wb_domain(__wb),      \
-                               .gdtc = __gdtc,                         \
-                               DTC_INIT_COMMON(__wb)
+
+#define MDTC_INIT(__wb, __gdtc)        .wb = (__wb),                           \
+                               .dom = mem_cgroup_wb_domain(__wb),      \
+                               .wb_completions = &(__wb)->memcg_completions, \
+                               .gdtc = __gdtc
 
 static bool mdtc_valid(struct dirty_throttle_control *dtc)
 {
@@ -213,7 +214,8 @@ static void wb_min_max_ratio(struct bdi_writeback *wb,
 
 #else  /* CONFIG_CGROUP_WRITEBACK */
 
-#define GDTC_INIT(__wb)                DTC_INIT_COMMON(__wb)
+#define GDTC_INIT(__wb)                .wb = (__wb),                           \
+                               .wb_completions = &(__wb)->completions
 #define GDTC_INIT_NO_WB
 #define MDTC_INIT(__wb, __gdtc)
 
@@ -682,13 +684,19 @@ static unsigned long hard_dirty_limit(struct wb_domain *dom,
        return max(thresh, dom->dirty_limit);
 }
 
-/* memory available to a memcg domain is capped by system-wide clean memory */
-static void mdtc_cap_avail(struct dirty_throttle_control *mdtc)
+/*
+ * Memory which can be further allocated to a memcg domain is capped by
+ * system-wide clean memory excluding the amount being used in the domain.
+ */
+static void mdtc_calc_avail(struct dirty_throttle_control *mdtc,
+                           unsigned long filepages, unsigned long headroom)
 {
        struct dirty_throttle_control *gdtc = mdtc_gdtc(mdtc);
-       unsigned long clean = gdtc->avail - min(gdtc->avail, gdtc->dirty);
+       unsigned long clean = filepages - min(filepages, mdtc->dirty);
+       unsigned long global_clean = gdtc->avail - min(gdtc->avail, gdtc->dirty);
+       unsigned long other_clean = global_clean - min(global_clean, clean);
 
-       mdtc->avail = min(mdtc->avail, clean);
+       mdtc->avail = filepages + min(headroom, other_clean);
 }
 
 /**
@@ -1562,16 +1570,16 @@ static void balance_dirty_pages(struct address_space *mapping,
                }
 
                if (mdtc) {
-                       unsigned long writeback;
+                       unsigned long filepages, headroom, writeback;
 
                        /*
                         * If @wb belongs to !root memcg, repeat the same
                         * basic calculations for the memcg domain.
                         */
-                       mem_cgroup_wb_stats(wb, &mdtc->avail, &mdtc->dirty,
-                                           &writeback);
-                       mdtc_cap_avail(mdtc);
+                       mem_cgroup_wb_stats(wb, &filepages, &headroom,
+                                           &mdtc->dirty, &writeback);
                        mdtc->dirty += writeback;
+                       mdtc_calc_avail(mdtc, filepages, headroom);
 
                        domain_dirty_limits(mdtc);
 
@@ -1893,10 +1901,11 @@ bool wb_over_bg_thresh(struct bdi_writeback *wb)
                return true;
 
        if (mdtc) {
-               unsigned long writeback;
+               unsigned long filepages, headroom, writeback;
 
-               mem_cgroup_wb_stats(wb, &mdtc->avail, &mdtc->dirty, &writeback);
-               mdtc_cap_avail(mdtc);
+               mem_cgroup_wb_stats(wb, &filepages, &headroom, &mdtc->dirty,
+                                   &writeback);
+               mdtc_calc_avail(mdtc, filepages, headroom);
                domain_dirty_limits(mdtc);      /* ditto, ignore writeback */
 
                if (mdtc->dirty > mdtc->bg_thresh)
@@ -1956,7 +1965,6 @@ void laptop_mode_timer_fn(unsigned long data)
        int nr_pages = global_page_state(NR_FILE_DIRTY) +
                global_page_state(NR_UNSTABLE_NFS);
        struct bdi_writeback *wb;
-       struct wb_iter iter;
 
        /*
         * We want to write everything out, not just down to the dirty
@@ -1965,10 +1973,12 @@ void laptop_mode_timer_fn(unsigned long data)
        if (!bdi_has_dirty_io(&q->backing_dev_info))
                return;
 
-       bdi_for_each_wb(wb, &q->backing_dev_info, &iter, 0)
+       rcu_read_lock();
+       list_for_each_entry_rcu(wb, &q->backing_dev_info.wb_list, bdi_node)
                if (wb_has_dirty_io(wb))
                        wb_start_writeback(wb, nr_pages, true,
                                           WB_REASON_LAPTOP_TIMER);
+       rcu_read_unlock();
 }
 
 /*
index 60cd846a9a4401f73a6a51539507ecc22fb308d4..24682f6f4cfd1d84d7245faea0da78e7fd17e716 100644 (file)
@@ -89,8 +89,8 @@ int read_cache_pages(struct address_space *mapping, struct list_head *pages,
        while (!list_empty(pages)) {
                page = list_to_page(pages);
                list_del(&page->lru);
-               if (add_to_page_cache_lru(page, mapping,
-                                       page->index, GFP_KERNEL)) {
+               if (add_to_page_cache_lru(page, mapping, page->index,
+                               GFP_KERNEL & mapping_gfp_mask(mapping))) {
                        read_cache_pages_invalidate_page(mapping, page);
                        continue;
                }
@@ -127,8 +127,8 @@ static int read_pages(struct address_space *mapping, struct file *filp,
        for (page_idx = 0; page_idx < nr_pages; page_idx++) {
                struct page *page = list_to_page(pages);
                list_del(&page->lru);
-               if (!add_to_page_cache_lru(page, mapping,
-                                       page->index, GFP_KERNEL)) {
+               if (!add_to_page_cache_lru(page, mapping, page->index,
+                               GFP_KERNEL & mapping_gfp_mask(mapping))) {
                        mapping->a_ops->readpage(filp, page);
                }
                page_cache_release(page);
index c77ebe6cc87cd3066f24fd9e3682699448689fa8..4fcc5dd8d5a6c2776ac2f88d9011ac23c78fb769 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -2190,9 +2190,16 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags)
                        size += BYTES_PER_WORD;
        }
 #if FORCED_DEBUG && defined(CONFIG_DEBUG_PAGEALLOC)
-       if (size >= kmalloc_size(INDEX_NODE + 1)
-           && cachep->object_size > cache_line_size()
-           && ALIGN(size, cachep->align) < PAGE_SIZE) {
+       /*
+        * To activate debug pagealloc, off-slab management is necessary
+        * requirement. In early phase of initialization, small sized slab
+        * doesn't get initialized so it would not be possible. So, we need
+        * to check size >= 256. It guarantees that all necessary small
+        * sized slab is initialized in current slab initialization sequence.
+        */
+       if (!slab_early_init && size >= kmalloc_size(INDEX_NODE) &&
+               size >= 256 && cachep->object_size > cache_line_size() &&
+               ALIGN(size, cachep->align) < PAGE_SIZE) {
                cachep->obj_offset += PAGE_SIZE - ALIGN(size, cachep->align);
                size = PAGE_SIZE;
        }
index 2d978b28a410b25df1acde351630dee387efbbe5..7f63a9381f71ebbb0c1f9bdda94a913c930280f0 100644 (file)
@@ -175,7 +175,7 @@ static bool sane_reclaim(struct scan_control *sc)
        if (!memcg)
                return true;
 #ifdef CONFIG_CGROUP_WRITEBACK
-       if (memcg->css.cgroup)
+       if (cgroup_on_dfl(memcg->css.cgroup))
                return true;
 #endif
        return false;
index 4f5cd974e11a0adbb8a601cc92b9866ab6d67d55..fbf14485a0498bf181e81f43bc69a0522e67afd5 100644 (file)
@@ -1363,15 +1363,16 @@ static cpumask_var_t cpu_stat_off;
 
 static void vmstat_update(struct work_struct *w)
 {
-       if (refresh_cpu_vm_stats())
+       if (refresh_cpu_vm_stats()) {
                /*
                 * Counters were updated so we expect more updates
                 * to occur in the future. Keep on running the
                 * update worker thread.
                 */
-               schedule_delayed_work(this_cpu_ptr(&vmstat_work),
+               schedule_delayed_work_on(smp_processor_id(),
+                       this_cpu_ptr(&vmstat_work),
                        round_jiffies_relative(sysctl_stat_interval));
-       else {
+       else {
                /*
                 * We did not update any counters so the app may be in
                 * a mode where it does not cause counter updates.
index 17e55dfecbe2a133a2a0e02d363b583a0334aecc..e07f551a863c89705fcbd348f2ac2eb73fd002fe 100644 (file)
@@ -317,6 +317,9 @@ static int clip_constructor(struct neighbour *neigh)
 
 static int clip_encap(struct atm_vcc *vcc, int mode)
 {
+       if (!CLIP_VCC(vcc))
+               return -EBADFD;
+
        CLIP_VCC(vcc)->encap = mode;
        return 0;
 }
index b4548c739a6475446d643bd5b01ab8627ef1f08e..2dda439c8cb83b7fa72b238dcf93023088762001 100644 (file)
@@ -91,10 +91,50 @@ static void hci_connect_le_scan_cleanup(struct hci_conn *conn)
         * autoconnect action, remove them completely. If they are, just unmark
         * them as waiting for connection, by clearing explicit_connect field.
         */
-       if (params->auto_connect == HCI_AUTO_CONN_EXPLICIT)
+       params->explicit_connect = false;
+
+       list_del_init(&params->action);
+
+       switch (params->auto_connect) {
+       case HCI_AUTO_CONN_EXPLICIT:
                hci_conn_params_del(conn->hdev, bdaddr, bdaddr_type);
-       else
-               params->explicit_connect = false;
+               /* return instead of break to avoid duplicate scan update */
+               return;
+       case HCI_AUTO_CONN_DIRECT:
+       case HCI_AUTO_CONN_ALWAYS:
+               list_add(&params->action, &conn->hdev->pend_le_conns);
+               break;
+       case HCI_AUTO_CONN_REPORT:
+               list_add(&params->action, &conn->hdev->pend_le_reports);
+               break;
+       default:
+               break;
+       }
+
+       hci_update_background_scan(conn->hdev);
+}
+
+static void hci_conn_cleanup(struct hci_conn *conn)
+{
+       struct hci_dev *hdev = conn->hdev;
+
+       if (test_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags))
+               hci_conn_params_del(conn->hdev, &conn->dst, conn->dst_type);
+
+       hci_chan_list_flush(conn);
+
+       hci_conn_hash_del(hdev, conn);
+
+       if (hdev->notify)
+               hdev->notify(hdev, HCI_NOTIFY_CONN_DEL);
+
+       hci_conn_del_sysfs(conn);
+
+       debugfs_remove_recursive(conn->debugfs);
+
+       hci_dev_put(hdev);
+
+       hci_conn_put(conn);
 }
 
 /* This function requires the caller holds hdev->lock */
@@ -102,8 +142,13 @@ static void hci_connect_le_scan_remove(struct hci_conn *conn)
 {
        hci_connect_le_scan_cleanup(conn);
 
-       hci_conn_hash_del(conn->hdev, conn);
-       hci_update_background_scan(conn->hdev);
+       /* We can't call hci_conn_del here since that would deadlock
+        * with trying to call cancel_delayed_work_sync(&conn->disc_work).
+        * Instead, call just hci_conn_cleanup() which contains the bare
+        * minimum cleanup operations needed for a connection in this
+        * state.
+        */
+       hci_conn_cleanup(conn);
 }
 
 static void hci_acl_create_connection(struct hci_conn *conn)
@@ -581,27 +626,17 @@ int hci_conn_del(struct hci_conn *conn)
                }
        }
 
-       hci_chan_list_flush(conn);
-
        if (conn->amp_mgr)
                amp_mgr_put(conn->amp_mgr);
 
-       hci_conn_hash_del(hdev, conn);
-       if (hdev->notify)
-               hdev->notify(hdev, HCI_NOTIFY_CONN_DEL);
-
        skb_queue_purge(&conn->data_q);
 
-       hci_conn_del_sysfs(conn);
-
-       debugfs_remove_recursive(conn->debugfs);
-
-       if (test_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags))
-               hci_conn_params_del(conn->hdev, &conn->dst, conn->dst_type);
-
-       hci_dev_put(hdev);
-
-       hci_conn_put(conn);
+       /* Remove the connection from the list and cleanup its remaining
+        * state. This is a separate function since for some cases like
+        * BT_CONNECT_SCAN we *only* want the cleanup part without the
+        * rest of hci_conn_del.
+        */
+       hci_conn_cleanup(conn);
 
        return 0;
 }
@@ -973,15 +1008,23 @@ static int hci_explicit_conn_params_set(struct hci_request *req,
        if (is_connected(hdev, addr, addr_type))
                return -EISCONN;
 
-       params = hci_conn_params_add(hdev, addr, addr_type);
-       if (!params)
-               return -EIO;
+       params = hci_conn_params_lookup(hdev, addr, addr_type);
+       if (!params) {
+               params = hci_conn_params_add(hdev, addr, addr_type);
+               if (!params)
+                       return -ENOMEM;
 
-       /* If we created new params, or existing params were marked as disabled,
-        * mark them to be used just once to connect.
-        */
-       if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
+               /* If we created new params, mark them to be deleted in
+                * hci_connect_le_scan_cleanup. It's different case than
+                * existing disabled params, those will stay after cleanup.
+                */
                params->auto_connect = HCI_AUTO_CONN_EXPLICIT;
+       }
+
+       /* We're trying to connect, so make sure params are at pend_le_conns */
+       if (params->auto_connect == HCI_AUTO_CONN_DISABLED ||
+           params->auto_connect == HCI_AUTO_CONN_REPORT ||
+           params->auto_connect == HCI_AUTO_CONN_EXPLICIT) {
                list_del_init(&params->action);
                list_add(&params->action, &hdev->pend_le_conns);
        }
index adcbc74c243268e8330bf760c39fa792a1c2a3a8..e837539452fb0e2880d8335da7769752a3b08110 100644 (file)
@@ -2861,13 +2861,6 @@ struct hci_conn_params *hci_explicit_connect_lookup(struct hci_dev *hdev,
                        return param;
        }
 
-       list_for_each_entry(param, &hdev->pend_le_reports, action) {
-               if (bacmp(&param->addr, addr) == 0 &&
-                   param->addr_type == addr_type &&
-                   param->explicit_connect)
-                       return param;
-       }
-
        return NULL;
 }
 
index 186041866315a4e107de086df52142f39d6c6ee3..bc31099d3b5bd113a8496b2ccad9e3e40364187f 100644 (file)
@@ -55,7 +55,12 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
        wake_up_bit(&hdev->flags, HCI_INQUIRY);
 
        hci_dev_lock(hdev);
-       hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
+       /* Set discovery state to stopped if we're not doing LE active
+        * scanning.
+        */
+       if (!hci_dev_test_flag(hdev, HCI_LE_SCAN) ||
+           hdev->le_scan_type != LE_SCAN_ACTIVE)
+               hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
        hci_dev_unlock(hdev);
 
        hci_conn_check_pending(hdev);
@@ -4648,8 +4653,8 @@ static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev,
        /* If we're not connectable only connect devices that we have in
         * our pend_le_conns list.
         */
-       params = hci_explicit_connect_lookup(hdev, addr, addr_type);
-
+       params = hci_pend_le_action_lookup(&hdev->pend_le_conns, addr,
+                                          addr_type);
        if (!params)
                return NULL;
 
index ccaf5a436d8f7a70799729a04ffc17583d11913f..c4fe2fee753fcfaa4233a4bb6675bbbdd29fc9d5 100644 (file)
@@ -3545,6 +3545,7 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
                                       auth_type);
        } else {
                u8 addr_type;
+               struct hci_conn_params *p;
 
                /* Convert from L2CAP channel address type to HCI address type
                 */
@@ -3562,7 +3563,10 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
                 * If connection parameters already exist, then they
                 * will be kept and this function does nothing.
                 */
-               hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
+               p = hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
+
+               if (p->auto_connect == HCI_AUTO_CONN_EXPLICIT)
+                       p->auto_connect = HCI_AUTO_CONN_DISABLED;
 
                conn = hci_connect_le_scan(hdev, &cp->addr.bdaddr,
                                           addr_type, sec_level,
@@ -6117,14 +6121,21 @@ static int hci_conn_params_set(struct hci_request *req, bdaddr_t *addr,
                __hci_update_background_scan(req);
                break;
        case HCI_AUTO_CONN_REPORT:
-               list_add(&params->action, &hdev->pend_le_reports);
+               if (params->explicit_connect)
+                       list_add(&params->action, &hdev->pend_le_conns);
+               else
+                       list_add(&params->action, &hdev->pend_le_reports);
                __hci_update_background_scan(req);
                break;
        case HCI_AUTO_CONN_DIRECT:
        case HCI_AUTO_CONN_ALWAYS:
                if (!is_connected(hdev, addr, addr_type)) {
                        list_add(&params->action, &hdev->pend_le_conns);
-                       __hci_update_background_scan(req);
+                       /* If we are in scan phase of connecting, we were
+                        * already added to pend_le_conns and scanning.
+                        */
+                       if (params->auto_connect != HCI_AUTO_CONN_EXPLICIT)
+                               __hci_update_background_scan(req);
                }
                break;
        }
@@ -6379,7 +6390,8 @@ static int remove_device(struct sock *sk, struct hci_dev *hdev,
                        goto unlock;
                }
 
-               if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
+               if (params->auto_connect == HCI_AUTO_CONN_DISABLED ||
+                   params->auto_connect == HCI_AUTO_CONN_EXPLICIT) {
                        err = cmd->cmd_complete(cmd,
                                                MGMT_STATUS_INVALID_PARAMS);
                        mgmt_pending_remove(cmd);
@@ -6415,6 +6427,10 @@ static int remove_device(struct sock *sk, struct hci_dev *hdev,
                        if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
                                continue;
                        device_removed(sk, hdev, &p->addr, p->addr_type);
+                       if (p->explicit_connect) {
+                               p->auto_connect = HCI_AUTO_CONN_EXPLICIT;
+                               continue;
+                       }
                        list_del(&p->action);
                        list_del(&p->list);
                        kfree(p);
index ad82324f710f0f97427a51c632e5a8aebfaba292..0510a577a7b58ef7dfbace4a68d712a3b8239891 100644 (file)
@@ -2311,12 +2311,6 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
        if (!conn)
                return 1;
 
-       chan = conn->smp;
-       if (!chan) {
-               BT_ERR("SMP security requested but not available");
-               return 1;
-       }
-
        if (!hci_dev_test_flag(hcon->hdev, HCI_LE_ENABLED))
                return 1;
 
@@ -2330,6 +2324,12 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
                if (smp_ltk_encrypt(conn, hcon->pending_sec_level))
                        return 0;
 
+       chan = conn->smp;
+       if (!chan) {
+               BT_ERR("SMP security requested but not available");
+               return 1;
+       }
+
        l2cap_chan_lock(chan);
 
        /* If SMP is already in progress ignore this request */
index 66efdc21f548524a19f3abc3ea5268b245f88dd2..480b3de1a0e3e158a0968355902a8da4764b5d4f 100644 (file)
@@ -1006,7 +1006,7 @@ static int br_ip4_multicast_igmp3_report(struct net_bridge *br,
 
        ih = igmpv3_report_hdr(skb);
        num = ntohs(ih->ngrec);
-       len = sizeof(*ih);
+       len = skb_transport_offset(skb) + sizeof(*ih);
 
        for (i = 0; i < num; i++) {
                len += sizeof(*grec);
@@ -1067,7 +1067,7 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br,
 
        icmp6h = icmp6_hdr(skb);
        num = ntohs(icmp6h->icmp6_dataun.un_data16[1]);
-       len = sizeof(*icmp6h);
+       len = skb_transport_offset(skb) + sizeof(*icmp6h);
 
        for (i = 0; i < num; i++) {
                __be16 *nsrcs, _nsrcs;
index 525f454f753185b216e1dbd3d2bb4d9e89c1dac5..b9b0e3b5da49f84d9fb1775e75aca83f55e80b2d 100644 (file)
@@ -1353,11 +1353,12 @@ static void prepare_write_keepalive(struct ceph_connection *con)
        dout("prepare_write_keepalive %p\n", con);
        con_out_kvec_reset(con);
        if (con->peer_features & CEPH_FEATURE_MSGR_KEEPALIVE2) {
-               struct timespec ts = CURRENT_TIME;
-               struct ceph_timespec ceph_ts;
-               ceph_encode_timespec(&ceph_ts, &ts);
+               struct timespec now = CURRENT_TIME;
+
                con_out_kvec_add(con, sizeof(tag_keepalive2), &tag_keepalive2);
-               con_out_kvec_add(con, sizeof(ceph_ts), &ceph_ts);
+               ceph_encode_timespec(&con->out_temp_keepalive2, &now);
+               con_out_kvec_add(con, sizeof(con->out_temp_keepalive2),
+                                &con->out_temp_keepalive2);
        } else {
                con_out_kvec_add(con, sizeof(tag_keepalive), &tag_keepalive);
        }
index 80b94e37c94aae115155454b9f4386a1b91021de..f79ccac6699fb7b171b680261db9000f7fe4c70c 100644 (file)
@@ -285,6 +285,7 @@ static void osd_req_op_data_release(struct ceph_osd_request *osd_req,
        switch (op->op) {
        case CEPH_OSD_OP_READ:
        case CEPH_OSD_OP_WRITE:
+       case CEPH_OSD_OP_WRITEFULL:
                ceph_osd_data_release(&op->extent.osd_data);
                break;
        case CEPH_OSD_OP_CALL:
@@ -485,13 +486,14 @@ void osd_req_op_extent_init(struct ceph_osd_request *osd_req,
        size_t payload_len = 0;
 
        BUG_ON(opcode != CEPH_OSD_OP_READ && opcode != CEPH_OSD_OP_WRITE &&
-              opcode != CEPH_OSD_OP_ZERO && opcode != CEPH_OSD_OP_TRUNCATE);
+              opcode != CEPH_OSD_OP_WRITEFULL && opcode != CEPH_OSD_OP_ZERO &&
+              opcode != CEPH_OSD_OP_TRUNCATE);
 
        op->extent.offset = offset;
        op->extent.length = length;
        op->extent.truncate_size = truncate_size;
        op->extent.truncate_seq = truncate_seq;
-       if (opcode == CEPH_OSD_OP_WRITE)
+       if (opcode == CEPH_OSD_OP_WRITE || opcode == CEPH_OSD_OP_WRITEFULL)
                payload_len += length;
 
        op->payload_len = payload_len;
@@ -670,9 +672,11 @@ static u64 osd_req_encode_op(struct ceph_osd_request *req,
                break;
        case CEPH_OSD_OP_READ:
        case CEPH_OSD_OP_WRITE:
+       case CEPH_OSD_OP_WRITEFULL:
        case CEPH_OSD_OP_ZERO:
        case CEPH_OSD_OP_TRUNCATE:
-               if (src->op == CEPH_OSD_OP_WRITE)
+               if (src->op == CEPH_OSD_OP_WRITE ||
+                   src->op == CEPH_OSD_OP_WRITEFULL)
                        request_data_len = src->extent.length;
                dst->extent.offset = cpu_to_le64(src->extent.offset);
                dst->extent.length = cpu_to_le64(src->extent.length);
@@ -681,7 +685,8 @@ static u64 osd_req_encode_op(struct ceph_osd_request *req,
                dst->extent.truncate_seq =
                        cpu_to_le32(src->extent.truncate_seq);
                osd_data = &src->extent.osd_data;
-               if (src->op == CEPH_OSD_OP_WRITE)
+               if (src->op == CEPH_OSD_OP_WRITE ||
+                   src->op == CEPH_OSD_OP_WRITEFULL)
                        ceph_osdc_msg_data_add(req->r_request, osd_data);
                else
                        ceph_osdc_msg_data_add(req->r_reply, osd_data);
index 877c84834d81a601ee4934fb287d1afccd4ee598..c14748d051e7f58343768e920e52317154ef06fb 100644 (file)
@@ -99,6 +99,7 @@
 #include <linux/rtnetlink.h>
 #include <linux/stat.h>
 #include <net/dst.h>
+#include <net/dst_metadata.h>
 #include <net/pkt_sched.h>
 #include <net/checksum.h>
 #include <net/xfrm.h>
@@ -681,6 +682,32 @@ int dev_get_iflink(const struct net_device *dev)
 }
 EXPORT_SYMBOL(dev_get_iflink);
 
+/**
+ *     dev_fill_metadata_dst - Retrieve tunnel egress information.
+ *     @dev: targeted interface
+ *     @skb: The packet.
+ *
+ *     For better visibility of tunnel traffic OVS needs to retrieve
+ *     egress tunnel information for a packet. Following API allows
+ *     user to get this info.
+ */
+int dev_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
+{
+       struct ip_tunnel_info *info;
+
+       if (!dev->netdev_ops  || !dev->netdev_ops->ndo_fill_metadata_dst)
+               return -EINVAL;
+
+       info = skb_tunnel_info_unclone(skb);
+       if (!info)
+               return -ENOMEM;
+       if (unlikely(!(info->mode & IP_TUNNEL_INFO_TX)))
+               return -EINVAL;
+
+       return dev->netdev_ops->ndo_fill_metadata_dst(dev, skb);
+}
+EXPORT_SYMBOL_GPL(dev_fill_metadata_dst);
+
 /**
  *     __dev_get_by_name       - find a device by its name
  *     @net: the applicable net namespace
@@ -4713,6 +4740,8 @@ void napi_disable(struct napi_struct *n)
 
        while (test_and_set_bit(NAPI_STATE_SCHED, &n->state))
                msleep(1);
+       while (test_and_set_bit(NAPI_STATE_NPSVC, &n->state))
+               msleep(1);
 
        hrtimer_cancel(&n->timer);
 
index b495ab1797fae303d12a3251f09b141052c1ff55..29edf74846fc9cfef49f3fc35b4ba41de6c254af 100644 (file)
@@ -1284,7 +1284,7 @@ static int ethtool_get_strings(struct net_device *dev, void __user *useraddr)
 
        gstrings.len = ret;
 
-       data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER);
+       data = kcalloc(gstrings.len, ETH_GSTRING_LEN, GFP_USER);
        if (!data)
                return -ENOMEM;
 
index bf77e3639ce0fd318822cca563c56b4376f9e8b7..365de66436aca8dba3868aa565d4cb77353b58d1 100644 (file)
@@ -631,15 +631,17 @@ static int dump_rules(struct sk_buff *skb, struct netlink_callback *cb,
 {
        int idx = 0;
        struct fib_rule *rule;
+       int err = 0;
 
        rcu_read_lock();
        list_for_each_entry_rcu(rule, &ops->rules_list, list) {
                if (idx < cb->args[1])
                        goto skip;
 
-               if (fib_nl_fill_rule(skb, rule, NETLINK_CB(cb->skb).portid,
-                                    cb->nlh->nlmsg_seq, RTM_NEWRULE,
-                                    NLM_F_MULTI, ops) < 0)
+               err = fib_nl_fill_rule(skb, rule, NETLINK_CB(cb->skb).portid,
+                                      cb->nlh->nlmsg_seq, RTM_NEWRULE,
+                                      NLM_F_MULTI, ops);
+               if (err)
                        break;
 skip:
                idx++;
@@ -648,7 +650,7 @@ skip:
        cb->args[1] = idx;
        rules_ops_put(ops);
 
-       return skb->len;
+       return err;
 }
 
 static int fib_nl_dumprule(struct sk_buff *skb, struct netlink_callback *cb)
@@ -664,7 +666,9 @@ static int fib_nl_dumprule(struct sk_buff *skb, struct netlink_callback *cb)
                if (ops == NULL)
                        return -EAFNOSUPPORT;
 
-               return dump_rules(skb, cb, ops);
+               dump_rules(skb, cb, ops);
+
+               return skb->len;
        }
 
        rcu_read_lock();
index 13079f03902e7674b7cd71bf01ca1d12844c758b..bb18c368000129ebea752a0a78785524848eaab8 100644 (file)
@@ -478,9 +478,9 @@ do_pass:
                                bpf_src = BPF_X;
                        } else {
                                insn->dst_reg = BPF_REG_A;
-                               insn->src_reg = BPF_REG_X;
                                insn->imm = fp->k;
                                bpf_src = BPF_SRC(fp->code);
+                               insn->src_reg = bpf_src == BPF_X ? BPF_REG_X : 0;
                        }
 
                        /* Common case where 'jump_false' is next insn. */
@@ -1415,6 +1415,7 @@ static u64 bpf_clone_redirect(u64 r1, u64 ifindex, u64 flags, u64 r4, u64 r5)
                return dev_forward_skb(dev, skb2);
 
        skb2->dev = dev;
+       skb_sender_cpu_clear(skb2);
        return dev_queue_xmit(skb2);
 }
 
@@ -1854,9 +1855,13 @@ int sk_get_filter(struct sock *sk, struct sock_filter __user *ubuf,
                goto out;
 
        /* We're copying the filter that has been originally attached,
-        * so no conversion/decode needed anymore.
+        * so no conversion/decode needed anymore. eBPF programs that
+        * have no original program cannot be dumped through this.
         */
+       ret = -EACCES;
        fprog = filter->prog->orig_prog;
+       if (!fprog)
+               goto out;
 
        ret = fprog->len;
        if (!len)
index b279077c30894dfeb69e2c21686d702cc809e678..830f8a7c1cb173caf3df0c9044bb81f9363338d8 100644 (file)
@@ -31,7 +31,6 @@
 static const char fmt_hex[] = "%#x\n";
 static const char fmt_long_hex[] = "%#lx\n";
 static const char fmt_dec[] = "%d\n";
-static const char fmt_udec[] = "%u\n";
 static const char fmt_ulong[] = "%lu\n";
 static const char fmt_u64[] = "%llu\n";
 
@@ -202,7 +201,7 @@ static ssize_t speed_show(struct device *dev,
        if (netif_running(netdev)) {
                struct ethtool_cmd cmd;
                if (!__ethtool_get_settings(netdev, &cmd))
-                       ret = sprintf(buf, fmt_udec, ethtool_cmd_speed(&cmd));
+                       ret = sprintf(buf, fmt_dec, ethtool_cmd_speed(&cmd));
        }
        rtnl_unlock();
        return ret;
@@ -1481,6 +1480,15 @@ static int of_dev_node_match(struct device *dev, const void *data)
        return ret == 0 ? dev->of_node == data : ret;
 }
 
+/*
+ * of_find_net_device_by_node - lookup the net device for the device node
+ * @np: OF device node
+ *
+ * Looks up the net_device structure corresponding with the device node.
+ * If successful, returns a pointer to the net_device with the embedded
+ * struct device refcount incremented by one, or NULL on failure. The
+ * refcount must be dropped when done with the net_device.
+ */
 struct net_device *of_find_net_device_by_node(struct device_node *np)
 {
        struct device *dev;
index 6aa3db8dfc3b5512577b60f9bf85439c726f85b8..8bdada242a7d1266fe276f86aa02bd1691d56697 100644 (file)
@@ -142,7 +142,7 @@ static void queue_process(struct work_struct *work)
  */
 static int poll_one_napi(struct napi_struct *napi, int budget)
 {
-       int work;
+       int work = 0;
 
        /* net_rx_action's ->poll() invocations and our's are
         * synchronized by this test which is only made while
@@ -151,7 +151,12 @@ static int poll_one_napi(struct napi_struct *napi, int budget)
        if (!test_bit(NAPI_STATE_SCHED, &napi->state))
                return budget;
 
-       set_bit(NAPI_STATE_NPSVC, &napi->state);
+       /* If we set this bit but see that it has already been set,
+        * that indicates that napi has been disabled and we need
+        * to abort this operation
+        */
+       if (test_and_set_bit(NAPI_STATE_NPSVC, &napi->state))
+               goto out;
 
        work = napi->poll(napi, budget);
        WARN_ONCE(work > budget, "%pF exceeded budget in poll\n", napi->poll);
@@ -159,6 +164,7 @@ static int poll_one_napi(struct napi_struct *napi, int budget)
 
        clear_bit(NAPI_STATE_NPSVC, &napi->state);
 
+out:
        return budget - work;
 }
 
index a466821d1441f22ac244eb3366f53f859a0aac29..0ec48403ed68cc77b29b120665ed707bced816c4 100644 (file)
@@ -3047,6 +3047,7 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb)
        u32 portid = NETLINK_CB(cb->skb).portid;
        u32 seq = cb->nlh->nlmsg_seq;
        u32 filter_mask = 0;
+       int err;
 
        if (nlmsg_len(cb->nlh) > sizeof(struct ifinfomsg)) {
                struct nlattr *extfilt;
@@ -3067,20 +3068,25 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb)
                struct net_device *br_dev = netdev_master_upper_dev_get(dev);
 
                if (br_dev && br_dev->netdev_ops->ndo_bridge_getlink) {
-                       if (idx >= cb->args[0] &&
-                           br_dev->netdev_ops->ndo_bridge_getlink(
-                                   skb, portid, seq, dev, filter_mask,
-                                   NLM_F_MULTI) < 0)
-                               break;
+                       if (idx >= cb->args[0]) {
+                               err = br_dev->netdev_ops->ndo_bridge_getlink(
+                                               skb, portid, seq, dev,
+                                               filter_mask, NLM_F_MULTI);
+                               if (err < 0 && err != -EOPNOTSUPP)
+                                       break;
+                       }
                        idx++;
                }
 
                if (ops->ndo_bridge_getlink) {
-                       if (idx >= cb->args[0] &&
-                           ops->ndo_bridge_getlink(skb, portid, seq, dev,
-                                                   filter_mask,
-                                                   NLM_F_MULTI) < 0)
-                               break;
+                       if (idx >= cb->args[0]) {
+                               err = ops->ndo_bridge_getlink(skb, portid,
+                                                             seq, dev,
+                                                             filter_mask,
+                                                             NLM_F_MULTI);
+                               if (err < 0 && err != -EOPNOTSUPP)
+                                       break;
+                       }
                        idx++;
                }
        }
index dad4dd37e2aaad17b9493cb67796ed9650515a84..fab4599ba8b261dc43977af8349a336edc4d2799 100644 (file)
@@ -2958,11 +2958,12 @@ EXPORT_SYMBOL_GPL(skb_append_pagefrags);
  */
 unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len)
 {
+       unsigned char *data = skb->data;
+
        BUG_ON(len > skb->len);
-       skb->len -= len;
-       BUG_ON(skb->len < skb->data_len);
-       skb_postpull_rcsum(skb, skb->data, len);
-       return skb->data += len;
+       __skb_pull(skb, len);
+       skb_postpull_rcsum(skb, data, len);
+       return skb->data;
 }
 EXPORT_SYMBOL_GPL(skb_pull_rcsum);
 
index ca2984afe16ed6545a6d27cdfa91a3c5548bcbf2..3307c02244d39cfa3fbae969ea478fa0f195e595 100644 (file)
@@ -2740,10 +2740,8 @@ static void req_prot_cleanup(struct request_sock_ops *rsk_prot)
                return;
        kfree(rsk_prot->slab_name);
        rsk_prot->slab_name = NULL;
-       if (rsk_prot->slab) {
-               kmem_cache_destroy(rsk_prot->slab);
-               rsk_prot->slab = NULL;
-       }
+       kmem_cache_destroy(rsk_prot->slab);
+       rsk_prot->slab = NULL;
 }
 
 static int req_prot_init(const struct proto *prot)
@@ -2828,10 +2826,8 @@ void proto_unregister(struct proto *prot)
        list_del(&prot->node);
        mutex_unlock(&proto_list_mutex);
 
-       if (prot->slab != NULL) {
-               kmem_cache_destroy(prot->slab);
-               prot->slab = NULL;
-       }
+       kmem_cache_destroy(prot->slab);
+       prot->slab = NULL;
 
        req_prot_cleanup(prot->rsk_prot);
 
index bd9e718c2a209b5d4b7e4859fc68f77c79541366..3de0d0362d7fda81ff34926c6bac9e046b7552bc 100644 (file)
@@ -398,12 +398,8 @@ out_err:
 
 void dccp_ackvec_exit(void)
 {
-       if (dccp_ackvec_slab != NULL) {
-               kmem_cache_destroy(dccp_ackvec_slab);
-               dccp_ackvec_slab = NULL;
-       }
-       if (dccp_ackvec_record_slab != NULL) {
-               kmem_cache_destroy(dccp_ackvec_record_slab);
-               dccp_ackvec_record_slab = NULL;
-       }
+       kmem_cache_destroy(dccp_ackvec_slab);
+       dccp_ackvec_slab = NULL;
+       kmem_cache_destroy(dccp_ackvec_record_slab);
+       dccp_ackvec_record_slab = NULL;
 }
index 83498975165f9906b80349d58559eb36d81e0fae..90f77d08cc37a96991a605fe68914551ad95d543 100644 (file)
@@ -95,8 +95,7 @@ static struct kmem_cache *ccid_kmem_cache_create(int obj_size, char *slab_name_f
 
 static void ccid_kmem_cache_destroy(struct kmem_cache *slab)
 {
-       if (slab != NULL)
-               kmem_cache_destroy(slab);
+       kmem_cache_destroy(slab);
 }
 
 static int __init ccid_activate(struct ccid_operations *ccid_ops)
index 30addee2dd037f9686c5585243e503632dcdd21a..838f524cf11a177b473ca83e3d7f597ee2904d21 100644 (file)
@@ -48,8 +48,6 @@ void dccp_time_wait(struct sock *sk, int state, int timeo)
                        tw->tw_ipv6only = sk->sk_ipv6only;
                }
 #endif
-               /* Linkage updates. */
-               __inet_twsk_hashdance(tw, sk, &dccp_hashinfo);
 
                /* Get the TIME_WAIT timeout firing. */
                if (timeo < rto)
@@ -60,6 +58,8 @@ void dccp_time_wait(struct sock *sk, int state, int timeo)
                        timeo = DCCP_TIMEWAIT_LEN;
 
                inet_twsk_schedule(tw, timeo);
+               /* Linkage updates. */
+               __inet_twsk_hashdance(tw, sk, &dccp_hashinfo);
                inet_twsk_put(tw);
        } else {
                /* Sorry, if we're out of memory, just CLOSE this
index 76e3800765f881c554e93385c85f965cc96f611c..adb5325f49348412efb50f0eeee5a5f0fa1e50ed 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/of_platform.h>
 #include <linux/of_net.h>
 #include <linux/sysfs.h>
+#include <linux/phy_fixed.h>
 #include "dsa_priv.h"
 
 char dsa_driver_version[] = "0.1";
@@ -305,7 +306,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
        if (ret < 0)
                goto out;
 
-       ds->slave_mii_bus = mdiobus_alloc();
+       ds->slave_mii_bus = devm_mdiobus_alloc(parent);
        if (ds->slave_mii_bus == NULL) {
                ret = -ENOMEM;
                goto out;
@@ -314,7 +315,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
 
        ret = mdiobus_register(ds->slave_mii_bus);
        if (ret < 0)
-               goto out_free;
+               goto out;
 
 
        /*
@@ -367,10 +368,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
 
        return ret;
 
-out_free:
-       mdiobus_free(ds->slave_mii_bus);
 out:
-       kfree(ds);
        return ret;
 }
 
@@ -400,7 +398,7 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
        /*
         * Allocate and initialise switch state.
         */
-       ds = kzalloc(sizeof(*ds) + drv->priv_size, GFP_KERNEL);
+       ds = devm_kzalloc(parent, sizeof(*ds) + drv->priv_size, GFP_KERNEL);
        if (ds == NULL)
                return ERR_PTR(-ENOMEM);
 
@@ -420,10 +418,47 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
 
 static void dsa_switch_destroy(struct dsa_switch *ds)
 {
+       struct device_node *port_dn;
+       struct phy_device *phydev;
+       struct dsa_chip_data *cd = ds->pd;
+       int port;
+
 #ifdef CONFIG_NET_DSA_HWMON
        if (ds->hwmon_dev)
                hwmon_device_unregister(ds->hwmon_dev);
 #endif
+
+       /* Disable configuration of the CPU and DSA ports */
+       for (port = 0; port < DSA_MAX_PORTS; port++) {
+               if (!(dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)))
+                       continue;
+
+               port_dn = cd->port_dn[port];
+               if (of_phy_is_fixed_link(port_dn)) {
+                       phydev = of_phy_find_device(port_dn);
+                       if (phydev) {
+                               int addr = phydev->addr;
+
+                               phy_device_free(phydev);
+                               of_node_put(port_dn);
+                               fixed_phy_del(addr);
+                       }
+               }
+       }
+
+       /* Destroy network devices for physical switch ports. */
+       for (port = 0; port < DSA_MAX_PORTS; port++) {
+               if (!(ds->phys_port_mask & (1 << port)))
+                       continue;
+
+               if (!ds->ports[port])
+                       continue;
+
+               unregister_netdev(ds->ports[port]);
+               free_netdev(ds->ports[port]);
+       }
+
+       mdiobus_unregister(ds->slave_mii_bus);
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -634,6 +669,10 @@ static void dsa_of_free_platform_data(struct dsa_platform_data *pd)
                        port_index++;
                }
                kfree(pd->chip[i].rtable);
+
+               /* Drop our reference to the MDIO bus device */
+               if (pd->chip[i].host_dev)
+                       put_device(pd->chip[i].host_dev);
        }
        kfree(pd->chip);
 }
@@ -661,16 +700,22 @@ static int dsa_of_probe(struct device *dev)
                return -EPROBE_DEFER;
 
        ethernet = of_parse_phandle(np, "dsa,ethernet", 0);
-       if (!ethernet)
-               return -EINVAL;
+       if (!ethernet) {
+               ret = -EINVAL;
+               goto out_put_mdio;
+       }
 
        ethernet_dev = of_find_net_device_by_node(ethernet);
-       if (!ethernet_dev)
-               return -EPROBE_DEFER;
+       if (!ethernet_dev) {
+               ret = -EPROBE_DEFER;
+               goto out_put_mdio;
+       }
 
        pd = kzalloc(sizeof(*pd), GFP_KERNEL);
-       if (!pd)
-               return -ENOMEM;
+       if (!pd) {
+               ret = -ENOMEM;
+               goto out_put_ethernet;
+       }
 
        dev->platform_data = pd;
        pd->of_netdev = ethernet_dev;
@@ -691,7 +736,9 @@ static int dsa_of_probe(struct device *dev)
                cd = &pd->chip[chip_index];
 
                cd->of_node = child;
-               cd->host_dev = &mdio_bus->dev;
+
+               /* When assigning the host device, increment its refcount */
+               cd->host_dev = get_device(&mdio_bus->dev);
 
                sw_addr = of_get_property(child, "reg", NULL);
                if (!sw_addr)
@@ -711,6 +758,12 @@ static int dsa_of_probe(struct device *dev)
                                ret = -EPROBE_DEFER;
                                goto out_free_chip;
                        }
+
+                       /* Drop the mdio_bus device ref, replacing the host
+                        * device with the mdio_bus_switch device, keeping
+                        * the refcount from of_mdio_find_bus() above.
+                        */
+                       put_device(cd->host_dev);
                        cd->host_dev = &mdio_bus_switch->dev;
                }
 
@@ -744,6 +797,10 @@ static int dsa_of_probe(struct device *dev)
                }
        }
 
+       /* The individual chips hold their own refcount on the mdio bus,
+        * so drop ours */
+       put_device(&mdio_bus->dev);
+
        return 0;
 
 out_free_chip:
@@ -751,6 +808,10 @@ out_free_chip:
 out_free:
        kfree(pd);
        dev->platform_data = NULL;
+out_put_ethernet:
+       put_device(&ethernet_dev->dev);
+out_put_mdio:
+       put_device(&mdio_bus->dev);
        return ret;
 }
 
@@ -762,6 +823,7 @@ static void dsa_of_remove(struct device *dev)
                return;
 
        dsa_of_free_platform_data(pd);
+       put_device(&pd->of_netdev->dev);
        kfree(pd);
 }
 #else
@@ -775,10 +837,11 @@ static inline void dsa_of_remove(struct device *dev)
 }
 #endif
 
-static void dsa_setup_dst(struct dsa_switch_tree *dst, struct net_device *dev,
-                         struct device *parent, struct dsa_platform_data *pd)
+static int dsa_setup_dst(struct dsa_switch_tree *dst, struct net_device *dev,
+                        struct device *parent, struct dsa_platform_data *pd)
 {
        int i;
+       unsigned configured = 0;
 
        dst->pd = pd;
        dst->master_netdev = dev;
@@ -798,8 +861,16 @@ static void dsa_setup_dst(struct dsa_switch_tree *dst, struct net_device *dev,
                dst->ds[i] = ds;
                if (ds->drv->poll_link != NULL)
                        dst->link_poll_needed = 1;
+
+               ++configured;
        }
 
+       /*
+        * If no switch was found, exit cleanly
+        */
+       if (!configured)
+               return -EPROBE_DEFER;
+
        /*
         * If we use a tagging format that doesn't have an ethertype
         * field, make sure that all packets from this point on get
@@ -816,6 +887,8 @@ static void dsa_setup_dst(struct dsa_switch_tree *dst, struct net_device *dev,
                dst->link_poll_timer.expires = round_jiffies(jiffies + HZ);
                add_timer(&dst->link_poll_timer);
        }
+
+       return 0;
 }
 
 static int dsa_probe(struct platform_device *pdev)
@@ -856,7 +929,7 @@ static int dsa_probe(struct platform_device *pdev)
                goto out;
        }
 
-       dst = kzalloc(sizeof(*dst), GFP_KERNEL);
+       dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL);
        if (dst == NULL) {
                dev_put(dev);
                ret = -ENOMEM;
@@ -865,7 +938,9 @@ static int dsa_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, dst);
 
-       dsa_setup_dst(dst, dev, &pdev->dev, pd);
+       ret = dsa_setup_dst(dst, dev, &pdev->dev, pd);
+       if (ret)
+               goto out;
 
        return 0;
 
@@ -887,7 +962,7 @@ static void dsa_remove_dst(struct dsa_switch_tree *dst)
        for (i = 0; i < dst->pd->nr_chips; i++) {
                struct dsa_switch *ds = dst->ds[i];
 
-               if (ds != NULL)
+               if (ds)
                        dsa_switch_destroy(ds);
        }
 }
index cce97385f7436445f22c17605b5ee4da48c80cac..7d91f4612ac07406cfffd90defb6aa1d7436cb36 100644 (file)
@@ -458,12 +458,17 @@ static int dsa_slave_stp_update(struct net_device *dev, u8 state)
 static int dsa_slave_port_attr_set(struct net_device *dev,
                                   struct switchdev_attr *attr)
 {
-       int ret = 0;
+       struct dsa_slave_priv *p = netdev_priv(dev);
+       struct dsa_switch *ds = p->parent;
+       int ret;
 
        switch (attr->id) {
        case SWITCHDEV_ATTR_PORT_STP_STATE:
-               if (attr->trans == SWITCHDEV_TRANS_COMMIT)
-                       ret = dsa_slave_stp_update(dev, attr->u.stp_state);
+               if (attr->trans == SWITCHDEV_TRANS_PREPARE)
+                       ret = ds->drv->port_stp_update ? 0 : -EOPNOTSUPP;
+               else
+                       ret = ds->drv->port_stp_update(ds, p->port,
+                                                      attr->u.stp_state);
                break;
        default:
                ret = -EOPNOTSUPP;
index d25efc93d8f120739c83c3998e77d5e9dd3cfc45..b6ca0890d0188550f83d5d79939acb333778cb20 100644 (file)
@@ -78,7 +78,7 @@ static int trailer_rcv(struct sk_buff *skb, struct net_device *dev,
 
        trailer = skb_tail_pointer(skb) - 4;
        if (trailer[0] != 0x80 || (trailer[1] & 0xf8) != 0x00 ||
-           (trailer[3] & 0xef) != 0x00 || trailer[3] != 0x00)
+           (trailer[2] & 0xef) != 0x00 || trailer[3] != 0x00)
                goto out_drop;
 
        source_port = trailer[1] & 7;
index 30409b75e92503cca0daacc48010a63936c6aa20..0c9c3482e41997a671c23be7dc0387edb1403916 100644 (file)
 #include <net/arp.h>
 #include <net/ax25.h>
 #include <net/netrom.h>
+#include <net/dst_metadata.h>
+#include <net/ip_tunnels.h>
 
 #include <linux/uaccess.h>
 
@@ -296,7 +298,8 @@ static void arp_send_dst(int type, int ptype, __be32 dest_ip,
                         struct net_device *dev, __be32 src_ip,
                         const unsigned char *dest_hw,
                         const unsigned char *src_hw,
-                        const unsigned char *target_hw, struct sk_buff *oskb)
+                        const unsigned char *target_hw,
+                        struct dst_entry *dst)
 {
        struct sk_buff *skb;
 
@@ -309,9 +312,7 @@ static void arp_send_dst(int type, int ptype, __be32 dest_ip,
        if (!skb)
                return;
 
-       if (oskb)
-               skb_dst_copy(skb, oskb);
-
+       skb_dst_set(skb, dst_clone(dst));
        arp_xmit(skb);
 }
 
@@ -333,6 +334,7 @@ static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
        __be32 target = *(__be32 *)neigh->primary_key;
        int probes = atomic_read(&neigh->probes);
        struct in_device *in_dev;
+       struct dst_entry *dst = NULL;
 
        rcu_read_lock();
        in_dev = __in_dev_get_rcu(dev);
@@ -381,9 +383,10 @@ static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
                }
        }
 
+       if (skb && !(dev->priv_flags & IFF_XMIT_DST_RELEASE))
+               dst = skb_dst(skb);
        arp_send_dst(ARPOP_REQUEST, ETH_P_ARP, target, dev, saddr,
-                    dst_hw, dev->dev_addr, NULL,
-                    dev->priv_flags & IFF_XMIT_DST_RELEASE ? NULL : skb);
+                    dst_hw, dev->dev_addr, NULL, dst);
 }
 
 static int arp_ignore(struct in_device *in_dev, __be32 sip, __be32 tip)
@@ -649,6 +652,7 @@ static int arp_process(struct sock *sk, struct sk_buff *skb)
        int addr_type;
        struct neighbour *n;
        struct net *net = dev_net(dev);
+       struct dst_entry *reply_dst = NULL;
        bool is_garp = false;
 
        /* arp_rcv below verifies the ARP header and verifies the device
@@ -749,13 +753,18 @@ static int arp_process(struct sock *sk, struct sk_buff *skb)
  *  cache.
  */
 
+       if (arp->ar_op == htons(ARPOP_REQUEST) && skb_metadata_dst(skb))
+               reply_dst = (struct dst_entry *)
+                           iptunnel_metadata_reply(skb_metadata_dst(skb),
+                                                   GFP_ATOMIC);
+
        /* Special case: IPv4 duplicate address detection packet (RFC2131) */
        if (sip == 0) {
                if (arp->ar_op == htons(ARPOP_REQUEST) &&
                    inet_addr_type_dev_table(net, dev, tip) == RTN_LOCAL &&
                    !arp_ignore(in_dev, sip, tip))
-                       arp_send(ARPOP_REPLY, ETH_P_ARP, sip, dev, tip, sha,
-                                dev->dev_addr, sha);
+                       arp_send_dst(ARPOP_REPLY, ETH_P_ARP, sip, dev, tip,
+                                    sha, dev->dev_addr, sha, reply_dst);
                goto out;
        }
 
@@ -774,9 +783,10 @@ static int arp_process(struct sock *sk, struct sk_buff *skb)
                        if (!dont_send) {
                                n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
                                if (n) {
-                                       arp_send(ARPOP_REPLY, ETH_P_ARP, sip,
-                                                dev, tip, sha, dev->dev_addr,
-                                                sha);
+                                       arp_send_dst(ARPOP_REPLY, ETH_P_ARP,
+                                                    sip, dev, tip, sha,
+                                                    dev->dev_addr, sha,
+                                                    reply_dst);
                                        neigh_release(n);
                                }
                        }
@@ -794,13 +804,14 @@ static int arp_process(struct sock *sk, struct sk_buff *skb)
                                if (NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED ||
                                    skb->pkt_type == PACKET_HOST ||
                                    NEIGH_VAR(in_dev->arp_parms, PROXY_DELAY) == 0) {
-                                       arp_send(ARPOP_REPLY, ETH_P_ARP, sip,
-                                                dev, tip, sha, dev->dev_addr,
-                                                sha);
+                                       arp_send_dst(ARPOP_REPLY, ETH_P_ARP,
+                                                    sip, dev, tip, sha,
+                                                    dev->dev_addr, sha,
+                                                    reply_dst);
                                } else {
                                        pneigh_enqueue(&arp_tbl,
                                                       in_dev->arp_parms, skb);
-                                       return 0;
+                                       goto out_free_dst;
                                }
                                goto out;
                        }
@@ -854,6 +865,8 @@ static int arp_process(struct sock *sk, struct sk_buff *skb)
 
 out:
        consume_skb(skb);
+out_free_dst:
+       dst_release(reply_dst);
        return 0;
 }
 
index 6fcbd215cdbc501fe6541054208d68d965b5286e..690bcbc59f26d1add82e9ebaa82e2c072b84ca47 100644 (file)
@@ -340,6 +340,7 @@ static int __fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
        fl4.flowi4_tos = tos;
        fl4.flowi4_scope = RT_SCOPE_UNIVERSE;
        fl4.flowi4_tun_key.tun_id = 0;
+       fl4.flowi4_flags = 0;
 
        no_addr = idev->ifa_list == NULL;
 
index 26d6ffb6d23cdf4fff4150cb5f43ec35f5081fd4..744e5936c10d7ec555d1ca621f5bd4be57f1c72b 100644 (file)
@@ -1426,7 +1426,7 @@ found:
                            nh->nh_flags & RTNH_F_LINKDOWN &&
                            !(fib_flags & FIB_LOOKUP_IGNORE_LINKSTATE))
                                continue;
-                       if (!(flp->flowi4_flags & FLOWI_FLAG_VRFSRC)) {
+                       if (!(flp->flowi4_flags & FLOWI_FLAG_SKIP_NH_OIF)) {
                                if (flp->flowi4_oif &&
                                    flp->flowi4_oif != nh->nh_oif)
                                        continue;
@@ -1569,7 +1569,7 @@ static struct key_vector *leaf_walk_rcu(struct key_vector **tn, t_key key)
        do {
                /* record parent and next child index */
                pn = n;
-               cindex = key ? get_index(key, pn) : 0;
+               cindex = (key > pn->key) ? get_index(key, pn) : 0;
 
                if (cindex >> pn->bits)
                        break;
index 5aa46d4b44efb99702ccd89005528f20ae422a0e..5a8ee3282550880a7749b8d6a9086dc413661519 100644 (file)
@@ -36,7 +36,8 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
                                  SKB_GSO_TCP_ECN |
                                  SKB_GSO_GRE |
                                  SKB_GSO_GRE_CSUM |
-                                 SKB_GSO_IPIP)))
+                                 SKB_GSO_IPIP |
+                                 SKB_GSO_SIT)))
                goto out;
 
        if (!skb->encapsulation)
index 79fe05befcae907c4374ba8a4a0773b26f41e320..e5eb8ac4089d88cc2875d8f991da51899360698a 100644 (file)
@@ -427,7 +427,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
        fl4.flowi4_mark = mark;
        fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos);
        fl4.flowi4_proto = IPPROTO_ICMP;
-       fl4.flowi4_oif = vrf_master_ifindex(skb->dev) ? : skb->dev->ifindex;
+       fl4.flowi4_oif = vrf_master_ifindex(skb->dev);
        security_skb_classify_flow(skb, flowi4_to_flowi(&fl4));
        rt = ip_route_output_key(net, &fl4);
        if (IS_ERR(rt))
@@ -461,7 +461,7 @@ static struct rtable *icmp_route_lookup(struct net *net,
        fl4->flowi4_proto = IPPROTO_ICMP;
        fl4->fl4_icmp_type = type;
        fl4->fl4_icmp_code = code;
-       fl4->flowi4_oif = vrf_master_ifindex(skb_in->dev) ? : skb_in->dev->ifindex;
+       fl4->flowi4_oif = vrf_master_ifindex(skb_in->dev);
 
        security_skb_classify_flow(skb_in, flowi4_to_flowi(fl4));
        rt = __ip_route_output_key(net, fl4);
index 134957159c27eb9180e08b73360fe891574b4742..61b45a17fc738e17146a5e1f1cf97774f338179e 100644 (file)
@@ -577,21 +577,22 @@ EXPORT_SYMBOL(inet_rtx_syn_ack);
 static bool reqsk_queue_unlink(struct request_sock_queue *queue,
                               struct request_sock *req)
 {
-       struct listen_sock *lopt = queue->listen_opt;
        struct request_sock **prev;
+       struct listen_sock *lopt;
        bool found = false;
 
        spin_lock(&queue->syn_wait_lock);
-
-       for (prev = &lopt->syn_table[req->rsk_hash]; *prev != NULL;
-            prev = &(*prev)->dl_next) {
-               if (*prev == req) {
-                       *prev = req->dl_next;
-                       found = true;
-                       break;
+       lopt = queue->listen_opt;
+       if (lopt) {
+               for (prev = &lopt->syn_table[req->rsk_hash]; *prev != NULL;
+                    prev = &(*prev)->dl_next) {
+                       if (*prev == req) {
+                               *prev = req->dl_next;
+                               found = true;
+                               break;
+                       }
                }
        }
-
        spin_unlock(&queue->syn_wait_lock);
        if (timer_pending(&req->rsk_timer) && del_timer_sync(&req->rsk_timer))
                reqsk_put(req);
@@ -685,20 +686,20 @@ void reqsk_queue_hash_req(struct request_sock_queue *queue,
        req->num_timeout = 0;
        req->sk = NULL;
 
+       setup_timer(&req->rsk_timer, reqsk_timer_handler, (unsigned long)req);
+       mod_timer_pinned(&req->rsk_timer, jiffies + timeout);
+       req->rsk_hash = hash;
+
        /* before letting lookups find us, make sure all req fields
         * are committed to memory and refcnt initialized.
         */
        smp_wmb();
        atomic_set(&req->rsk_refcnt, 2);
-       setup_timer(&req->rsk_timer, reqsk_timer_handler, (unsigned long)req);
-       req->rsk_hash = hash;
 
        spin_lock(&queue->syn_wait_lock);
        req->dl_next = lopt->syn_table[hash];
        lopt->syn_table[hash] = req;
        spin_unlock(&queue->syn_wait_lock);
-
-       mod_timer_pinned(&req->rsk_timer, jiffies + timeout);
 }
 EXPORT_SYMBOL(reqsk_queue_hash_req);
 
index ae22cc24fbe89b32be1f2142450c198e78026851..c67f9bd7699c5a1d210f214fd54aeea6944ccecb 100644 (file)
@@ -123,13 +123,15 @@ void __inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk,
        /*
         * Step 2: Hash TW into tcp ehash chain.
         * Notes :
-        * - tw_refcnt is set to 3 because :
+        * - tw_refcnt is set to 4 because :
         * - We have one reference from bhash chain.
         * - We have one reference from ehash chain.
+        * - We have one reference from timer.
+        * - One reference for ourself (our caller will release it).
         * We can use atomic_set() because prior spin_lock()/spin_unlock()
         * committed into memory all tw fields.
         */
-       atomic_set(&tw->tw_refcnt, 1 + 1 + 1);
+       atomic_set(&tw->tw_refcnt, 4);
        inet_twsk_add_node_rcu(tw, &ehead->chain);
 
        /* Step 3: Remove SK from hash chain */
@@ -217,7 +219,7 @@ void inet_twsk_deschedule_put(struct inet_timewait_sock *tw)
 }
 EXPORT_SYMBOL(inet_twsk_deschedule_put);
 
-void inet_twsk_schedule(struct inet_timewait_sock *tw, const int timeo)
+void __inet_twsk_schedule(struct inet_timewait_sock *tw, int timeo, bool rearm)
 {
        /* timeout := RTO * 3.5
         *
@@ -245,12 +247,14 @@ void inet_twsk_schedule(struct inet_timewait_sock *tw, const int timeo)
         */
 
        tw->tw_kill = timeo <= 4*HZ;
-       if (!mod_timer_pinned(&tw->tw_timer, jiffies + timeo)) {
-               atomic_inc(&tw->tw_refcnt);
+       if (!rearm) {
+               BUG_ON(mod_timer_pinned(&tw->tw_timer, jiffies + timeo));
                atomic_inc(&tw->tw_dr->tw_count);
+       } else {
+               mod_timer_pending(&tw->tw_timer, jiffies + timeo);
        }
 }
-EXPORT_SYMBOL_GPL(inet_twsk_schedule);
+EXPORT_SYMBOL_GPL(__inet_twsk_schedule);
 
 void inet_twsk_purge(struct inet_hashinfo *hashinfo,
                     struct inet_timewait_death_row *twdr, int family)
index bd0679d90519b170dc98369e9b438e4c31b152b9..614521437e30159c5234e9b24fcc41bad7ea6c6b 100644 (file)
@@ -498,10 +498,26 @@ static struct sk_buff *gre_handle_offloads(struct sk_buff *skb,
                                        csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE);
 }
 
+static struct rtable *gre_get_rt(struct sk_buff *skb,
+                                struct net_device *dev,
+                                struct flowi4 *fl,
+                                const struct ip_tunnel_key *key)
+{
+       struct net *net = dev_net(dev);
+
+       memset(fl, 0, sizeof(*fl));
+       fl->daddr = key->u.ipv4.dst;
+       fl->saddr = key->u.ipv4.src;
+       fl->flowi4_tos = RT_TOS(key->tos);
+       fl->flowi4_mark = skb->mark;
+       fl->flowi4_proto = IPPROTO_GRE;
+
+       return ip_route_output_key(net, fl);
+}
+
 static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct ip_tunnel_info *tun_info;
-       struct net *net = dev_net(dev);
        const struct ip_tunnel_key *key;
        struct flowi4 fl;
        struct rtable *rt;
@@ -516,14 +532,7 @@ static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev)
                goto err_free_skb;
 
        key = &tun_info->key;
-       memset(&fl, 0, sizeof(fl));
-       fl.daddr = key->u.ipv4.dst;
-       fl.saddr = key->u.ipv4.src;
-       fl.flowi4_tos = RT_TOS(key->tos);
-       fl.flowi4_mark = skb->mark;
-       fl.flowi4_proto = IPPROTO_GRE;
-
-       rt = ip_route_output_key(net, &fl);
+       rt = gre_get_rt(skb, dev, &fl, key);
        if (IS_ERR(rt))
                goto err_free_skb;
 
@@ -566,6 +575,24 @@ err_free_skb:
        dev->stats.tx_dropped++;
 }
 
+static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
+{
+       struct ip_tunnel_info *info = skb_tunnel_info(skb);
+       struct rtable *rt;
+       struct flowi4 fl4;
+
+       if (ip_tunnel_info_af(info) != AF_INET)
+               return -EINVAL;
+
+       rt = gre_get_rt(skb, dev, &fl4, &info->key);
+       if (IS_ERR(rt))
+               return PTR_ERR(rt);
+
+       ip_rt_put(rt);
+       info->key.u.ipv4.src = fl4.saddr;
+       return 0;
+}
+
 static netdev_tx_t ipgre_xmit(struct sk_buff *skb,
                              struct net_device *dev)
 {
@@ -1023,6 +1050,7 @@ static const struct net_device_ops gre_tap_netdev_ops = {
        .ndo_change_mtu         = ip_tunnel_change_mtu,
        .ndo_get_stats64        = ip_tunnel_get_stats64,
        .ndo_get_iflink         = ip_tunnel_get_iflink,
+       .ndo_fill_metadata_dst  = gre_fill_metadata_dst,
 };
 
 static void ipgre_tap_setup(struct net_device *dev)
index 29ed6c5a5185402eac38b1377e7a968828b6c65d..84dce6a92f93bec35158b392477c536d6f2f1529 100644 (file)
 #include <net/net_namespace.h>
 #include <net/netns/generic.h>
 #include <net/rtnetlink.h>
+#include <net/dst_metadata.h>
 
 int iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb,
                  __be32 src, __be32 dst, __u8 proto,
                  __u8 tos, __u8 ttl, __be16 df, bool xnet)
 {
-       int pkt_len = skb->len;
+       int pkt_len = skb->len - skb_inner_network_offset(skb);
        struct iphdr *iph;
        int err;
 
@@ -119,6 +120,33 @@ int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto)
 }
 EXPORT_SYMBOL_GPL(iptunnel_pull_header);
 
+struct metadata_dst *iptunnel_metadata_reply(struct metadata_dst *md,
+                                            gfp_t flags)
+{
+       struct metadata_dst *res;
+       struct ip_tunnel_info *dst, *src;
+
+       if (!md || md->u.tun_info.mode & IP_TUNNEL_INFO_TX)
+               return NULL;
+
+       res = metadata_dst_alloc(0, flags);
+       if (!res)
+               return NULL;
+
+       dst = &res->u.tun_info;
+       src = &md->u.tun_info;
+       dst->key.tun_id = src->key.tun_id;
+       if (src->mode & IP_TUNNEL_INFO_IPV6)
+               memcpy(&dst->key.u.ipv6.dst, &src->key.u.ipv6.src,
+                      sizeof(struct in6_addr));
+       else
+               dst->key.u.ipv4.dst = src->key.u.ipv4.src;
+       dst->mode = src->mode | IP_TUNNEL_INFO_TX;
+
+       return res;
+}
+EXPORT_SYMBOL_GPL(iptunnel_metadata_reply);
+
 struct sk_buff *iptunnel_handle_offloads(struct sk_buff *skb,
                                         bool csum_help,
                                         int gso_type_mask)
@@ -198,8 +226,6 @@ static const struct nla_policy ip_tun_policy[LWTUNNEL_IP_MAX + 1] = {
        [LWTUNNEL_IP_SRC]       = { .type = NLA_U32 },
        [LWTUNNEL_IP_TTL]       = { .type = NLA_U8 },
        [LWTUNNEL_IP_TOS]       = { .type = NLA_U8 },
-       [LWTUNNEL_IP_SPORT]     = { .type = NLA_U16 },
-       [LWTUNNEL_IP_DPORT]     = { .type = NLA_U16 },
        [LWTUNNEL_IP_FLAGS]     = { .type = NLA_U16 },
 };
 
@@ -239,12 +265,6 @@ static int ip_tun_build_state(struct net_device *dev, struct nlattr *attr,
        if (tb[LWTUNNEL_IP_TOS])
                tun_info->key.tos = nla_get_u8(tb[LWTUNNEL_IP_TOS]);
 
-       if (tb[LWTUNNEL_IP_SPORT])
-               tun_info->key.tp_src = nla_get_be16(tb[LWTUNNEL_IP_SPORT]);
-
-       if (tb[LWTUNNEL_IP_DPORT])
-               tun_info->key.tp_dst = nla_get_be16(tb[LWTUNNEL_IP_DPORT]);
-
        if (tb[LWTUNNEL_IP_FLAGS])
                tun_info->key.tun_flags = nla_get_u16(tb[LWTUNNEL_IP_FLAGS]);
 
@@ -266,8 +286,6 @@ static int ip_tun_fill_encap_info(struct sk_buff *skb,
            nla_put_be32(skb, LWTUNNEL_IP_SRC, tun_info->key.u.ipv4.src) ||
            nla_put_u8(skb, LWTUNNEL_IP_TOS, tun_info->key.tos) ||
            nla_put_u8(skb, LWTUNNEL_IP_TTL, tun_info->key.ttl) ||
-           nla_put_u16(skb, LWTUNNEL_IP_SPORT, tun_info->key.tp_src) ||
-           nla_put_u16(skb, LWTUNNEL_IP_DPORT, tun_info->key.tp_dst) ||
            nla_put_u16(skb, LWTUNNEL_IP_FLAGS, tun_info->key.tun_flags))
                return -ENOMEM;
 
@@ -281,8 +299,6 @@ static int ip_tun_encap_nlsize(struct lwtunnel_state *lwtstate)
                + nla_total_size(4)     /* LWTUNNEL_IP_SRC */
                + nla_total_size(1)     /* LWTUNNEL_IP_TOS */
                + nla_total_size(1)     /* LWTUNNEL_IP_TTL */
-               + nla_total_size(2)     /* LWTUNNEL_IP_SPORT */
-               + nla_total_size(2)     /* LWTUNNEL_IP_DPORT */
                + nla_total_size(2);    /* LWTUNNEL_IP_FLAGS */
 }
 
@@ -305,8 +321,6 @@ static const struct nla_policy ip6_tun_policy[LWTUNNEL_IP6_MAX + 1] = {
        [LWTUNNEL_IP6_SRC]              = { .len = sizeof(struct in6_addr) },
        [LWTUNNEL_IP6_HOPLIMIT]         = { .type = NLA_U8 },
        [LWTUNNEL_IP6_TC]               = { .type = NLA_U8 },
-       [LWTUNNEL_IP6_SPORT]            = { .type = NLA_U16 },
-       [LWTUNNEL_IP6_DPORT]            = { .type = NLA_U16 },
        [LWTUNNEL_IP6_FLAGS]            = { .type = NLA_U16 },
 };
 
@@ -346,12 +360,6 @@ static int ip6_tun_build_state(struct net_device *dev, struct nlattr *attr,
        if (tb[LWTUNNEL_IP6_TC])
                tun_info->key.tos = nla_get_u8(tb[LWTUNNEL_IP6_TC]);
 
-       if (tb[LWTUNNEL_IP6_SPORT])
-               tun_info->key.tp_src = nla_get_be16(tb[LWTUNNEL_IP6_SPORT]);
-
-       if (tb[LWTUNNEL_IP6_DPORT])
-               tun_info->key.tp_dst = nla_get_be16(tb[LWTUNNEL_IP6_DPORT]);
-
        if (tb[LWTUNNEL_IP6_FLAGS])
                tun_info->key.tun_flags = nla_get_u16(tb[LWTUNNEL_IP6_FLAGS]);
 
@@ -373,8 +381,6 @@ static int ip6_tun_fill_encap_info(struct sk_buff *skb,
            nla_put_in6_addr(skb, LWTUNNEL_IP6_SRC, &tun_info->key.u.ipv6.src) ||
            nla_put_u8(skb, LWTUNNEL_IP6_HOPLIMIT, tun_info->key.tos) ||
            nla_put_u8(skb, LWTUNNEL_IP6_TC, tun_info->key.ttl) ||
-           nla_put_u16(skb, LWTUNNEL_IP6_SPORT, tun_info->key.tp_src) ||
-           nla_put_u16(skb, LWTUNNEL_IP6_DPORT, tun_info->key.tp_dst) ||
            nla_put_u16(skb, LWTUNNEL_IP6_FLAGS, tun_info->key.tun_flags))
                return -ENOMEM;
 
@@ -388,8 +394,6 @@ static int ip6_tun_encap_nlsize(struct lwtunnel_state *lwtstate)
                + nla_total_size(16)    /* LWTUNNEL_IP6_SRC */
                + nla_total_size(1)     /* LWTUNNEL_IP6_HOPLIMIT */
                + nla_total_size(1)     /* LWTUNNEL_IP6_TC */
-               + nla_total_size(2)     /* LWTUNNEL_IP6_SPORT */
-               + nla_total_size(2)     /* LWTUNNEL_IP6_DPORT */
                + nla_total_size(2);    /* LWTUNNEL_IP6_FLAGS */
 }
 
index 690d27d3f2f90d99612de8ed4a32dec0596a680a..a3558417653567ffe3a83d06515fb1b68ec36dcf 100644 (file)
@@ -75,6 +75,7 @@ endif # NF_TABLES
 
 config NF_DUP_IPV4
        tristate "Netfilter IPv4 packet duplication to alternate destination"
+       depends on !NF_CONNTRACK || NF_CONNTRACK
        help
          This option enables the nf_dup_ipv4 core, which duplicates an IPv4
          packet to be rerouted to another destination.
index 8618fd150c965015ca2ee256499add4186f4810a..c4ffc9de165420f5839006ec053859aff77147fe 100644 (file)
@@ -61,9 +61,7 @@ static bool rpfilter_lookup_reverse(struct flowi4 *fl4,
        if (FIB_RES_DEV(res) == dev)
                dev_match = true;
 #endif
-       if (dev_match || flags & XT_RPFILTER_LOOSE)
-               return FIB_RES_NH(res).nh_scope <= RT_SCOPE_HOST;
-       return dev_match;
+       return dev_match || flags & XT_RPFILTER_LOOSE;
 }
 
 static bool rpfilter_is_local(const struct sk_buff *skb)
index 5f4a5565ad8b32ef7d10619364a86713d52f38e0..c81deb85acb4da84480f2f54555f4d7cdcbbb209 100644 (file)
@@ -1737,6 +1737,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
        fl4.flowi4_mark = skb->mark;
        fl4.flowi4_tos = tos;
        fl4.flowi4_scope = RT_SCOPE_UNIVERSE;
+       fl4.flowi4_flags = 0;
        fl4.daddr = daddr;
        fl4.saddr = saddr;
        err = fib_lookup(net, &fl4, &res, 0);
@@ -2045,6 +2046,7 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
        struct fib_result res;
        struct rtable *rth;
        int orig_oif;
+       int err = -ENETUNREACH;
 
        res.tclassid    = 0;
        res.fi          = NULL;
@@ -2153,7 +2155,8 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
                goto make_route;
        }
 
-       if (fib_lookup(net, fl4, &res, 0)) {
+       err = fib_lookup(net, fl4, &res, 0);
+       if (err) {
                res.fi = NULL;
                res.table = NULL;
                if (fl4->flowi4_oif) {
@@ -2181,7 +2184,7 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
                        res.type = RTN_UNICAST;
                        goto make_route;
                }
-               rth = ERR_PTR(-ENETUNREACH);
+               rth = ERR_PTR(err);
                goto out;
        }
 
index c6ded6b2a79fb5d8ece3f3b4b1ed0e01707124c3..448c2615fece946d7b5cc3136941efff92a2edd9 100644 (file)
@@ -154,14 +154,20 @@ static void bictcp_init(struct sock *sk)
 static void bictcp_cwnd_event(struct sock *sk, enum tcp_ca_event event)
 {
        if (event == CA_EVENT_TX_START) {
-               s32 delta = tcp_time_stamp - tcp_sk(sk)->lsndtime;
                struct bictcp *ca = inet_csk_ca(sk);
+               u32 now = tcp_time_stamp;
+               s32 delta;
+
+               delta = now - tcp_sk(sk)->lsndtime;
 
                /* We were application limited (idle) for a while.
                 * Shift epoch_start to keep cwnd growth to cubic curve.
                 */
-               if (ca->epoch_start && delta > 0)
+               if (ca->epoch_start && delta > 0) {
                        ca->epoch_start += delta;
+                       if (after(ca->epoch_start, now))
+                               ca->epoch_start = now;
+               }
                return;
        }
 }
index 7092a61c4dc8465fcf17ff71b289cf25bbb8b559..7e538f71f5fbae087c3e3e4367d60e08cd609ac5 100644 (file)
@@ -209,7 +209,7 @@ static void dctcp_update_alpha(struct sock *sk, u32 flags)
 
                /* alpha = (1 - g) * alpha + g * F */
 
-               alpha -= alpha >> dctcp_shift_g;
+               alpha -= min_not_zero(alpha, alpha >> dctcp_shift_g);
                if (bytes_ecn) {
                        /* If dctcp_shift_g == 1, a 32bit value would overflow
                         * after 8 Mbytes.
index 6d8795b066aca708df47de3c9211f36bee5eb1d4..def765911ff85dfefd2c73c41b6585b33c77bcea 100644 (file)
@@ -162,9 +162,9 @@ kill_with_rst:
                if (tcp_death_row.sysctl_tw_recycle &&
                    tcptw->tw_ts_recent_stamp &&
                    tcp_tw_remember_stamp(tw))
-                       inet_twsk_schedule(tw, tw->tw_timeout);
+                       inet_twsk_reschedule(tw, tw->tw_timeout);
                else
-                       inet_twsk_schedule(tw, TCP_TIMEWAIT_LEN);
+                       inet_twsk_reschedule(tw, TCP_TIMEWAIT_LEN);
                return TCP_TW_ACK;
        }
 
@@ -201,7 +201,7 @@ kill:
                                return TCP_TW_SUCCESS;
                        }
                }
-               inet_twsk_schedule(tw, TCP_TIMEWAIT_LEN);
+               inet_twsk_reschedule(tw, TCP_TIMEWAIT_LEN);
 
                if (tmp_opt.saw_tstamp) {
                        tcptw->tw_ts_recent       = tmp_opt.rcv_tsval;
@@ -251,7 +251,7 @@ kill:
                 * Do not reschedule in the last case.
                 */
                if (paws_reject || th->ack)
-                       inet_twsk_schedule(tw, TCP_TIMEWAIT_LEN);
+                       inet_twsk_reschedule(tw, TCP_TIMEWAIT_LEN);
 
                return tcp_timewait_check_oow_rate_limit(
                        tw, skb, LINUX_MIB_TCPACKSKIPPEDTIMEWAIT);
@@ -322,9 +322,6 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
                } while (0);
 #endif
 
-               /* Linkage updates. */
-               __inet_twsk_hashdance(tw, sk, &tcp_hashinfo);
-
                /* Get the TIME_WAIT timeout firing. */
                if (timeo < rto)
                        timeo = rto;
@@ -338,6 +335,8 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
                }
 
                inet_twsk_schedule(tw, timeo);
+               /* Linkage updates. */
+               __inet_twsk_hashdance(tw, sk, &tcp_hashinfo);
                inet_twsk_put(tw);
        } else {
                /* Sorry, if we're out of memory, just CLOSE this
index f9a8a12b62ee64d954ae9a4aab75bcdce687650b..3dbee0d83b15b0cbd2a1008cab5eeb8f9365c878 100644 (file)
@@ -2897,6 +2897,7 @@ void tcp_send_active_reset(struct sock *sk, gfp_t priority)
        skb_reserve(skb, MAX_TCP_HEADER);
        tcp_init_nondata_skb(skb, tcp_acceptable_seq(sk),
                             TCPHDR_ACK | TCPHDR_RST);
+       skb_mstamp_get(&skb->skb_mstamp);
        /* Send it off. */
        if (tcp_transmit_skb(sk, skb, 0, priority))
                NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPABORTFAILED);
@@ -3404,7 +3405,7 @@ static int tcp_xmit_probe_skb(struct sock *sk, int urgent, int mib)
         */
        tcp_init_nondata_skb(skb, tp->snd_una - !urgent, TCPHDR_ACK);
        skb_mstamp_get(&skb->skb_mstamp);
-       NET_INC_STATS_BH(sock_net(sk), mib);
+       NET_INC_STATS(sock_net(sk), mib);
        return tcp_transmit_skb(sk, skb, 0, GFP_ATOMIC);
 }
 
index c0a15e7f359fe54e4edcffca5d59acb418dad116..f7d1d5e19e955563178fcddb84c4ffe9abb66036 100644 (file)
@@ -1024,7 +1024,8 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
                if (netif_index_is_vrf(net, ipc.oif)) {
                        flowi4_init_output(fl4, ipc.oif, sk->sk_mark, tos,
                                           RT_SCOPE_UNIVERSE, sk->sk_protocol,
-                                          (flow_flags | FLOWI_FLAG_VRFSRC),
+                                          (flow_flags | FLOWI_FLAG_VRFSRC |
+                                           FLOWI_FLAG_SKIP_NH_OIF),
                                           faddr, saddr, dport,
                                           inet->inet_sport);
 
index 2878dbfffeb7e769a32079f1a6b80061136a7efc..41a261355662eb42fae031fdd30132767469f98e 100644 (file)
@@ -30,6 +30,8 @@ static int xfrm4_tunnel_check_size(struct sk_buff *skb)
 
        mtu = dst_mtu(skb_dst(skb));
        if (skb->len > mtu) {
+               skb->protocol = htons(ETH_P_IP);
+
                if (skb->sk)
                        xfrm_local_error(skb, mtu);
                else
index bb919b28619fbfd7689d5479ca267ce03db89d71..c10a9ee684337782fa96b71302c0f05695711f36 100644 (file)
@@ -33,6 +33,8 @@ static struct dst_entry *__xfrm4_dst_lookup(struct net *net, struct flowi4 *fl4,
        if (saddr)
                fl4->saddr = saddr->a4;
 
+       fl4->flowi4_flags = FLOWI_FLAG_SKIP_NH_OIF;
+
        rt = __ip_route_output_key(net, fl4);
        if (!IS_ERR(rt))
                return &rt->dst;
index 030fefdc9aed8cedbf8ba9e26864de0aca89236a..36b85bd05ac8a320b1b910c7d3454da1139ecd3c 100644 (file)
@@ -3119,6 +3119,8 @@ static void addrconf_gre_config(struct net_device *dev)
        }
 
        addrconf_addr_gen(idev, true);
+       if (dev->flags & IFF_POINTOPOINT)
+               addrconf_add_mroute(dev);
 }
 #endif
 
@@ -5127,13 +5129,12 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
 
                        rt = addrconf_get_prefix_route(&ifp->peer_addr, 128,
                                                       ifp->idev->dev, 0, 0);
-                       if (rt && ip6_del_rt(rt))
-                               dst_free(&rt->dst);
+                       if (rt)
+                               ip6_del_rt(rt);
                }
                dst_hold(&ifp->rt->dst);
 
-               if (ip6_del_rt(ifp->rt))
-                       dst_free(&ifp->rt->dst);
+               ip6_del_rt(ifp->rt);
 
                rt_genid_bump_ipv6(net);
                break;
index 9f777ec59a59d24566d87643889a8c591dd52637..ed33abf57abd7d7ec71685a7180cf88ec132626c 100644 (file)
@@ -32,6 +32,7 @@ struct fib6_rule {
 struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
                                   int flags, pol_lookup_t lookup)
 {
+       struct rt6_info *rt;
        struct fib_lookup_arg arg = {
                .lookup_ptr = lookup,
                .flags = FIB_LOOKUP_NOREF,
@@ -40,11 +41,21 @@ struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
        fib_rules_lookup(net->ipv6.fib6_rules_ops,
                         flowi6_to_flowi(fl6), flags, &arg);
 
-       if (arg.result)
-               return arg.result;
+       rt = arg.result;
 
-       dst_hold(&net->ipv6.ip6_null_entry->dst);
-       return &net->ipv6.ip6_null_entry->dst;
+       if (!rt) {
+               dst_hold(&net->ipv6.ip6_null_entry->dst);
+               return &net->ipv6.ip6_null_entry->dst;
+       }
+
+       if (rt->rt6i_flags & RTF_REJECT &&
+           rt->dst.error == -EAGAIN) {
+               ip6_rt_put(rt);
+               rt = net->ipv6.ip6_null_entry;
+               dst_hold(&rt->dst);
+       }
+
+       return &rt->dst;
 }
 
 static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
index 418d9823692b6e78077d44c1ed8b15e998e2316b..6cedc62b2abb1c3520647b4046c1f027ffe1295b 100644 (file)
@@ -155,6 +155,11 @@ static void node_free(struct fib6_node *fn)
        kmem_cache_free(fib6_node_kmem, fn);
 }
 
+static void rt6_rcu_free(struct rt6_info *rt)
+{
+       call_rcu(&rt->dst.rcu_head, dst_rcu_free);
+}
+
 static void rt6_free_pcpu(struct rt6_info *non_pcpu_rt)
 {
        int cpu;
@@ -169,7 +174,7 @@ static void rt6_free_pcpu(struct rt6_info *non_pcpu_rt)
                ppcpu_rt = per_cpu_ptr(non_pcpu_rt->rt6i_pcpu, cpu);
                pcpu_rt = *ppcpu_rt;
                if (pcpu_rt) {
-                       dst_free(&pcpu_rt->dst);
+                       rt6_rcu_free(pcpu_rt);
                        *ppcpu_rt = NULL;
                }
        }
@@ -181,7 +186,7 @@ static void rt6_release(struct rt6_info *rt)
 {
        if (atomic_dec_and_test(&rt->rt6i_ref)) {
                rt6_free_pcpu(rt);
-               dst_free(&rt->dst);
+               rt6_rcu_free(rt);
        }
 }
 
@@ -280,7 +285,17 @@ struct fib6_table *fib6_get_table(struct net *net, u32 id)
 struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
                                   int flags, pol_lookup_t lookup)
 {
-       return (struct dst_entry *) lookup(net, net->ipv6.fib6_main_tbl, fl6, flags);
+       struct rt6_info *rt;
+
+       rt = lookup(net, net->ipv6.fib6_main_tbl, fl6, flags);
+       if (rt->rt6i_flags & RTF_REJECT &&
+           rt->dst.error == -EAGAIN) {
+               ip6_rt_put(rt);
+               rt = net->ipv6.ip6_null_entry;
+               dst_hold(&rt->dst);
+       }
+
+       return &rt->dst;
 }
 
 static void __net_init fib6_tables_init(struct net *net)
@@ -846,7 +861,7 @@ add:
                *ins = rt;
                rt->rt6i_node = fn;
                atomic_inc(&rt->rt6i_ref);
-               inet6_rt_notify(RTM_NEWROUTE, rt, info);
+               inet6_rt_notify(RTM_NEWROUTE, rt, info, 0);
                info->nl_net->ipv6.rt6_stats->fib_rt_entries++;
 
                if (!(fn->fn_flags & RTN_RTINFO)) {
@@ -872,7 +887,7 @@ add:
                rt->rt6i_node = fn;
                rt->dst.rt6_next = iter->dst.rt6_next;
                atomic_inc(&rt->rt6i_ref);
-               inet6_rt_notify(RTM_NEWROUTE, rt, info);
+               inet6_rt_notify(RTM_NEWROUTE, rt, info, NLM_F_REPLACE);
                if (!(fn->fn_flags & RTN_RTINFO)) {
                        info->nl_net->ipv6.rt6_stats->fib_route_nodes++;
                        fn->fn_flags |= RTN_RTINFO;
@@ -933,6 +948,10 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt,
        int replace_required = 0;
        int sernum = fib6_new_sernum(info->nl_net);
 
+       if (WARN_ON_ONCE((rt->dst.flags & DST_NOCACHE) &&
+                        !atomic_read(&rt->dst.__refcnt)))
+               return -EINVAL;
+
        if (info->nlh) {
                if (!(info->nlh->nlmsg_flags & NLM_F_CREATE))
                        allow_create = 0;
@@ -1025,6 +1044,7 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt,
                fib6_start_gc(info->nl_net, rt);
                if (!(rt->rt6i_flags & RTF_CACHE))
                        fib6_prune_clones(info->nl_net, pn);
+               rt->dst.flags &= ~DST_NOCACHE;
        }
 
 out:
@@ -1049,7 +1069,8 @@ out:
                        atomic_inc(&pn->leaf->rt6i_ref);
                }
 #endif
-               dst_free(&rt->dst);
+               if (!(rt->dst.flags & DST_NOCACHE))
+                       dst_free(&rt->dst);
        }
        return err;
 
@@ -1060,7 +1081,8 @@ out:
 st_failure:
        if (fn && !(fn->fn_flags & (RTN_RTINFO|RTN_ROOT)))
                fib6_repair_tree(info->nl_net, fn);
-       dst_free(&rt->dst);
+       if (!(rt->dst.flags & DST_NOCACHE))
+               dst_free(&rt->dst);
        return err;
 #endif
 }
@@ -1410,7 +1432,7 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp,
 
        fib6_purge_rt(rt, fn, net);
 
-       inet6_rt_notify(RTM_DELROUTE, rt, info);
+       inet6_rt_notify(RTM_DELROUTE, rt, info, 0);
        rt6_release(rt);
 }
 
index 4038c694ec03e7bf782a5db9d34e65d5cad560d2..3c7b9310b33fdb052e2b97d4cd502482524b4dd8 100644 (file)
@@ -404,13 +404,13 @@ static void ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                struct ipv6_tlv_tnl_enc_lim *tel;
                __u32 mtu;
        case ICMPV6_DEST_UNREACH:
-               net_warn_ratelimited("%s: Path to destination invalid or inactive!\n",
-                                    t->parms.name);
+               net_dbg_ratelimited("%s: Path to destination invalid or inactive!\n",
+                                   t->parms.name);
                break;
        case ICMPV6_TIME_EXCEED:
                if (code == ICMPV6_EXC_HOPLIMIT) {
-                       net_warn_ratelimited("%s: Too small hop limit or routing loop in tunnel!\n",
-                                            t->parms.name);
+                       net_dbg_ratelimited("%s: Too small hop limit or routing loop in tunnel!\n",
+                                           t->parms.name);
                }
                break;
        case ICMPV6_PARAMPROB:
@@ -421,12 +421,12 @@ static void ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                if (teli && teli == be32_to_cpu(info) - 2) {
                        tel = (struct ipv6_tlv_tnl_enc_lim *) &skb->data[teli];
                        if (tel->encap_limit == 0) {
-                               net_warn_ratelimited("%s: Too small encapsulation limit or routing loop in tunnel!\n",
-                                                    t->parms.name);
+                               net_dbg_ratelimited("%s: Too small encapsulation limit or routing loop in tunnel!\n",
+                                                   t->parms.name);
                        }
                } else {
-                       net_warn_ratelimited("%s: Recipient unable to parse tunneled packet!\n",
-                                            t->parms.name);
+                       net_dbg_ratelimited("%s: Recipient unable to parse tunneled packet!\n",
+                                           t->parms.name);
                }
                break;
        case ICMPV6_PKT_TOOBIG:
@@ -634,20 +634,20 @@ static netdev_tx_t ip6gre_xmit2(struct sk_buff *skb,
        }
 
        if (!fl6->flowi6_mark)
-               dst = ip6_tnl_dst_check(tunnel);
+               dst = ip6_tnl_dst_get(tunnel);
 
        if (!dst) {
-               ndst = ip6_route_output(net, NULL, fl6);
+               dst = ip6_route_output(net, NULL, fl6);
 
-               if (ndst->error)
+               if (dst->error)
                        goto tx_err_link_failure;
-               ndst = xfrm_lookup(net, ndst, flowi6_to_flowi(fl6), NULL, 0);
-               if (IS_ERR(ndst)) {
-                       err = PTR_ERR(ndst);
-                       ndst = NULL;
+               dst = xfrm_lookup(net, dst, flowi6_to_flowi(fl6), NULL, 0);
+               if (IS_ERR(dst)) {
+                       err = PTR_ERR(dst);
+                       dst = NULL;
                        goto tx_err_link_failure;
                }
-               dst = ndst;
+               ndst = dst;
        }
 
        tdev = dst->dev;
@@ -702,12 +702,9 @@ static netdev_tx_t ip6gre_xmit2(struct sk_buff *skb,
                skb = new_skb;
        }
 
-       if (fl6->flowi6_mark) {
-               skb_dst_set(skb, dst);
-               ndst = NULL;
-       } else {
-               skb_dst_set_noref(skb, dst);
-       }
+       if (!fl6->flowi6_mark && ndst)
+               ip6_tnl_dst_set(tunnel, ndst);
+       skb_dst_set(skb, dst);
 
        proto = NEXTHDR_GRE;
        if (encap_limit >= 0) {
@@ -762,14 +759,12 @@ static netdev_tx_t ip6gre_xmit2(struct sk_buff *skb,
        skb_set_inner_protocol(skb, protocol);
 
        ip6tunnel_xmit(NULL, skb, dev);
-       if (ndst)
-               ip6_tnl_dst_store(tunnel, ndst);
        return 0;
 tx_err_link_failure:
        stats->tx_carrier_errors++;
        dst_link_failure(skb);
 tx_err_dst_release:
-       dst_release(ndst);
+       dst_release(dst);
        return err;
 }
 
@@ -1223,6 +1218,9 @@ static const struct net_device_ops ip6gre_netdev_ops = {
 
 static void ip6gre_dev_free(struct net_device *dev)
 {
+       struct ip6_tnl *t = netdev_priv(dev);
+
+       ip6_tnl_dst_destroy(t);
        free_percpu(dev->tstats);
        free_netdev(dev);
 }
@@ -1245,9 +1243,10 @@ static void ip6gre_tunnel_setup(struct net_device *dev)
        netif_keep_dst(dev);
 }
 
-static int ip6gre_tunnel_init(struct net_device *dev)
+static int ip6gre_tunnel_init_common(struct net_device *dev)
 {
        struct ip6_tnl *tunnel;
+       int ret;
 
        tunnel = netdev_priv(dev);
 
@@ -1255,16 +1254,37 @@ static int ip6gre_tunnel_init(struct net_device *dev)
        tunnel->net = dev_net(dev);
        strcpy(tunnel->parms.name, dev->name);
 
+       dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
+       if (!dev->tstats)
+               return -ENOMEM;
+
+       ret = ip6_tnl_dst_init(tunnel);
+       if (ret) {
+               free_percpu(dev->tstats);
+               dev->tstats = NULL;
+               return ret;
+       }
+
+       return 0;
+}
+
+static int ip6gre_tunnel_init(struct net_device *dev)
+{
+       struct ip6_tnl *tunnel;
+       int ret;
+
+       ret = ip6gre_tunnel_init_common(dev);
+       if (ret)
+               return ret;
+
+       tunnel = netdev_priv(dev);
+
        memcpy(dev->dev_addr, &tunnel->parms.laddr, sizeof(struct in6_addr));
        memcpy(dev->broadcast, &tunnel->parms.raddr, sizeof(struct in6_addr));
 
        if (ipv6_addr_any(&tunnel->parms.raddr))
                dev->header_ops = &ip6gre_header_ops;
 
-       dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
-       if (!dev->tstats)
-               return -ENOMEM;
-
        return 0;
 }
 
@@ -1460,19 +1480,16 @@ static void ip6gre_netlink_parms(struct nlattr *data[],
 static int ip6gre_tap_init(struct net_device *dev)
 {
        struct ip6_tnl *tunnel;
+       int ret;
 
-       tunnel = netdev_priv(dev);
+       ret = ip6gre_tunnel_init_common(dev);
+       if (ret)
+               return ret;
 
-       tunnel->dev = dev;
-       tunnel->net = dev_net(dev);
-       strcpy(tunnel->parms.name, dev->name);
+       tunnel = netdev_priv(dev);
 
        ip6gre_tnl_link_config(tunnel, 1);
 
-       dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
-       if (!dev->tstats)
-               return -ENOMEM;
-
        return 0;
 }
 
index 26ea4793074004d0af1026bb378860b53baa0ad2..f84ec4e9b2de7653d1ad8b2348977418827676c2 100644 (file)
@@ -376,6 +376,9 @@ int ip6_forward(struct sk_buff *skb)
        if (skb->pkt_type != PACKET_HOST)
                goto drop;
 
+       if (unlikely(skb->sk))
+               goto drop;
+
        if (skb_warn_if_lro(skb))
                goto drop;
 
@@ -581,25 +584,29 @@ int ip6_fragment(struct sock *sk, struct sk_buff *skb,
                if (np->frag_size)
                        mtu = np->frag_size;
        }
+       if (mtu < hlen + sizeof(struct frag_hdr) + 8)
+               goto fail_toobig;
        mtu -= hlen + sizeof(struct frag_hdr);
 
        frag_id = ipv6_select_ident(net, &ipv6_hdr(skb)->daddr,
                                    &ipv6_hdr(skb)->saddr);
 
+       hroom = LL_RESERVED_SPACE(rt->dst.dev);
        if (skb_has_frag_list(skb)) {
                int first_len = skb_pagelen(skb);
                struct sk_buff *frag2;
 
                if (first_len - hlen > mtu ||
                    ((first_len - hlen) & 7) ||
-                   skb_cloned(skb))
+                   skb_cloned(skb) ||
+                   skb_headroom(skb) < (hroom + sizeof(struct frag_hdr)))
                        goto slow_path;
 
                skb_walk_frags(skb, frag) {
                        /* Correct geometry. */
                        if (frag->len > mtu ||
                            ((frag->len & 7) && frag->next) ||
-                           skb_headroom(frag) < hlen)
+                           skb_headroom(frag) < (hlen + hroom + sizeof(struct frag_hdr)))
                                goto slow_path_clean;
 
                        /* Partially cloned skb? */
@@ -616,8 +623,6 @@ int ip6_fragment(struct sock *sk, struct sk_buff *skb,
 
                err = 0;
                offset = 0;
-               frag = skb_shinfo(skb)->frag_list;
-               skb_frag_list_init(skb);
                /* BUILD HEADER */
 
                *prevhdr = NEXTHDR_FRAGMENT;
@@ -625,8 +630,11 @@ int ip6_fragment(struct sock *sk, struct sk_buff *skb,
                if (!tmp_hdr) {
                        IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
                                      IPSTATS_MIB_FRAGFAILS);
-                       return -ENOMEM;
+                       err = -ENOMEM;
+                       goto fail;
                }
+               frag = skb_shinfo(skb)->frag_list;
+               skb_frag_list_init(skb);
 
                __skb_pull(skb, hlen);
                fh = (struct frag_hdr *)__skb_push(skb, sizeof(struct frag_hdr));
@@ -723,7 +731,6 @@ slow_path:
         */
 
        *prevhdr = NEXTHDR_FRAGMENT;
-       hroom = LL_RESERVED_SPACE(rt->dst.dev);
        troom = rt->dst.dev->needed_tailroom;
 
        /*
@@ -872,7 +879,8 @@ static struct dst_entry *ip6_sk_dst_check(struct sock *sk,
 #ifdef CONFIG_IPV6_SUBTREES
            ip6_rt_check(&rt->rt6i_src, &fl6->saddr, np->saddr_cache) ||
 #endif
-           (fl6->flowi6_oif && fl6->flowi6_oif != dst->dev->ifindex)) {
+          (!(fl6->flowi6_flags & FLOWI_FLAG_SKIP_NH_OIF) &&
+             (fl6->flowi6_oif && fl6->flowi6_oif != dst->dev->ifindex))) {
                dst_release(dst);
                dst = NULL;
        }
index b0ab420612bcc30efd5e58a30bdfb5e730e88b0e..eabffbb89795d921b0977989345b25d81f553ee0 100644 (file)
@@ -126,36 +126,92 @@ static struct net_device_stats *ip6_get_stats(struct net_device *dev)
  * Locking : hash tables are protected by RCU and RTNL
  */
 
-struct dst_entry *ip6_tnl_dst_check(struct ip6_tnl *t)
+static void ip6_tnl_per_cpu_dst_set(struct ip6_tnl_dst *idst,
+                                   struct dst_entry *dst)
 {
-       struct dst_entry *dst = t->dst_cache;
+       write_seqlock_bh(&idst->lock);
+       dst_release(rcu_dereference_protected(
+                           idst->dst,
+                           lockdep_is_held(&idst->lock.lock)));
+       if (dst) {
+               dst_hold(dst);
+               idst->cookie = rt6_get_cookie((struct rt6_info *)dst);
+       } else {
+               idst->cookie = 0;
+       }
+       rcu_assign_pointer(idst->dst, dst);
+       write_sequnlock_bh(&idst->lock);
+}
+
+struct dst_entry *ip6_tnl_dst_get(struct ip6_tnl *t)
+{
+       struct ip6_tnl_dst *idst;
+       struct dst_entry *dst;
+       unsigned int seq;
+       u32 cookie;
 
-       if (dst && dst->obsolete &&
-           !dst->ops->check(dst, t->dst_cookie)) {
-               t->dst_cache = NULL;
+       idst = raw_cpu_ptr(t->dst_cache);
+
+       rcu_read_lock();
+       do {
+               seq = read_seqbegin(&idst->lock);
+               dst = rcu_dereference(idst->dst);
+               cookie = idst->cookie;
+       } while (read_seqretry(&idst->lock, seq));
+
+       if (dst && !atomic_inc_not_zero(&dst->__refcnt))
+               dst = NULL;
+       rcu_read_unlock();
+
+       if (dst && dst->obsolete && !dst->ops->check(dst, cookie)) {
+               ip6_tnl_per_cpu_dst_set(idst, NULL);
                dst_release(dst);
-               return NULL;
+               dst = NULL;
        }
-
        return dst;
 }
-EXPORT_SYMBOL_GPL(ip6_tnl_dst_check);
+EXPORT_SYMBOL_GPL(ip6_tnl_dst_get);
 
 void ip6_tnl_dst_reset(struct ip6_tnl *t)
 {
-       dst_release(t->dst_cache);
-       t->dst_cache = NULL;
+       int i;
+
+       for_each_possible_cpu(i)
+               ip6_tnl_per_cpu_dst_set(raw_cpu_ptr(t->dst_cache), NULL);
 }
 EXPORT_SYMBOL_GPL(ip6_tnl_dst_reset);
 
-void ip6_tnl_dst_store(struct ip6_tnl *t, struct dst_entry *dst)
+void ip6_tnl_dst_set(struct ip6_tnl *t, struct dst_entry *dst)
+{
+       ip6_tnl_per_cpu_dst_set(raw_cpu_ptr(t->dst_cache), dst);
+
+}
+EXPORT_SYMBOL_GPL(ip6_tnl_dst_set);
+
+void ip6_tnl_dst_destroy(struct ip6_tnl *t)
 {
-       struct rt6_info *rt = (struct rt6_info *) dst;
-       t->dst_cookie = rt6_get_cookie(rt);
-       dst_release(t->dst_cache);
-       t->dst_cache = dst;
+       if (!t->dst_cache)
+               return;
+
+       ip6_tnl_dst_reset(t);
+       free_percpu(t->dst_cache);
 }
-EXPORT_SYMBOL_GPL(ip6_tnl_dst_store);
+EXPORT_SYMBOL_GPL(ip6_tnl_dst_destroy);
+
+int ip6_tnl_dst_init(struct ip6_tnl *t)
+{
+       int i;
+
+       t->dst_cache = alloc_percpu(struct ip6_tnl_dst);
+       if (!t->dst_cache)
+               return -ENOMEM;
+
+       for_each_possible_cpu(i)
+               seqlock_init(&per_cpu_ptr(t->dst_cache, i)->lock);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(ip6_tnl_dst_init);
 
 /**
  * ip6_tnl_lookup - fetch tunnel matching the end-point addresses
@@ -271,6 +327,9 @@ ip6_tnl_unlink(struct ip6_tnl_net *ip6n, struct ip6_tnl *t)
 
 static void ip6_dev_free(struct net_device *dev)
 {
+       struct ip6_tnl *t = netdev_priv(dev);
+
+       ip6_tnl_dst_destroy(t);
        free_percpu(dev->tstats);
        free_netdev(dev);
 }
@@ -510,14 +569,14 @@ ip6_tnl_err(struct sk_buff *skb, __u8 ipproto, struct inet6_skb_parm *opt,
                struct ipv6_tlv_tnl_enc_lim *tel;
                __u32 mtu;
        case ICMPV6_DEST_UNREACH:
-               net_warn_ratelimited("%s: Path to destination invalid or inactive!\n",
-                                    t->parms.name);
+               net_dbg_ratelimited("%s: Path to destination invalid or inactive!\n",
+                                   t->parms.name);
                rel_msg = 1;
                break;
        case ICMPV6_TIME_EXCEED:
                if ((*code) == ICMPV6_EXC_HOPLIMIT) {
-                       net_warn_ratelimited("%s: Too small hop limit or routing loop in tunnel!\n",
-                                            t->parms.name);
+                       net_dbg_ratelimited("%s: Too small hop limit or routing loop in tunnel!\n",
+                                           t->parms.name);
                        rel_msg = 1;
                }
                break;
@@ -529,13 +588,13 @@ ip6_tnl_err(struct sk_buff *skb, __u8 ipproto, struct inet6_skb_parm *opt,
                if (teli && teli == *info - 2) {
                        tel = (struct ipv6_tlv_tnl_enc_lim *) &skb->data[teli];
                        if (tel->encap_limit == 0) {
-                               net_warn_ratelimited("%s: Too small encapsulation limit or routing loop in tunnel!\n",
-                                                    t->parms.name);
+                               net_dbg_ratelimited("%s: Too small encapsulation limit or routing loop in tunnel!\n",
+                                                   t->parms.name);
                                rel_msg = 1;
                        }
                } else {
-                       net_warn_ratelimited("%s: Recipient unable to parse tunneled packet!\n",
-                                            t->parms.name);
+                       net_dbg_ratelimited("%s: Recipient unable to parse tunneled packet!\n",
+                                           t->parms.name);
                }
                break;
        case ICMPV6_PKT_TOOBIG:
@@ -1010,23 +1069,23 @@ static int ip6_tnl_xmit2(struct sk_buff *skb,
                memcpy(&fl6->daddr, addr6, sizeof(fl6->daddr));
                neigh_release(neigh);
        } else if (!fl6->flowi6_mark)
-               dst = ip6_tnl_dst_check(t);
+               dst = ip6_tnl_dst_get(t);
 
        if (!ip6_tnl_xmit_ctl(t, &fl6->saddr, &fl6->daddr))
                goto tx_err_link_failure;
 
        if (!dst) {
-               ndst = ip6_route_output(net, NULL, fl6);
+               dst = ip6_route_output(net, NULL, fl6);
 
-               if (ndst->error)
+               if (dst->error)
                        goto tx_err_link_failure;
-               ndst = xfrm_lookup(net, ndst, flowi6_to_flowi(fl6), NULL, 0);
-               if (IS_ERR(ndst)) {
-                       err = PTR_ERR(ndst);
-                       ndst = NULL;
+               dst = xfrm_lookup(net, dst, flowi6_to_flowi(fl6), NULL, 0);
+               if (IS_ERR(dst)) {
+                       err = PTR_ERR(dst);
+                       dst = NULL;
                        goto tx_err_link_failure;
                }
-               dst = ndst;
+               ndst = dst;
        }
 
        tdev = dst->dev;
@@ -1072,12 +1131,11 @@ static int ip6_tnl_xmit2(struct sk_buff *skb,
                consume_skb(skb);
                skb = new_skb;
        }
-       if (fl6->flowi6_mark) {
-               skb_dst_set(skb, dst);
-               ndst = NULL;
-       } else {
-               skb_dst_set_noref(skb, dst);
-       }
+
+       if (!fl6->flowi6_mark && ndst)
+               ip6_tnl_dst_set(t, ndst);
+       skb_dst_set(skb, dst);
+
        skb->transport_header = skb->network_header;
 
        proto = fl6->flowi6_proto;
@@ -1101,14 +1159,12 @@ static int ip6_tnl_xmit2(struct sk_buff *skb,
        ipv6h->saddr = fl6->saddr;
        ipv6h->daddr = fl6->daddr;
        ip6tunnel_xmit(NULL, skb, dev);
-       if (ndst)
-               ip6_tnl_dst_store(t, ndst);
        return 0;
 tx_err_link_failure:
        stats->tx_carrier_errors++;
        dst_link_failure(skb);
 tx_err_dst_release:
-       dst_release(ndst);
+       dst_release(dst);
        return err;
 }
 
@@ -1573,12 +1629,21 @@ static inline int
 ip6_tnl_dev_init_gen(struct net_device *dev)
 {
        struct ip6_tnl *t = netdev_priv(dev);
+       int ret;
 
        t->dev = dev;
        t->net = dev_net(dev);
        dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
        if (!dev->tstats)
                return -ENOMEM;
+
+       ret = ip6_tnl_dst_init(t);
+       if (ret) {
+               free_percpu(dev->tstats);
+               dev->tstats = NULL;
+               return ret;
+       }
+
        return 0;
 }
 
index 96833e4b31939a191eaf7de297ac438d4aa41fa4..f6a024e141e595541009cb24c172e0c52a8a879f 100644 (file)
@@ -58,6 +58,7 @@ endif # NF_TABLES
 
 config NF_DUP_IPV6
        tristate "Netfilter IPv6 packet duplication to alternate destination"
+       depends on !NF_CONNTRACK || NF_CONNTRACK
        help
          This option enables the nf_dup_ipv6 core, which duplicates an IPv6
          packet to be rerouted to another destination.
index 701cd2bae0a9224d56005f67d8b9f5e71f45825f..c7196ad1d69f8467a6971cf40f1c5ffdd14b4a92 100644 (file)
@@ -646,6 +646,7 @@ void nf_ct_frag6_consume_orig(struct sk_buff *skb)
                s = s2;
        }
 }
+EXPORT_SYMBOL_GPL(nf_ct_frag6_consume_orig);
 
 static int nf_ct_net_init(struct net *net)
 {
index 53617d71518850dfc26220dd15923b8027c5249a..946880ad48acda725eb66f9e2d0a8fd0f2b4ec40 100644 (file)
@@ -142,6 +142,9 @@ static void rt6_uncached_list_flush_dev(struct net *net, struct net_device *dev)
        struct net_device *loopback_dev = net->loopback_dev;
        int cpu;
 
+       if (dev == loopback_dev)
+               return;
+
        for_each_possible_cpu(cpu) {
                struct uncached_list *ul = per_cpu_ptr(&rt6_uncached_list, cpu);
                struct rt6_info *rt;
@@ -151,14 +154,12 @@ static void rt6_uncached_list_flush_dev(struct net *net, struct net_device *dev)
                        struct inet6_dev *rt_idev = rt->rt6i_idev;
                        struct net_device *rt_dev = rt->dst.dev;
 
-                       if (rt_idev && (rt_idev->dev == dev || !dev) &&
-                           rt_idev->dev != loopback_dev) {
+                       if (rt_idev->dev == dev) {
                                rt->rt6i_idev = in6_dev_get(loopback_dev);
                                in6_dev_put(rt_idev);
                        }
 
-                       if (rt_dev && (rt_dev == dev || !dev) &&
-                           rt_dev != loopback_dev) {
+                       if (rt_dev == dev) {
                                rt->dst.dev = loopback_dev;
                                dev_hold(rt->dst.dev);
                                dev_put(rt_dev);
@@ -247,12 +248,6 @@ static void ip6_rt_blackhole_redirect(struct dst_entry *dst, struct sock *sk,
 {
 }
 
-static u32 *ip6_rt_blackhole_cow_metrics(struct dst_entry *dst,
-                                        unsigned long old)
-{
-       return NULL;
-}
-
 static struct dst_ops ip6_dst_blackhole_ops = {
        .family                 =       AF_INET6,
        .destroy                =       ip6_dst_destroy,
@@ -261,7 +256,7 @@ static struct dst_ops ip6_dst_blackhole_ops = {
        .default_advmss         =       ip6_default_advmss,
        .update_pmtu            =       ip6_rt_blackhole_update_pmtu,
        .redirect               =       ip6_rt_blackhole_redirect,
-       .cow_metrics            =       ip6_rt_blackhole_cow_metrics,
+       .cow_metrics            =       dst_cow_metrics_generic,
        .neigh_lookup           =       ip6_neigh_lookup,
 };
 
@@ -318,6 +313,15 @@ static const struct rt6_info ip6_blk_hole_entry_template = {
 
 #endif
 
+static void rt6_info_init(struct rt6_info *rt)
+{
+       struct dst_entry *dst = &rt->dst;
+
+       memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst));
+       INIT_LIST_HEAD(&rt->rt6i_siblings);
+       INIT_LIST_HEAD(&rt->rt6i_uncached);
+}
+
 /* allocate dst with ip6_dst_ops */
 static struct rt6_info *__ip6_dst_alloc(struct net *net,
                                        struct net_device *dev,
@@ -326,13 +330,9 @@ static struct rt6_info *__ip6_dst_alloc(struct net *net,
        struct rt6_info *rt = dst_alloc(&net->ipv6.ip6_dst_ops, dev,
                                        0, DST_OBSOLETE_FORCE_CHK, flags);
 
-       if (rt) {
-               struct dst_entry *dst = &rt->dst;
+       if (rt)
+               rt6_info_init(rt);
 
-               memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst));
-               INIT_LIST_HEAD(&rt->rt6i_siblings);
-               INIT_LIST_HEAD(&rt->rt6i_uncached);
-       }
        return rt;
 }
 
@@ -1068,6 +1068,9 @@ static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
        fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
        saved_fn = fn;
 
+       if (fl6->flowi6_flags & FLOWI_FLAG_SKIP_NH_OIF)
+               oif = 0;
+
 redo_rt6_select:
        rt = rt6_select(fn, oif, strict);
        if (rt->rt6i_nsiblings)
@@ -1190,13 +1193,16 @@ struct dst_entry *ip6_route_output(struct net *net, const struct sock *sk,
                                    struct flowi6 *fl6)
 {
        int flags = 0;
+       bool any_src;
 
        fl6->flowi6_iif = LOOPBACK_IFINDEX;
 
-       if ((sk && sk->sk_bound_dev_if) || rt6_need_strict(&fl6->daddr))
+       any_src = ipv6_addr_any(&fl6->saddr);
+       if ((sk && sk->sk_bound_dev_if) || rt6_need_strict(&fl6->daddr) ||
+           (fl6->flowi6_oif && any_src))
                flags |= RT6_LOOKUP_F_IFACE;
 
-       if (!ipv6_addr_any(&fl6->saddr))
+       if (!any_src)
                flags |= RT6_LOOKUP_F_HAS_SADDR;
        else if (sk)
                flags |= rt6_srcprefs2flags(inet6_sk(sk)->srcprefs);
@@ -1212,24 +1218,20 @@ struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_ori
 
        rt = dst_alloc(&ip6_dst_blackhole_ops, ort->dst.dev, 1, DST_OBSOLETE_NONE, 0);
        if (rt) {
-               new = &rt->dst;
-
-               memset(new + 1, 0, sizeof(*rt) - sizeof(*new));
+               rt6_info_init(rt);
 
+               new = &rt->dst;
                new->__use = 1;
                new->input = dst_discard;
                new->output = dst_discard_sk;
 
-               if (dst_metrics_read_only(&ort->dst))
-                       new->_metrics = ort->dst._metrics;
-               else
-                       dst_copy_metrics(new, &ort->dst);
+               dst_copy_metrics(new, &ort->dst);
                rt->rt6i_idev = ort->rt6i_idev;
                if (rt->rt6i_idev)
                        in6_dev_hold(rt->rt6i_idev);
 
                rt->rt6i_gateway = ort->rt6i_gateway;
-               rt->rt6i_flags = ort->rt6i_flags;
+               rt->rt6i_flags = ort->rt6i_flags & ~RTF_PCPU;
                rt->rt6i_metric = 0;
 
                memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key));
@@ -1322,8 +1324,7 @@ static void ip6_link_failure(struct sk_buff *skb)
        if (rt) {
                if (rt->rt6i_flags & RTF_CACHE) {
                        dst_hold(&rt->dst);
-                       if (ip6_del_rt(rt))
-                               dst_free(&rt->dst);
+                       ip6_del_rt(rt);
                } else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT)) {
                        rt->rt6i_node->fn_sernum = -1;
                }
@@ -1886,9 +1887,11 @@ int ip6_route_info_create(struct fib6_config *cfg, struct rt6_info **rt_ret)
                        rt->dst.input = ip6_pkt_prohibit;
                        break;
                case RTN_THROW:
+               case RTN_UNREACHABLE:
                default:
                        rt->dst.error = (cfg->fc_type == RTN_THROW) ? -EAGAIN
-                                       : -ENETUNREACH;
+                                       : (cfg->fc_type == RTN_UNREACHABLE)
+                                       ? -EHOSTUNREACH : -ENETUNREACH;
                        rt->dst.output = ip6_pkt_discard_out;
                        rt->dst.input = ip6_pkt_discard;
                        break;
@@ -2028,7 +2031,8 @@ static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info)
        struct fib6_table *table;
        struct net *net = dev_net(rt->dst.dev);
 
-       if (rt == net->ipv6.ip6_null_entry) {
+       if (rt == net->ipv6.ip6_null_entry ||
+           rt->dst.flags & DST_NOCACHE) {
                err = -ENOENT;
                goto out;
        }
@@ -2515,6 +2519,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
        rt->rt6i_dst.addr = *addr;
        rt->rt6i_dst.plen = 128;
        rt->rt6i_table = fib6_get_table(net, RT6_TABLE_LOCAL);
+       rt->dst.flags |= DST_NOCACHE;
 
        atomic_set(&rt->dst.__refcnt, 1);
 
@@ -2618,7 +2623,8 @@ void rt6_ifdown(struct net *net, struct net_device *dev)
 
        fib6_clean_all(net, fib6_ifdown, &adn);
        icmp6_clean_all(fib6_ifdown, &adn);
-       rt6_uncached_list_flush_dev(net, dev);
+       if (dev)
+               rt6_uncached_list_flush_dev(net, dev);
 }
 
 struct rt6_mtu_change_arg {
@@ -3303,7 +3309,8 @@ errout:
        return err;
 }
 
-void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info)
+void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info,
+                    unsigned int nlm_flags)
 {
        struct sk_buff *skb;
        struct net *net = info->nl_net;
@@ -3318,7 +3325,7 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info)
                goto errout;
 
        err = rt6_fill_node(net, skb, rt, NULL, NULL, 0,
-                               event, info->portid, seq, 0, 0, 0);
+                               event, info->portid, seq, 0, 0, nlm_flags);
        if (err < 0) {
                /* -EMSGSIZE implies BUG in rt6_nlmsg_size() */
                WARN_ON(err == -EMSGSIZE);
index 09c76a7b474dbcb12cae8aeba6fcba375d0d329a..e15feb7b413dd1a93a376f2ab6aabcbc3c3bb944 100644 (file)
@@ -79,6 +79,7 @@ static int xfrm6_tunnel_check_size(struct sk_buff *skb)
 
        if (!skb->ignore_df && skb->len > mtu) {
                skb->dev = dst->dev;
+               skb->protocol = htons(ETH_P_IPV6);
 
                if (xfrm6_local_dontfrag(skb))
                        xfrm6_local_rxpmtu(skb, mtu);
@@ -136,6 +137,7 @@ static int __xfrm6_output(struct sock *sk, struct sk_buff *skb)
        struct dst_entry *dst = skb_dst(skb);
        struct xfrm_state *x = dst->xfrm;
        int mtu;
+       bool toobig;
 
 #ifdef CONFIG_NETFILTER
        if (!x) {
@@ -144,25 +146,29 @@ static int __xfrm6_output(struct sock *sk, struct sk_buff *skb)
        }
 #endif
 
+       if (x->props.mode != XFRM_MODE_TUNNEL)
+               goto skip_frag;
+
        if (skb->protocol == htons(ETH_P_IPV6))
                mtu = ip6_skb_dst_mtu(skb);
        else
                mtu = dst_mtu(skb_dst(skb));
 
-       if (skb->len > mtu && xfrm6_local_dontfrag(skb)) {
+       toobig = skb->len > mtu && !skb_is_gso(skb);
+
+       if (toobig && xfrm6_local_dontfrag(skb)) {
                xfrm6_local_rxpmtu(skb, mtu);
                return -EMSGSIZE;
-       } else if (!skb->ignore_df && skb->len > mtu && skb->sk) {
+       } else if (!skb->ignore_df && toobig && skb->sk) {
                xfrm_local_error(skb, mtu);
                return -EMSGSIZE;
        }
 
-       if (x->props.mode == XFRM_MODE_TUNNEL &&
-           ((skb->len > mtu && !skb_is_gso(skb)) ||
-               dst_allfrag(skb_dst(skb)))) {
+       if (toobig || dst_allfrag(skb_dst(skb)))
                return ip6_fragment(sk, skb,
                                    x->outer_mode->afinfo->output_finish);
-       }
+
+skip_frag:
        return x->outer_mode->afinfo->output_finish(sk, skb);
 }
 
index 30caa289c5dbf589270768ce90d15f2990341231..da55e0c85bb8edca213eae4686c46073e2af1650 100644 (file)
@@ -37,6 +37,7 @@ static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos, int oif,
 
        memset(&fl6, 0, sizeof(fl6));
        fl6.flowi6_oif = oif;
+       fl6.flowi6_flags = FLOWI_FLAG_SKIP_NH_OIF;
        memcpy(&fl6.daddr, daddr, sizeof(fl6.daddr));
        if (saddr)
                memcpy(&fl6.saddr, saddr, sizeof(fl6.saddr));
@@ -178,7 +179,8 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)
                        return;
 
                case IPPROTO_ICMPV6:
-                       if (!onlyproto && pskb_may_pull(skb, nh + offset + 2 - skb->data)) {
+                       if (!onlyproto && (nh + offset + 2 < skb->data ||
+                           pskb_may_pull(skb, nh + offset + 2 - skb->data))) {
                                u8 *icmp;
 
                                nh = skb_network_header(skb);
@@ -192,7 +194,8 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)
 #if IS_ENABLED(CONFIG_IPV6_MIP6)
                case IPPROTO_MH:
                        offset += ipv6_optlen(exthdr);
-                       if (!onlyproto && pskb_may_pull(skb, nh + offset + 3 - skb->data)) {
+                       if (!onlyproto && (nh + offset + 3 < skb->data ||
+                           pskb_may_pull(skb, nh + offset + 3 - skb->data))) {
                                struct ip6_mh *mh;
 
                                nh = skb_network_header(skb);
index a26c401ef4a4431b2957d5b46c05c0c2a35c90bd..43964594aa12d9864c00a3b778d77060084e6a14 100644 (file)
@@ -1839,7 +1839,7 @@ static void *irlmp_seq_hb_idx(struct irlmp_iter_state *iter, loff_t *off)
        for (element = hashbin_get_first(iter->hashbin);
             element != NULL;
             element = hashbin_get_next(iter->hashbin)) {
-               if (!off || *off-- == 0) {
+               if (!off || (*off)-- == 0) {
                        /* NB: hashbin left locked */
                        return element;
                }
index 83a70688784b8449603e13f32ec26ff6fce06639..f9c9ecb0cdd3b3eea618538fda2e884583f9bc09 100644 (file)
@@ -261,7 +261,7 @@ static int pfkey_broadcast(struct sk_buff *skb,
 
                err2 = pfkey_broadcast_one(skb, &skb2, GFP_ATOMIC, sk);
 
-               /* Error is cleare after succecful sending to at least one
+               /* Error is cleared after successful sending to at least one
                 * registered KM */
                if ((broadcast_flags & BROADCAST_REGISTERED) && err)
                        err = err2;
index f6b090df3930d32dc1fda0c8069ad1f7b3246d41..afca2eb4dfa777c75288dfb6fce9636b309a2ebc 100644 (file)
@@ -1319,7 +1319,7 @@ static void l2tp_tunnel_del_work(struct work_struct *work)
        tunnel = container_of(work, struct l2tp_tunnel, del_work);
        sk = l2tp_tunnel_sock_lookup(tunnel);
        if (!sk)
-               return;
+               goto out;
 
        sock = sk->sk_socket;
 
@@ -1341,6 +1341,8 @@ static void l2tp_tunnel_del_work(struct work_struct *work)
        }
 
        l2tp_tunnel_sock_put(sk);
+out:
+       l2tp_tunnel_dec_refcount(tunnel);
 }
 
 /* Create a socket for the tunnel, if one isn't set up by
@@ -1636,8 +1638,13 @@ EXPORT_SYMBOL_GPL(l2tp_tunnel_create);
  */
 int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel)
 {
+       l2tp_tunnel_inc_refcount(tunnel);
        l2tp_tunnel_closeall(tunnel);
-       return (false == queue_work(l2tp_wq, &tunnel->del_work));
+       if (false == queue_work(l2tp_wq, &tunnel->del_work)) {
+               l2tp_tunnel_dec_refcount(tunnel);
+               return 1;
+       }
+       return 0;
 }
 EXPORT_SYMBOL_GPL(l2tp_tunnel_delete);
 
index 17b1fe961c5d67b958346dee07e265448408cc71..7a77a1470f25bd26aa280eada69479da1f4e9dd9 100644 (file)
@@ -2474,6 +2474,7 @@ static int ieee80211_set_cqm_rssi_config(struct wiphy *wiphy,
 
        bss_conf->cqm_rssi_thold = rssi_thold;
        bss_conf->cqm_rssi_hyst = rssi_hyst;
+       sdata->u.mgd.last_cqm_event_signal = 0;
 
        /* tell the driver upon association, unless already associated */
        if (sdata->u.mgd.associated &&
@@ -2518,15 +2519,17 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy,
                        continue;
 
                for (j = 0; j < IEEE80211_HT_MCS_MASK_LEN; j++) {
-                       if (~sdata->rc_rateidx_mcs_mask[i][j])
+                       if (~sdata->rc_rateidx_mcs_mask[i][j]) {
                                sdata->rc_has_mcs_mask[i] = true;
+                               break;
+                       }
+               }
 
-                       if (~sdata->rc_rateidx_vht_mcs_mask[i][j])
+               for (j = 0; j < NL80211_VHT_NSS_MAX; j++) {
+                       if (~sdata->rc_rateidx_vht_mcs_mask[i][j]) {
                                sdata->rc_has_vht_mcs_mask[i] = true;
-
-                       if (sdata->rc_has_mcs_mask[i] &&
-                           sdata->rc_has_vht_mcs_mask[i])
                                break;
+                       }
                }
        }
 
index ced6bf3be8d6cf5d3d9fc80b6c46f48c4e567aef..1560c8482bcb9fd587d1e278a499f99fd9958803 100644 (file)
@@ -149,7 +149,7 @@ static ssize_t hwflags_read(struct file *file, char __user *user_buf,
 
        for (i = 0; i < NUM_IEEE80211_HW_FLAGS; i++) {
                if (test_bit(i, local->hw.flags))
-                       pos += scnprintf(pos, end - pos, "%s",
+                       pos += scnprintf(pos, end - pos, "%s\n",
                                         hw_flag_names[i]);
        }
 
index 8ba5832435095f10e94f782e07d92a4f742cad3a..3ed7ddfbf8e840d4c910b0e9452c06843031c91d 100644 (file)
@@ -101,6 +101,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
         * when it wakes up for the next time.
         */
        set_sta_flag(sta, WLAN_STA_CLEAR_PS_FILT);
+       ieee80211_clear_fast_xmit(sta);
 
        /*
         * This code races in the following way:
index 84e0e8c7fb236952dfc1cfcb23204623e80d7867..7892eb8ed4c8b1fa416ebcb297fab9f1cce91743 100644 (file)
@@ -1218,8 +1218,10 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
 
        if (!tx->sta)
                info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
-       else if (test_and_clear_sta_flag(tx->sta, WLAN_STA_CLEAR_PS_FILT))
+       else if (test_and_clear_sta_flag(tx->sta, WLAN_STA_CLEAR_PS_FILT)) {
                info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
+               ieee80211_check_fast_xmit(tx->sta);
+       }
 
        info->flags |= IEEE80211_TX_CTL_FIRST_FRAGMENT;
 
@@ -2451,7 +2453,8 @@ void ieee80211_check_fast_xmit(struct sta_info *sta)
 
        if (test_sta_flag(sta, WLAN_STA_PS_STA) ||
            test_sta_flag(sta, WLAN_STA_PS_DRIVER) ||
-           test_sta_flag(sta, WLAN_STA_PS_DELIVER))
+           test_sta_flag(sta, WLAN_STA_PS_DELIVER) ||
+           test_sta_flag(sta, WLAN_STA_CLEAR_PS_FILT))
                goto out;
 
        if (sdata->noack_map)
index 8e47f8113495739082572d269797e00160251751..21a085686dc1b543439f33e448531bc64a273684 100644 (file)
@@ -152,6 +152,8 @@ void nf_unregister_net_hook(struct net *net, const struct nf_hook_ops *reg)
 #endif
        synchronize_net();
        nf_queue_nf_hook_drop(net, &entry->ops);
+       /* other cpu might still process nfqueue verdict that used reg */
+       synchronize_net();
        kfree(entry);
 }
 EXPORT_SYMBOL(nf_unregister_net_hook);
index a1fe5377a2b3376d29f29b18d77ebfe08fc988e1..5a30ce6e8c90d278ac37cb0115f45a4390f9a6d7 100644 (file)
@@ -297,7 +297,7 @@ list_set_uadd(struct ip_set *set, void *value, const struct ip_set_ext *ext,
              ip_set_timeout_expired(ext_timeout(n, set))))
                n =  NULL;
 
-       e = kzalloc(set->dsize, GFP_KERNEL);
+       e = kzalloc(set->dsize, GFP_ATOMIC);
        if (!e)
                return -ENOMEM;
        e->id = d->id;
index 675d12c69e325c70e46ca5e5522fb5f8c77b7d8b..a5d41dfa9f05d6363d0ea3253493a7539842df32 100644 (file)
@@ -107,12 +107,17 @@ EXPORT_SYMBOL(nf_log_register);
 
 void nf_log_unregister(struct nf_logger *logger)
 {
+       const struct nf_logger *log;
        int i;
 
        mutex_lock(&nf_log_mutex);
-       for (i = 0; i < NFPROTO_NUMPROTO; i++)
-               RCU_INIT_POINTER(loggers[i][logger->type], NULL);
+       for (i = 0; i < NFPROTO_NUMPROTO; i++) {
+               log = nft_log_dereference(loggers[i][logger->type]);
+               if (log == logger)
+                       RCU_INIT_POINTER(loggers[i][logger->type], NULL);
+       }
        mutex_unlock(&nf_log_mutex);
+       synchronize_rcu();
 }
 EXPORT_SYMBOL(nf_log_unregister);
 
index 66def315eb5619a26b64da8a1a5525af7d4a5e3f..9c8fab00164b5b6f3e43b3fc6fe983e39f89e64e 100644 (file)
@@ -619,6 +619,13 @@ struct nft_xt {
 
 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)
+{
+       return strcmp(match->name, name) == 0 && match->revision == rev &&
+              (match->family == NFPROTO_UNSPEC || match->family == family);
+}
+
 static const struct nft_expr_ops *
 nft_match_select_ops(const struct nft_ctx *ctx,
                     const struct nlattr * const tb[])
@@ -626,7 +633,7 @@ nft_match_select_ops(const struct nft_ctx *ctx,
        struct nft_xt *nft_match;
        struct xt_match *match;
        char *mt_name;
-       __u32 rev, family;
+       u32 rev, family;
 
        if (tb[NFTA_MATCH_NAME] == NULL ||
            tb[NFTA_MATCH_REV] == NULL ||
@@ -641,8 +648,7 @@ nft_match_select_ops(const struct nft_ctx *ctx,
        list_for_each_entry(nft_match, &nft_match_list, head) {
                struct xt_match *match = nft_match->ops.data;
 
-               if (strcmp(match->name, mt_name) == 0 &&
-                   match->revision == rev && match->family == family) {
+               if (nft_match_cmp(match, mt_name, rev, family)) {
                        if (!try_module_get(match->me))
                                return ERR_PTR(-ENOENT);
 
@@ -693,6 +699,13 @@ 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)
+{
+       return strcmp(tg->name, name) == 0 && tg->revision == rev &&
+              (tg->family == NFPROTO_UNSPEC || tg->family == family);
+}
+
 static const struct nft_expr_ops *
 nft_target_select_ops(const struct nft_ctx *ctx,
                      const struct nlattr * const tb[])
@@ -700,7 +713,7 @@ nft_target_select_ops(const struct nft_ctx *ctx,
        struct nft_xt *nft_target;
        struct xt_target *target;
        char *tg_name;
-       __u32 rev, family;
+       u32 rev, family;
 
        if (tb[NFTA_TARGET_NAME] == NULL ||
            tb[NFTA_TARGET_REV] == NULL ||
@@ -715,8 +728,7 @@ nft_target_select_ops(const struct nft_ctx *ctx,
        list_for_each_entry(nft_target, &nft_target_list, head) {
                struct xt_target *target = nft_target->ops.data;
 
-               if (strcmp(target->name, tg_name) == 0 &&
-                   target->revision == rev && target->family == family) {
+               if (nft_target_cmp(target, tg_name, rev, family)) {
                        if (!try_module_get(target->me))
                                return ERR_PTR(-ENOENT);
 
index 7f86d3b550601839f730d4c9f15951f5410e3fd4..fafe33bdb61989e680dc4b26dbe99dcc1d4064b5 100644 (file)
@@ -125,6 +125,24 @@ static inline u32 netlink_group_mask(u32 group)
        return group ? 1 << (group - 1) : 0;
 }
 
+static struct sk_buff *netlink_to_full_skb(const struct sk_buff *skb,
+                                          gfp_t gfp_mask)
+{
+       unsigned int len = skb_end_offset(skb);
+       struct sk_buff *new;
+
+       new = alloc_skb(len, gfp_mask);
+       if (new == NULL)
+               return NULL;
+
+       NETLINK_CB(new).portid = NETLINK_CB(skb).portid;
+       NETLINK_CB(new).dst_group = NETLINK_CB(skb).dst_group;
+       NETLINK_CB(new).creds = NETLINK_CB(skb).creds;
+
+       memcpy(skb_put(new, len), skb->data, len);
+       return new;
+}
+
 int netlink_add_tap(struct netlink_tap *nt)
 {
        if (unlikely(nt->dev->type != ARPHRD_NETLINK))
@@ -206,7 +224,11 @@ static int __netlink_deliver_tap_skb(struct sk_buff *skb,
        int ret = -ENOMEM;
 
        dev_hold(dev);
-       nskb = skb_clone(skb, GFP_ATOMIC);
+
+       if (netlink_skb_is_mmaped(skb) || is_vmalloc_addr(skb->head))
+               nskb = netlink_to_full_skb(skb, GFP_ATOMIC);
+       else
+               nskb = skb_clone(skb, GFP_ATOMIC);
        if (nskb) {
                nskb->dev = dev;
                nskb->protocol = htons((u16) sk->sk_protocol);
@@ -279,11 +301,6 @@ static void netlink_rcv_wake(struct sock *sk)
 }
 
 #ifdef CONFIG_NETLINK_MMAP
-static bool netlink_skb_is_mmaped(const struct sk_buff *skb)
-{
-       return NETLINK_CB(skb).flags & NETLINK_SKB_MMAPED;
-}
-
 static bool netlink_rx_is_mmaped(struct sock *sk)
 {
        return nlk_sk(sk)->rx_ring.pg_vec != NULL;
@@ -846,7 +863,6 @@ static void netlink_ring_set_copied(struct sock *sk, struct sk_buff *skb)
 }
 
 #else /* CONFIG_NETLINK_MMAP */
-#define netlink_skb_is_mmaped(skb)     false
 #define netlink_rx_is_mmaped(sk)       false
 #define netlink_tx_is_mmaped(sk)       false
 #define netlink_mmap                   sock_no_mmap
@@ -1094,8 +1110,8 @@ static int netlink_insert(struct sock *sk, u32 portid)
 
        lock_sock(sk);
 
-       err = -EBUSY;
-       if (nlk_sk(sk)->portid)
+       err = nlk_sk(sk)->portid == portid ? 0 : -EBUSY;
+       if (nlk_sk(sk)->bound)
                goto err;
 
        err = -ENOMEM;
@@ -1115,10 +1131,14 @@ static int netlink_insert(struct sock *sk, u32 portid)
                        err = -EOVERFLOW;
                if (err == -EEXIST)
                        err = -EADDRINUSE;
-               nlk_sk(sk)->portid = 0;
                sock_put(sk);
+               goto err;
        }
 
+       /* We need to ensure that the socket is hashed and visible. */
+       smp_wmb();
+       nlk_sk(sk)->bound = portid;
+
 err:
        release_sock(sk);
        return err;
@@ -1503,6 +1523,7 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr,
        struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr;
        int err;
        long unsigned int groups = nladdr->nl_groups;
+       bool bound;
 
        if (addr_len < sizeof(struct sockaddr_nl))
                return -EINVAL;
@@ -1519,9 +1540,14 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr,
                        return err;
        }
 
-       if (nlk->portid)
+       bound = nlk->bound;
+       if (bound) {
+               /* Ensure nlk->portid is up-to-date. */
+               smp_rmb();
+
                if (nladdr->nl_pid != nlk->portid)
                        return -EINVAL;
+       }
 
        if (nlk->netlink_bind && groups) {
                int group;
@@ -1537,7 +1563,10 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr,
                }
        }
 
-       if (!nlk->portid) {
+       /* No need for barriers here as we return to user-space without
+        * using any of the bound attributes.
+        */
+       if (!bound) {
                err = nladdr->nl_pid ?
                        netlink_insert(sk, nladdr->nl_pid) :
                        netlink_autobind(sock);
@@ -1585,7 +1614,10 @@ static int netlink_connect(struct socket *sock, struct sockaddr *addr,
            !netlink_allowed(sock, NL_CFG_F_NONROOT_SEND))
                return -EPERM;
 
-       if (!nlk->portid)
+       /* No need for barriers here as we return to user-space without
+        * using any of the bound attributes.
+        */
+       if (!nlk->bound)
                err = netlink_autobind(sock);
 
        if (err == 0) {
@@ -2339,7 +2371,7 @@ static int netlink_getsockopt(struct socket *sock, int level, int optname,
                int pos, idx, shift;
 
                err = 0;
-               netlink_table_grab();
+               netlink_lock_table();
                for (pos = 0; pos * 8 < nlk->ngroups; pos += sizeof(u32)) {
                        if (len - pos < sizeof(u32))
                                break;
@@ -2354,7 +2386,7 @@ static int netlink_getsockopt(struct socket *sock, int level, int optname,
                }
                if (put_user(ALIGN(nlk->ngroups / 8, sizeof(u32)), optlen))
                        err = -EFAULT;
-               netlink_table_ungrab();
+               netlink_unlock_table();
                break;
        }
        case NETLINK_CAP_ACK:
@@ -2426,10 +2458,13 @@ static int netlink_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
                dst_group = nlk->dst_group;
        }
 
-       if (!nlk->portid) {
+       if (!nlk->bound) {
                err = netlink_autobind(sock);
                if (err)
                        goto out;
+       } else {
+               /* Ensure nlk is hashed and visible. */
+               smp_rmb();
        }
 
        /* It's a really convoluted way for userland to ask for mmaped
@@ -2750,6 +2785,7 @@ static int netlink_dump(struct sock *sk)
        struct sk_buff *skb = NULL;
        struct nlmsghdr *nlh;
        int len, err = -ENOBUFS;
+       int alloc_min_size;
        int alloc_size;
 
        mutex_lock(nlk->cb_mutex);
@@ -2758,9 +2794,6 @@ static int netlink_dump(struct sock *sk)
                goto errout_skb;
        }
 
-       cb = &nlk->cb;
-       alloc_size = max_t(int, cb->min_dump_alloc, NLMSG_GOODSIZE);
-
        if (!netlink_rx_is_mmaped(sk) &&
            atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf)
                goto errout_skb;
@@ -2770,23 +2803,35 @@ static int netlink_dump(struct sock *sk)
         * to reduce number of system calls on dump operations, if user
         * ever provided a big enough buffer.
         */
-       if (alloc_size < nlk->max_recvmsg_len) {
-               skb = netlink_alloc_skb(sk,
-                                       nlk->max_recvmsg_len,
-                                       nlk->portid,
+       cb = &nlk->cb;
+       alloc_min_size = max_t(int, cb->min_dump_alloc, NLMSG_GOODSIZE);
+
+       if (alloc_min_size < nlk->max_recvmsg_len) {
+               alloc_size = nlk->max_recvmsg_len;
+               skb = netlink_alloc_skb(sk, alloc_size, nlk->portid,
                                        GFP_KERNEL |
                                        __GFP_NOWARN |
                                        __GFP_NORETRY);
-               /* available room should be exact amount to avoid MSG_TRUNC */
-               if (skb)
-                       skb_reserve(skb, skb_tailroom(skb) -
-                                        nlk->max_recvmsg_len);
        }
-       if (!skb)
+       if (!skb) {
+               alloc_size = alloc_min_size;
                skb = netlink_alloc_skb(sk, alloc_size, nlk->portid,
                                        GFP_KERNEL);
+       }
        if (!skb)
                goto errout_skb;
+
+       /* Trim skb to allocated size. User is expected to provide buffer as
+        * large as max(min_dump_alloc, 16KiB (mac_recvmsg_len capped at
+        * netlink_recvmsg())). dump will pack as many smaller messages as
+        * could fit within the allocated skb. skb is typically allocated
+        * with larger space than required (could be as much as near 2x the
+        * requested size with align to next power of 2 approach). Allowing
+        * dump to use the excess space makes it difficult for a user to have a
+        * reasonable static buffer based on the expected largest dump of a
+        * single netdev. The outcome is MSG_TRUNC error.
+        */
+       skb_reserve(skb, skb_tailroom(skb) - alloc_size);
        netlink_skb_set_owner_r(skb, sk);
 
        len = cb->dump(skb, cb);
index 89008405d6b4d2c9f2d82850fa872be98553e154..14437d9b1965dcf3d3f085e4aba1f804bdc6f652 100644 (file)
@@ -35,6 +35,7 @@ struct netlink_sock {
        unsigned long           state;
        size_t                  max_recvmsg_len;
        wait_queue_head_t       wait;
+       bool                    bound;
        bool                    cb_running;
        struct netlink_callback cb;
        struct mutex            *cb_mutex;
@@ -59,6 +60,15 @@ static inline struct netlink_sock *nlk_sk(struct sock *sk)
        return container_of(sk, struct netlink_sock, sk);
 }
 
+static inline bool netlink_skb_is_mmaped(const struct sk_buff *skb)
+{
+#ifdef CONFIG_NETLINK_MMAP
+       return NETLINK_CB(skb).flags & NETLINK_SKB_MMAPED;
+#else
+       return false;
+#endif /* CONFIG_NETLINK_MMAP */
+}
+
 struct netlink_table {
        struct rhashtable       hash;
        struct hlist_head       mc_list;
index 2a071f470d578e135e6a04c462199f9a5cdb7b69..d143aa9f66541898d558888b409414f618fc769d 100644 (file)
@@ -5,7 +5,8 @@
 config OPENVSWITCH
        tristate "Open vSwitch"
        depends on INET
-       depends on (!NF_CONNTRACK || NF_CONNTRACK)
+       depends on !NF_CONNTRACK || \
+                  (NF_CONNTRACK && (!NF_DEFRAG_IPV6 || NF_DEFRAG_IPV6))
        select LIBCRC32C
        select MPLS
        select NET_MPLS_GSO
index 315f5330b6e5400eaf28ce7d0290038b7113a6fd..dba635d086b2f165940ce1dea67c92c48392e4cb 100644 (file)
@@ -684,7 +684,7 @@ static void ovs_fragment(struct vport *vport, struct sk_buff *skb, u16 mru,
 {
        if (skb_network_offset(skb) > MAX_L2_LEN) {
                OVS_NLERR(1, "L2 header too long to fragment");
-               return;
+               goto err;
        }
 
        if (ethertype == htons(ETH_P_IP)) {
@@ -708,8 +708,7 @@ static void ovs_fragment(struct vport *vport, struct sk_buff *skb, u16 mru,
                struct rt6_info ovs_rt;
 
                if (!v6ops) {
-                       kfree_skb(skb);
-                       return;
+                       goto err;
                }
 
                prepare_frag(vport, skb);
@@ -728,8 +727,12 @@ static void ovs_fragment(struct vport *vport, struct sk_buff *skb, u16 mru,
                WARN_ONCE(1, "Failed fragment ->%s: eth=%04x, MRU=%d, MTU=%d.",
                          ovs_vport_name(vport), ntohs(ethertype), mru,
                          vport->dev->mtu);
-               kfree_skb(skb);
+               goto err;
        }
+
+       return;
+err:
+       kfree_skb(skb);
 }
 
 static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port,
@@ -765,7 +768,6 @@ static int output_userspace(struct datapath *dp, struct sk_buff *skb,
                            struct sw_flow_key *key, const struct nlattr *attr,
                            const struct nlattr *actions, int actions_len)
 {
-       struct ip_tunnel_info info;
        struct dp_upcall_info upcall;
        const struct nlattr *a;
        int rem;
@@ -793,11 +795,9 @@ static int output_userspace(struct datapath *dp, struct sk_buff *skb,
                        if (vport) {
                                int err;
 
-                               upcall.egress_tun_info = &info;
-                               err = ovs_vport_get_egress_tun_info(vport, skb,
-                                                                   &upcall);
-                               if (err)
-                                       upcall.egress_tun_info = NULL;
+                               err = dev_fill_metadata_dst(vport->dev, skb);
+                               if (!err)
+                                       upcall.egress_tun_info = skb_tunnel_info(skb);
                        }
 
                        break;
@@ -968,7 +968,7 @@ static int execute_masked_set_action(struct sk_buff *skb,
        case OVS_KEY_ATTR_CT_STATE:
        case OVS_KEY_ATTR_CT_ZONE:
        case OVS_KEY_ATTR_CT_MARK:
-       case OVS_KEY_ATTR_CT_LABEL:
+       case OVS_KEY_ATTR_CT_LABELS:
                err = -EINVAL;
                break;
        }
@@ -1099,12 +1099,18 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
                        break;
 
                case OVS_ACTION_ATTR_CT:
+                       if (!is_flow_key_valid(key)) {
+                               err = ovs_flow_key_update(skb, key);
+                               if (err)
+                                       return err;
+                       }
+
                        err = ovs_ct_execute(ovs_dp_get_net(dp), skb, key,
                                             nla_data(a));
 
                        /* Hide stolen IP fragments from user space. */
-                       if (err == -EINPROGRESS)
-                               return 0;
+                       if (err)
+                               return err == -EINPROGRESS ? 0 : err;
                        break;
                }
 
index e8e524ad8a01cb3e62b531cf13659784f2f123ef..50095820edb7b2f8adc1ba1699543c2b28e378b0 100644 (file)
@@ -37,9 +37,9 @@ struct md_mark {
 };
 
 /* Metadata label for masked write to conntrack label. */
-struct md_label {
-       struct ovs_key_ct_label value;
-       struct ovs_key_ct_label mask;
+struct md_labels {
+       struct ovs_key_ct_labels value;
+       struct ovs_key_ct_labels mask;
 };
 
 /* Conntrack action context for execution. */
@@ -47,10 +47,10 @@ struct ovs_conntrack_info {
        struct nf_conntrack_helper *helper;
        struct nf_conntrack_zone zone;
        struct nf_conn *ct;
-       u32 flags;
+       u8 commit : 1;
        u16 family;
        struct md_mark mark;
-       struct md_label label;
+       struct md_labels labels;
 };
 
 static u16 key_to_nfproto(const struct sw_flow_key *key)
@@ -109,21 +109,21 @@ static u32 ovs_ct_get_mark(const struct nf_conn *ct)
 #endif
 }
 
-static void ovs_ct_get_label(const struct nf_conn *ct,
-                            struct ovs_key_ct_label *label)
+static void ovs_ct_get_labels(const struct nf_conn *ct,
+                             struct ovs_key_ct_labels *labels)
 {
        struct nf_conn_labels *cl = ct ? nf_ct_labels_find(ct) : NULL;
 
        if (cl) {
                size_t len = cl->words * sizeof(long);
 
-               if (len > OVS_CT_LABEL_LEN)
-                       len = OVS_CT_LABEL_LEN;
-               else if (len < OVS_CT_LABEL_LEN)
-                       memset(label, 0, OVS_CT_LABEL_LEN);
-               memcpy(label, cl->bits, len);
+               if (len > OVS_CT_LABELS_LEN)
+                       len = OVS_CT_LABELS_LEN;
+               else if (len < OVS_CT_LABELS_LEN)
+                       memset(labels, 0, OVS_CT_LABELS_LEN);
+               memcpy(labels, cl->bits, len);
        } else {
-               memset(label, 0, OVS_CT_LABEL_LEN);
+               memset(labels, 0, OVS_CT_LABELS_LEN);
        }
 }
 
@@ -134,7 +134,7 @@ static void __ovs_ct_update_key(struct sw_flow_key *key, u8 state,
        key->ct.state = state;
        key->ct.zone = zone->id;
        key->ct.mark = ovs_ct_get_mark(ct);
-       ovs_ct_get_label(ct, &key->ct.label);
+       ovs_ct_get_labels(ct, &key->ct.labels);
 }
 
 /* Update 'key' based on skb->nfct. If 'post_ct' is true, then OVS has
@@ -151,6 +151,8 @@ static void ovs_ct_update_key(const struct sk_buff *skb,
        ct = nf_ct_get(skb, &ctinfo);
        if (ct) {
                state = ovs_ct_get_state(ctinfo);
+               if (!nf_ct_is_confirmed(ct))
+                       state |= OVS_CS_F_NEW;
                if (ct->master)
                        state |= OVS_CS_F_RELATED;
                zone = nf_ct_zone(ct);
@@ -167,7 +169,7 @@ void ovs_ct_fill_key(const struct sk_buff *skb, struct sw_flow_key *key)
 
 int ovs_ct_put_key(const struct sw_flow_key *key, struct sk_buff *skb)
 {
-       if (nla_put_u8(skb, OVS_KEY_ATTR_CT_STATE, key->ct.state))
+       if (nla_put_u32(skb, OVS_KEY_ATTR_CT_STATE, key->ct.state))
                return -EMSGSIZE;
 
        if (IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES) &&
@@ -179,8 +181,8 @@ int ovs_ct_put_key(const struct sw_flow_key *key, struct sk_buff *skb)
                return -EMSGSIZE;
 
        if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) &&
-           nla_put(skb, OVS_KEY_ATTR_CT_LABEL, sizeof(key->ct.label),
-                   &key->ct.label))
+           nla_put(skb, OVS_KEY_ATTR_CT_LABELS, sizeof(key->ct.labels),
+                   &key->ct.labels))
                return -EMSGSIZE;
 
        return 0;
@@ -213,18 +215,15 @@ static int ovs_ct_set_mark(struct sk_buff *skb, struct sw_flow_key *key,
 #endif
 }
 
-static int ovs_ct_set_label(struct sk_buff *skb, struct sw_flow_key *key,
-                           const struct ovs_key_ct_label *label,
-                           const struct ovs_key_ct_label *mask)
+static int ovs_ct_set_labels(struct sk_buff *skb, struct sw_flow_key *key,
+                            const struct ovs_key_ct_labels *labels,
+                            const struct ovs_key_ct_labels *mask)
 {
        enum ip_conntrack_info ctinfo;
        struct nf_conn_labels *cl;
        struct nf_conn *ct;
        int err;
 
-       if (!IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS))
-               return -ENOTSUPP;
-
        /* The connection could be invalid, in which case set_label is no-op.*/
        ct = nf_ct_get(skb, &ctinfo);
        if (!ct)
@@ -235,15 +234,15 @@ static int ovs_ct_set_label(struct sk_buff *skb, struct sw_flow_key *key,
                nf_ct_labels_ext_add(ct);
                cl = nf_ct_labels_find(ct);
        }
-       if (!cl || cl->words * sizeof(long) < OVS_CT_LABEL_LEN)
+       if (!cl || cl->words * sizeof(long) < OVS_CT_LABELS_LEN)
                return -ENOSPC;
 
-       err = nf_connlabels_replace(ct, (u32 *)label, (u32 *)mask,
-                                   OVS_CT_LABEL_LEN / sizeof(u32));
+       err = nf_connlabels_replace(ct, (u32 *)labels, (u32 *)mask,
+                                   OVS_CT_LABELS_LEN / sizeof(u32));
        if (err)
                return err;
 
-       ovs_ct_get_label(ct, &key->ct.label);
+       ovs_ct_get_labels(ct, &key->ct.labels);
        return 0;
 }
 
@@ -275,13 +274,15 @@ static int ovs_ct_helper(struct sk_buff *skb, u16 proto)
        case NFPROTO_IPV6: {
                u8 nexthdr = ipv6_hdr(skb)->nexthdr;
                __be16 frag_off;
+               int ofs;
 
-               protoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr),
-                                          &nexthdr, &frag_off);
-               if (protoff < 0 || (frag_off & htons(~0x7)) != 0) {
+               ofs = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr,
+                                      &frag_off);
+               if (ofs < 0 || (frag_off & htons(~0x7)) != 0) {
                        pr_debug("proto header not found\n");
                        return NF_ACCEPT;
                }
+               protoff = ofs;
                break;
        }
        default:
@@ -292,6 +293,9 @@ static int ovs_ct_helper(struct sk_buff *skb, u16 proto)
        return helper->help(skb, protoff, ct, ctinfo);
 }
 
+/* Returns 0 on success, -EINPROGRESS if 'skb' is stolen, or other nonzero
+ * value if 'skb' is freed.
+ */
 static int handle_fragments(struct net *net, struct sw_flow_key *key,
                            u16 zone, struct sk_buff *skb)
 {
@@ -307,8 +311,8 @@ static int handle_fragments(struct net *net, struct sw_flow_key *key,
                        return err;
 
                ovs_cb.mru = IPCB(skb)->frag_max_size;
-       } else if (key->eth.type == htons(ETH_P_IPV6)) {
 #if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6)
+       } else if (key->eth.type == htons(ETH_P_IPV6)) {
                enum ip6_defrag_users user = IP6_DEFRAG_CONNTRACK_IN + zone;
                struct sk_buff *reasm;
 
@@ -317,17 +321,25 @@ static int handle_fragments(struct net *net, struct sw_flow_key *key,
                if (!reasm)
                        return -EINPROGRESS;
 
-               if (skb == reasm)
+               if (skb == reasm) {
+                       kfree_skb(skb);
                        return -EINVAL;
+               }
+
+               /* Don't free 'skb' even though it is one of the original
+                * fragments, as we're going to morph it into the head.
+                */
+               skb_get(skb);
+               nf_ct_frag6_consume_orig(reasm);
 
                key->ip.proto = ipv6_hdr(reasm)->nexthdr;
                skb_morph(skb, reasm);
+               skb->next = reasm->next;
                consume_skb(reasm);
                ovs_cb.mru = IP6CB(skb)->frag_max_size;
-#else
-               return -EPFNOSUPPORT;
 #endif
        } else {
+               kfree_skb(skb);
                return -EPFNOSUPPORT;
        }
 
@@ -375,7 +387,7 @@ static bool skb_nfct_cached(const struct net *net, const struct sk_buff *skb,
        return true;
 }
 
-static int __ovs_ct_lookup(struct net *net, const struct sw_flow_key *key,
+static int __ovs_ct_lookup(struct net *net, struct sw_flow_key *key,
                           const struct ovs_conntrack_info *info,
                           struct sk_buff *skb)
 {
@@ -406,6 +418,8 @@ static int __ovs_ct_lookup(struct net *net, const struct sw_flow_key *key,
                }
        }
 
+       ovs_ct_update_key(skb, key, true);
+
        return 0;
 }
 
@@ -428,8 +442,6 @@ static int ovs_ct_lookup(struct net *net, struct sw_flow_key *key,
                err = __ovs_ct_lookup(net, key, info, skb);
                if (err)
                        return err;
-
-               ovs_ct_update_key(skb, key, true);
        }
 
        return 0;
@@ -458,22 +470,23 @@ static int ovs_ct_commit(struct net *net, struct sw_flow_key *key,
        if (nf_conntrack_confirm(skb) != NF_ACCEPT)
                return -EINVAL;
 
-       ovs_ct_update_key(skb, key, true);
-
        return 0;
 }
 
-static bool label_nonzero(const struct ovs_key_ct_label *label)
+static bool labels_nonzero(const struct ovs_key_ct_labels *labels)
 {
        size_t i;
 
-       for (i = 0; i < sizeof(*label); i++)
-               if (label->ct_label[i])
+       for (i = 0; i < sizeof(*labels); i++)
+               if (labels->ct_labels[i])
                        return true;
 
        return false;
 }
 
+/* Returns 0 on success, -EINPROGRESS if 'skb' is stolen, or other nonzero
+ * value if 'skb' is freed.
+ */
 int ovs_ct_execute(struct net *net, struct sk_buff *skb,
                   struct sw_flow_key *key,
                   const struct ovs_conntrack_info *info)
@@ -491,7 +504,7 @@ int ovs_ct_execute(struct net *net, struct sk_buff *skb,
                        return err;
        }
 
-       if (info->flags & OVS_CT_F_COMMIT)
+       if (info->commit)
                err = ovs_ct_commit(net, key, info, skb);
        else
                err = ovs_ct_lookup(net, key, info, skb);
@@ -504,11 +517,13 @@ int ovs_ct_execute(struct net *net, struct sk_buff *skb,
                if (err)
                        goto err;
        }
-       if (label_nonzero(&info->label.mask))
-               err = ovs_ct_set_label(skb, key, &info->label.value,
-                                      &info->label.mask);
+       if (labels_nonzero(&info->labels.mask))
+               err = ovs_ct_set_labels(skb, key, &info->labels.value,
+                                       &info->labels.mask);
 err:
        skb_push(skb, nh_ofs);
+       if (err)
+               kfree_skb(skb);
        return err;
 }
 
@@ -537,14 +552,13 @@ static int ovs_ct_add_helper(struct ovs_conntrack_info *info, const char *name,
 }
 
 static const struct ovs_ct_len_tbl ovs_ct_attr_lens[OVS_CT_ATTR_MAX + 1] = {
-       [OVS_CT_ATTR_FLAGS]     = { .minlen = sizeof(u32),
-                                   .maxlen = sizeof(u32) },
+       [OVS_CT_ATTR_COMMIT]    = { .minlen = 0, .maxlen = 0 },
        [OVS_CT_ATTR_ZONE]      = { .minlen = sizeof(u16),
                                    .maxlen = sizeof(u16) },
        [OVS_CT_ATTR_MARK]      = { .minlen = sizeof(struct md_mark),
                                    .maxlen = sizeof(struct md_mark) },
-       [OVS_CT_ATTR_LABEL]     = { .minlen = sizeof(struct md_label),
-                                   .maxlen = sizeof(struct md_label) },
+       [OVS_CT_ATTR_LABELS]    = { .minlen = sizeof(struct md_labels),
+                                   .maxlen = sizeof(struct md_labels) },
        [OVS_CT_ATTR_HELPER]    = { .minlen = 1,
                                    .maxlen = NF_CT_HELPER_NAME_LEN }
 };
@@ -574,8 +588,8 @@ static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info,
                }
 
                switch (type) {
-               case OVS_CT_ATTR_FLAGS:
-                       info->flags = nla_get_u32(a);
+               case OVS_CT_ATTR_COMMIT:
+                       info->commit = true;
                        break;
 #ifdef CONFIG_NF_CONNTRACK_ZONES
                case OVS_CT_ATTR_ZONE:
@@ -586,15 +600,23 @@ static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info,
                case OVS_CT_ATTR_MARK: {
                        struct md_mark *mark = nla_data(a);
 
+                       if (!mark->mask) {
+                               OVS_NLERR(log, "ct_mark mask cannot be 0");
+                               return -EINVAL;
+                       }
                        info->mark = *mark;
                        break;
                }
 #endif
 #ifdef CONFIG_NF_CONNTRACK_LABELS
-               case OVS_CT_ATTR_LABEL: {
-                       struct md_label *label = nla_data(a);
+               case OVS_CT_ATTR_LABELS: {
+                       struct md_labels *labels = nla_data(a);
 
-                       info->label = *label;
+                       if (!labels_nonzero(&labels->mask)) {
+                               OVS_NLERR(log, "ct_labels mask cannot be 0");
+                               return -EINVAL;
+                       }
+                       info->labels = *labels;
                        break;
                }
 #endif
@@ -631,7 +653,7 @@ bool ovs_ct_verify(struct net *net, enum ovs_key_attr attr)
            attr == OVS_KEY_ATTR_CT_MARK)
                return true;
        if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) &&
-           attr == OVS_KEY_ATTR_CT_LABEL) {
+           attr == OVS_KEY_ATTR_CT_LABELS) {
                struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
 
                return ovs_net->xt_label;
@@ -699,18 +721,19 @@ int ovs_ct_action_to_attr(const struct ovs_conntrack_info *ct_info,
        if (!start)
                return -EMSGSIZE;
 
-       if (nla_put_u32(skb, OVS_CT_ATTR_FLAGS, ct_info->flags))
+       if (ct_info->commit && nla_put_flag(skb, OVS_CT_ATTR_COMMIT))
                return -EMSGSIZE;
        if (IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES) &&
            nla_put_u16(skb, OVS_CT_ATTR_ZONE, ct_info->zone.id))
                return -EMSGSIZE;
-       if (IS_ENABLED(CONFIG_NF_CONNTRACK_MARK) &&
+       if (IS_ENABLED(CONFIG_NF_CONNTRACK_MARK) && ct_info->mark.mask &&
            nla_put(skb, OVS_CT_ATTR_MARK, sizeof(ct_info->mark),
                    &ct_info->mark))
                return -EMSGSIZE;
        if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) &&
-           nla_put(skb, OVS_CT_ATTR_LABEL, sizeof(ct_info->label),
-                   &ct_info->label))
+           labels_nonzero(&ct_info->labels.mask) &&
+           nla_put(skb, OVS_CT_ATTR_LABELS, sizeof(ct_info->labels),
+                   &ct_info->labels))
                return -EMSGSIZE;
        if (ct_info->helper) {
                if (nla_put_string(skb, OVS_CT_ATTR_HELPER,
@@ -735,7 +758,7 @@ void ovs_ct_free_action(const struct nlattr *a)
 
 void ovs_ct_init(struct net *net)
 {
-       unsigned int n_bits = sizeof(struct ovs_key_ct_label) * BITS_PER_BYTE;
+       unsigned int n_bits = sizeof(struct ovs_key_ct_labels) * BITS_PER_BYTE;
        struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
 
        if (nf_connlabels_get(net, n_bits)) {
index 43f5dd7a55774414aeb7aad8c0560db3e0596035..a7544f405c1626f6564075f4453832b311b1ac29 100644 (file)
@@ -34,6 +34,10 @@ int ovs_ct_execute(struct net *, struct sk_buff *, struct sw_flow_key *,
 void ovs_ct_fill_key(const struct sk_buff *skb, struct sw_flow_key *key);
 int ovs_ct_put_key(const struct sw_flow_key *key, struct sk_buff *skb);
 void ovs_ct_free_action(const struct nlattr *a);
+
+#define CT_SUPPORTED_MASK (OVS_CS_F_NEW | OVS_CS_F_ESTABLISHED | \
+                          OVS_CS_F_RELATED | OVS_CS_F_REPLY_DIR | \
+                          OVS_CS_F_INVALID | OVS_CS_F_TRACKED)
 #else
 #include <linux/errno.h>
 
@@ -63,6 +67,7 @@ static inline int ovs_ct_execute(struct net *net, struct sk_buff *skb,
                                 struct sw_flow_key *key,
                                 const struct ovs_conntrack_info *info)
 {
+       kfree_skb(skb);
        return -ENOTSUPP;
 }
 
@@ -72,7 +77,7 @@ static inline void ovs_ct_fill_key(const struct sk_buff *skb,
        key->ct.state = 0;
        key->ct.zone = 0;
        key->ct.mark = 0;
-       memset(&key->ct.label, 0, sizeof(key->ct.label));
+       memset(&key->ct.labels, 0, sizeof(key->ct.labels));
 }
 
 static inline int ovs_ct_put_key(const struct sw_flow_key *key,
@@ -82,5 +87,7 @@ static inline int ovs_ct_put_key(const struct sw_flow_key *key,
 }
 
 static inline void ovs_ct_free_action(const struct nlattr *a) { }
+
+#define CT_SUPPORTED_MASK 0
 #endif /* CONFIG_NF_CONNTRACK */
 #endif /* ovs_conntrack.h */
index 6fbd2decb19e2682bacd1d1cfedf186b4724bd9c..c5d08ee377304313e7e320133e46343adff5da95 100644 (file)
@@ -490,9 +490,8 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,
 
        if (upcall_info->egress_tun_info) {
                nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_EGRESS_TUN_KEY);
-               err = ovs_nla_put_egress_tunnel_key(user_skb,
-                                                   upcall_info->egress_tun_info,
-                                                   upcall_info->egress_tun_opts);
+               err = ovs_nla_put_tunnel_info(user_skb,
+                                             upcall_info->egress_tun_info);
                BUG_ON(err);
                nla_nest_end(user_skb, nla);
        }
@@ -952,7 +951,7 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
        if (error)
                goto err_kfree_flow;
 
-       ovs_flow_mask_key(&new_flow->key, &key, &mask);
+       ovs_flow_mask_key(&new_flow->key, &key, true, &mask);
 
        /* Extract flow identifier. */
        error = ovs_nla_get_identifier(&new_flow->id, a[OVS_FLOW_ATTR_UFID],
@@ -1080,7 +1079,7 @@ static struct sw_flow_actions *get_flow_actions(struct net *net,
        struct sw_flow_key masked_key;
        int error;
 
-       ovs_flow_mask_key(&masked_key, key, mask);
+       ovs_flow_mask_key(&masked_key, key, true, mask);
        error = ovs_nla_copy_actions(net, a, &masked_key, &acts, log);
        if (error) {
                OVS_NLERR(log,
index f88038a99f4442bb753b4fc0cb3cc6c05c2bc2fc..67bdecd9fdc1f2b0544c2081aa1a557b16e0063a 100644 (file)
@@ -117,7 +117,6 @@ struct ovs_skb_cb {
  */
 struct dp_upcall_info {
        struct ip_tunnel_info *egress_tun_info;
-       const void *egress_tun_opts;
        const struct nlattr *userdata;
        const struct nlattr *actions;
        int actions_len;
index fe527d2dd4b7ae9d6b31a7d9d92586d1cd276c26..8cfa15a08668804a2a74c0047662694f23acbb80 100644 (file)
@@ -116,7 +116,7 @@ struct sw_flow_key {
                u16 zone;
                u32 mark;
                u8 state;
-               struct ovs_key_ct_label label;
+               struct ovs_key_ct_labels labels;
        } ct;
 
 } __aligned(BITS_PER_LONG/8); /* Ensure that we can do comparisons as longs. */
index c92d6a262bc5100771b7f0fd25e39742350f5ca7..38536c137c54d0d4ebcebcce613fefdb89799b5a 100644 (file)
@@ -57,6 +57,7 @@ struct ovs_len_tbl {
 };
 
 #define OVS_ATTR_NESTED -1
+#define OVS_ATTR_VARIABLE -2
 
 static void update_range(struct sw_flow_match *match,
                         size_t offset, size_t size, bool is_mask)
@@ -290,10 +291,10 @@ size_t ovs_key_attr_size(void)
                + nla_total_size(4)   /* OVS_KEY_ATTR_SKB_MARK */
                + nla_total_size(4)   /* OVS_KEY_ATTR_DP_HASH */
                + nla_total_size(4)   /* OVS_KEY_ATTR_RECIRC_ID */
-               + nla_total_size(1)   /* OVS_KEY_ATTR_CT_STATE */
+               + nla_total_size(4)   /* OVS_KEY_ATTR_CT_STATE */
                + nla_total_size(2)   /* OVS_KEY_ATTR_CT_ZONE */
                + nla_total_size(4)   /* OVS_KEY_ATTR_CT_MARK */
-               + nla_total_size(16)  /* OVS_KEY_ATTR_CT_LABEL */
+               + nla_total_size(16)  /* OVS_KEY_ATTR_CT_LABELS */
                + nla_total_size(12)  /* OVS_KEY_ATTR_ETHERNET */
                + nla_total_size(2)   /* OVS_KEY_ATTR_ETHERTYPE */
                + nla_total_size(4)   /* OVS_KEY_ATTR_VLAN */
@@ -304,6 +305,10 @@ size_t ovs_key_attr_size(void)
                + nla_total_size(28); /* OVS_KEY_ATTR_ND */
 }
 
+static const struct ovs_len_tbl ovs_vxlan_ext_key_lens[OVS_VXLAN_EXT_MAX + 1] = {
+       [OVS_VXLAN_EXT_GBP]         = { .len = sizeof(u32) },
+};
+
 static const struct ovs_len_tbl ovs_tunnel_key_lens[OVS_TUNNEL_KEY_ATTR_MAX + 1] = {
        [OVS_TUNNEL_KEY_ATTR_ID]            = { .len = sizeof(u64) },
        [OVS_TUNNEL_KEY_ATTR_IPV4_SRC]      = { .len = sizeof(u32) },
@@ -315,8 +320,9 @@ static const struct ovs_len_tbl ovs_tunnel_key_lens[OVS_TUNNEL_KEY_ATTR_MAX + 1]
        [OVS_TUNNEL_KEY_ATTR_TP_SRC]        = { .len = sizeof(u16) },
        [OVS_TUNNEL_KEY_ATTR_TP_DST]        = { .len = sizeof(u16) },
        [OVS_TUNNEL_KEY_ATTR_OAM]           = { .len = 0 },
-       [OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS]   = { .len = OVS_ATTR_NESTED },
-       [OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS]    = { .len = OVS_ATTR_NESTED },
+       [OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS]   = { .len = OVS_ATTR_VARIABLE },
+       [OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS]    = { .len = OVS_ATTR_NESTED,
+                                               .next = ovs_vxlan_ext_key_lens },
 };
 
 /* The size of the argument for each %OVS_KEY_ATTR_* Netlink attribute.  */
@@ -343,12 +349,19 @@ static const struct ovs_len_tbl ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = {
        [OVS_KEY_ATTR_TUNNEL]    = { .len = OVS_ATTR_NESTED,
                                     .next = ovs_tunnel_key_lens, },
        [OVS_KEY_ATTR_MPLS]      = { .len = sizeof(struct ovs_key_mpls) },
-       [OVS_KEY_ATTR_CT_STATE]  = { .len = sizeof(u8) },
+       [OVS_KEY_ATTR_CT_STATE]  = { .len = sizeof(u32) },
        [OVS_KEY_ATTR_CT_ZONE]   = { .len = sizeof(u16) },
        [OVS_KEY_ATTR_CT_MARK]   = { .len = sizeof(u32) },
-       [OVS_KEY_ATTR_CT_LABEL]  = { .len = sizeof(struct ovs_key_ct_label) },
+       [OVS_KEY_ATTR_CT_LABELS] = { .len = sizeof(struct ovs_key_ct_labels) },
 };
 
+static bool check_attr_len(unsigned int attr_len, unsigned int expected_len)
+{
+       return expected_len == attr_len ||
+              expected_len == OVS_ATTR_NESTED ||
+              expected_len == OVS_ATTR_VARIABLE;
+}
+
 static bool is_all_zero(const u8 *fp, size_t size)
 {
        int i;
@@ -388,7 +401,7 @@ static int __parse_flow_nlattrs(const struct nlattr *attr,
                }
 
                expected_len = ovs_key_lens[type].len;
-               if (nla_len(nla) != expected_len && expected_len != OVS_ATTR_NESTED) {
+               if (!check_attr_len(nla_len(nla), expected_len)) {
                        OVS_NLERR(log, "Key %d has unexpected len %d expected %d",
                                  type, nla_len(nla), expected_len);
                        return -EINVAL;
@@ -473,29 +486,50 @@ static int genev_tun_opt_from_nlattr(const struct nlattr *a,
        return 0;
 }
 
-static const struct nla_policy vxlan_opt_policy[OVS_VXLAN_EXT_MAX + 1] = {
-       [OVS_VXLAN_EXT_GBP]     = { .type = NLA_U32 },
-};
-
-static int vxlan_tun_opt_from_nlattr(const struct nlattr *a,
+static int vxlan_tun_opt_from_nlattr(const struct nlattr *attr,
                                     struct sw_flow_match *match, bool is_mask,
                                     bool log)
 {
-       struct nlattr *tb[OVS_VXLAN_EXT_MAX+1];
+       struct nlattr *a;
+       int rem;
        unsigned long opt_key_offset;
        struct vxlan_metadata opts;
-       int err;
 
        BUILD_BUG_ON(sizeof(opts) > sizeof(match->key->tun_opts));
 
-       err = nla_parse_nested(tb, OVS_VXLAN_EXT_MAX, a, vxlan_opt_policy);
-       if (err < 0)
-               return err;
-
        memset(&opts, 0, sizeof(opts));
+       nla_for_each_nested(a, attr, rem) {
+               int type = nla_type(a);
 
-       if (tb[OVS_VXLAN_EXT_GBP])
-               opts.gbp = nla_get_u32(tb[OVS_VXLAN_EXT_GBP]);
+               if (type > OVS_VXLAN_EXT_MAX) {
+                       OVS_NLERR(log, "VXLAN extension %d out of range max %d",
+                                 type, OVS_VXLAN_EXT_MAX);
+                       return -EINVAL;
+               }
+
+               if (!check_attr_len(nla_len(a),
+                                   ovs_vxlan_ext_key_lens[type].len)) {
+                       OVS_NLERR(log, "VXLAN extension %d has unexpected len %d expected %d",
+                                 type, nla_len(a),
+                                 ovs_vxlan_ext_key_lens[type].len);
+                       return -EINVAL;
+               }
+
+               switch (type) {
+               case OVS_VXLAN_EXT_GBP:
+                       opts.gbp = nla_get_u32(a);
+                       break;
+               default:
+                       OVS_NLERR(log, "Unknown VXLAN extension attribute %d",
+                                 type);
+                       return -EINVAL;
+               }
+       }
+       if (rem) {
+               OVS_NLERR(log, "VXLAN extension message has %d unknown bytes.",
+                         rem);
+               return -EINVAL;
+       }
 
        if (!is_mask)
                SW_FLOW_KEY_PUT(match, tun_opts_len, sizeof(opts), false);
@@ -528,8 +562,8 @@ static int ipv4_tun_from_nlattr(const struct nlattr *attr,
                        return -EINVAL;
                }
 
-               if (ovs_tunnel_key_lens[type].len != nla_len(a) &&
-                   ovs_tunnel_key_lens[type].len != OVS_ATTR_NESTED) {
+               if (!check_attr_len(nla_len(a),
+                                   ovs_tunnel_key_lens[type].len)) {
                        OVS_NLERR(log, "Tunnel attr %d has unexpected len %d expected %d",
                                  type, nla_len(a), ovs_tunnel_key_lens[type].len);
                        return -EINVAL;
@@ -683,7 +717,7 @@ static int __ipv4_tun_to_nlattr(struct sk_buff *skb,
        if ((output->tun_flags & TUNNEL_OAM) &&
            nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_OAM))
                return -EMSGSIZE;
-       if (tun_opts) {
+       if (swkey_tun_opts_len) {
                if (output->tun_flags & TUNNEL_GENEVE_OPT &&
                    nla_put(skb, OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS,
                            swkey_tun_opts_len, tun_opts))
@@ -715,13 +749,12 @@ static int ipv4_tun_to_nlattr(struct sk_buff *skb,
        return 0;
 }
 
-int ovs_nla_put_egress_tunnel_key(struct sk_buff *skb,
-                                 const struct ip_tunnel_info *egress_tun_info,
-                                 const void *egress_tun_opts)
+int ovs_nla_put_tunnel_info(struct sk_buff *skb,
+                           struct ip_tunnel_info *tun_info)
 {
-       return __ipv4_tun_to_nlattr(skb, &egress_tun_info->key,
-                                   egress_tun_opts,
-                                   egress_tun_info->options_len);
+       return __ipv4_tun_to_nlattr(skb, &tun_info->key,
+                                   ip_tunnel_info_opts(tun_info),
+                                   tun_info->options_len);
 }
 
 static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
@@ -780,7 +813,13 @@ static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
 
        if (*attrs & (1 << OVS_KEY_ATTR_CT_STATE) &&
            ovs_ct_verify(net, OVS_KEY_ATTR_CT_STATE)) {
-               u8 ct_state = nla_get_u8(a[OVS_KEY_ATTR_CT_STATE]);
+               u32 ct_state = nla_get_u32(a[OVS_KEY_ATTR_CT_STATE]);
+
+               if (ct_state & ~CT_SUPPORTED_MASK) {
+                       OVS_NLERR(log, "ct_state flags %08x unsupported",
+                                 ct_state);
+                       return -EINVAL;
+               }
 
                SW_FLOW_KEY_PUT(match, ct.state, ct_state, is_mask);
                *attrs &= ~(1ULL << OVS_KEY_ATTR_CT_STATE);
@@ -799,14 +838,14 @@ static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
                SW_FLOW_KEY_PUT(match, ct.mark, mark, is_mask);
                *attrs &= ~(1ULL << OVS_KEY_ATTR_CT_MARK);
        }
-       if (*attrs & (1 << OVS_KEY_ATTR_CT_LABEL) &&
-           ovs_ct_verify(net, OVS_KEY_ATTR_CT_LABEL)) {
-               const struct ovs_key_ct_label *cl;
+       if (*attrs & (1 << OVS_KEY_ATTR_CT_LABELS) &&
+           ovs_ct_verify(net, OVS_KEY_ATTR_CT_LABELS)) {
+               const struct ovs_key_ct_labels *cl;
 
-               cl = nla_data(a[OVS_KEY_ATTR_CT_LABEL]);
-               SW_FLOW_KEY_MEMCPY(match, ct.label, cl->ct_label,
+               cl = nla_data(a[OVS_KEY_ATTR_CT_LABELS]);
+               SW_FLOW_KEY_MEMCPY(match, ct.labels, cl->ct_labels,
                                   sizeof(*cl), is_mask);
-               *attrs &= ~(1ULL << OVS_KEY_ATTR_CT_LABEL);
+               *attrs &= ~(1ULL << OVS_KEY_ATTR_CT_LABELS);
        }
        return 0;
 }
@@ -1052,10 +1091,16 @@ static void nlattr_set(struct nlattr *attr, u8 val,
 
        /* The nlattr stream should already have been validated */
        nla_for_each_nested(nla, attr, rem) {
-               if (tbl && tbl[nla_type(nla)].len == OVS_ATTR_NESTED)
-                       nlattr_set(nla, val, tbl[nla_type(nla)].next);
-               else
+               if (tbl[nla_type(nla)].len == OVS_ATTR_NESTED) {
+                       if (tbl[nla_type(nla)].next)
+                               tbl = tbl[nla_type(nla)].next;
+                       nlattr_set(nla, val, tbl);
+               } else {
                        memset(nla_data(nla), val, nla_len(nla));
+               }
+
+               if (nla_type(nla) == OVS_KEY_ATTR_CT_STATE)
+                       *(u32 *)nla_data(nla) &= CT_SUPPORTED_MASK;
        }
 }
 
@@ -1922,8 +1967,7 @@ static int validate_set(const struct nlattr *a,
                key_len /= 2;
 
        if (key_type > OVS_KEY_ATTR_MAX ||
-           (ovs_key_lens[key_type].len != key_len &&
-            ovs_key_lens[key_type].len != OVS_ATTR_NESTED))
+           !check_attr_len(key_len, ovs_key_lens[key_type].len))
                return -EINVAL;
 
        if (masked && !validate_masked(nla_data(ovs_key), key_len))
@@ -1937,7 +1981,7 @@ static int validate_set(const struct nlattr *a,
        case OVS_KEY_ATTR_PRIORITY:
        case OVS_KEY_ATTR_SKB_MARK:
        case OVS_KEY_ATTR_CT_MARK:
-       case OVS_KEY_ATTR_CT_LABEL:
+       case OVS_KEY_ATTR_CT_LABELS:
        case OVS_KEY_ATTR_ETHERNET:
                break;
 
@@ -2338,10 +2382,7 @@ static int set_action_to_attr(const struct nlattr *a, struct sk_buff *skb)
                if (!start)
                        return -EMSGSIZE;
 
-               err = ipv4_tun_to_nlattr(skb, &tun_info->key,
-                                        tun_info->options_len ?
-                                            ip_tunnel_info_opts(tun_info) : NULL,
-                                        tun_info->options_len);
+               err = ovs_nla_put_tunnel_info(skb, tun_info);
                if (err)
                        return err;
                nla_nest_end(skb, start);
index 6ca3f0baf449f05f82dd92f9796cd8cfa7abf141..47dd142eca1c0856c74406e1d75682fc822861f6 100644 (file)
@@ -55,9 +55,9 @@ int ovs_nla_put_mask(const struct sw_flow *flow, struct sk_buff *skb);
 int ovs_nla_get_match(struct net *, struct sw_flow_match *,
                      const struct nlattr *key, const struct nlattr *mask,
                      bool log);
-int ovs_nla_put_egress_tunnel_key(struct sk_buff *,
-                                 const struct ip_tunnel_info *,
-                                 const void *egress_tun_opts);
+
+int ovs_nla_put_tunnel_info(struct sk_buff *skb,
+                           struct ip_tunnel_info *tun_info);
 
 bool ovs_nla_get_ufid(struct sw_flow_id *, const struct nlattr *, bool log);
 int ovs_nla_get_identifier(struct sw_flow_id *sfid, const struct nlattr *ufid,
index d22d8e948d0f4b126894a71f8dcc30bc7d6d024d..c7f74aab34b9ef7d2befcd571d44290b76fbfbc1 100644 (file)
@@ -57,20 +57,21 @@ static u16 range_n_bytes(const struct sw_flow_key_range *range)
 }
 
 void ovs_flow_mask_key(struct sw_flow_key *dst, const struct sw_flow_key *src,
-                      const struct sw_flow_mask *mask)
+                      bool full, const struct sw_flow_mask *mask)
 {
-       const long *m = (const long *)((const u8 *)&mask->key +
-                               mask->range.start);
-       const long *s = (const long *)((const u8 *)src +
-                               mask->range.start);
-       long *d = (long *)((u8 *)dst + mask->range.start);
+       int start = full ? 0 : mask->range.start;
+       int len = full ? sizeof *dst : range_n_bytes(&mask->range);
+       const long *m = (const long *)((const u8 *)&mask->key + start);
+       const long *s = (const long *)((const u8 *)src + start);
+       long *d = (long *)((u8 *)dst + start);
        int i;
 
-       /* The memory outside of the 'mask->range' are not set since
-        * further operations on 'dst' only uses contents within
-        * 'mask->range'.
+       /* If 'full' is true then all of 'dst' is fully initialized. Otherwise,
+        * if 'full' is false the memory outside of the 'mask->range' is left
+        * uninitialized. This can be used as an optimization when further
+        * operations on 'dst' only use contents within 'mask->range'.
         */
-       for (i = 0; i < range_n_bytes(&mask->range); i += sizeof(long))
+       for (i = 0; i < len; i += sizeof(long))
                *d++ = *s++ & *m++;
 }
 
@@ -92,7 +93,8 @@ struct sw_flow *ovs_flow_alloc(void)
 
        /* Initialize the default stat node. */
        stats = kmem_cache_alloc_node(flow_stats_cache,
-                                     GFP_KERNEL | __GFP_ZERO, 0);
+                                     GFP_KERNEL | __GFP_ZERO,
+                                     node_online(0) ? 0 : NUMA_NO_NODE);
        if (!stats)
                goto err;
 
@@ -475,7 +477,7 @@ static struct sw_flow *masked_flow_lookup(struct table_instance *ti,
        u32 hash;
        struct sw_flow_key masked_key;
 
-       ovs_flow_mask_key(&masked_key, unmasked, mask);
+       ovs_flow_mask_key(&masked_key, unmasked, false, mask);
        hash = flow_hash(&masked_key, &mask->range);
        head = find_bucket(ti, hash);
        hlist_for_each_entry_rcu(flow, head, flow_table.node[ti->node_ver]) {
index 616eda10d9554d1e519d38b65f04352bc1f8796d..2dd9900f533df364fb5fb7b1772b9805b28092cc 100644 (file)
@@ -86,5 +86,5 @@ struct sw_flow *ovs_flow_tbl_lookup_ufid(struct flow_table *,
 bool ovs_flow_cmp(const struct sw_flow *, const struct sw_flow_match *);
 
 void ovs_flow_mask_key(struct sw_flow_key *dst, const struct sw_flow_key *src,
-                      const struct sw_flow_mask *mask);
+                      bool full, const struct sw_flow_mask *mask);
 #endif /* flow_table.h */
index 2735e9c4a3b88586165ef5644e429cf28079974d..5f8aaaaa0785385b89096925718d96b3335c1d32 100644 (file)
@@ -52,18 +52,6 @@ static int geneve_get_options(const struct vport *vport,
        return 0;
 }
 
-static int geneve_get_egress_tun_info(struct vport *vport, struct sk_buff *skb,
-                                     struct dp_upcall_info *upcall)
-{
-       struct geneve_port *geneve_port = geneve_vport(vport);
-       struct net *net = ovs_dp_get_net(vport->dp);
-       __be16 dport = htons(geneve_port->port_no);
-       __be16 sport = udp_flow_src_port(net, skb, 1, USHRT_MAX, true);
-
-       return ovs_tunnel_get_egress_info(upcall, ovs_dp_get_net(vport->dp),
-                                         skb, IPPROTO_UDP, sport, dport);
-}
-
 static struct vport *geneve_tnl_create(const struct vport_parms *parms)
 {
        struct net *net = ovs_dp_get_net(parms->dp);
@@ -130,7 +118,6 @@ static struct vport_ops ovs_geneve_vport_ops = {
        .get_options    = geneve_get_options,
        .send           = ovs_netdev_send,
        .owner          = THIS_MODULE,
-       .get_egress_tun_info    = geneve_get_egress_tun_info,
 };
 
 static int __init ovs_geneve_tnl_init(void)
index 4d24481669c95197b06bb75d207b3e713b433508..64225bf5eb405f4082547bbc8f09d920de72cdb8 100644 (file)
@@ -84,18 +84,10 @@ static struct vport *gre_create(const struct vport_parms *parms)
        return ovs_netdev_link(vport, parms->name);
 }
 
-static int gre_get_egress_tun_info(struct vport *vport, struct sk_buff *skb,
-                                  struct dp_upcall_info *upcall)
-{
-       return ovs_tunnel_get_egress_info(upcall, ovs_dp_get_net(vport->dp),
-                                         skb, IPPROTO_GRE, 0, 0);
-}
-
 static struct vport_ops ovs_gre_vport_ops = {
        .type           = OVS_VPORT_TYPE_GRE,
        .create         = gre_create,
        .send           = ovs_netdev_send,
-       .get_egress_tun_info    = gre_get_egress_tun_info,
        .destroy        = ovs_netdev_tunnel_destroy,
        .owner          = THIS_MODULE,
 };
index 388b8a6bf112979f7f7291c5bb17fd6c7027e594..b3934126daa894d7bdaf7511ece6ff5319cf2c8a 100644 (file)
@@ -106,12 +106,45 @@ static void internal_dev_destructor(struct net_device *dev)
        free_netdev(dev);
 }
 
+static struct rtnl_link_stats64 *
+internal_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
+{
+       int i;
+
+       memset(stats, 0, sizeof(*stats));
+       stats->rx_errors  = dev->stats.rx_errors;
+       stats->tx_errors  = dev->stats.tx_errors;
+       stats->tx_dropped = dev->stats.tx_dropped;
+       stats->rx_dropped = dev->stats.rx_dropped;
+
+       for_each_possible_cpu(i) {
+               const struct pcpu_sw_netstats *percpu_stats;
+               struct pcpu_sw_netstats local_stats;
+               unsigned int start;
+
+               percpu_stats = per_cpu_ptr(dev->tstats, i);
+
+               do {
+                       start = u64_stats_fetch_begin_irq(&percpu_stats->syncp);
+                       local_stats = *percpu_stats;
+               } while (u64_stats_fetch_retry_irq(&percpu_stats->syncp, start));
+
+               stats->rx_bytes         += local_stats.rx_bytes;
+               stats->rx_packets       += local_stats.rx_packets;
+               stats->tx_bytes         += local_stats.tx_bytes;
+               stats->tx_packets       += local_stats.tx_packets;
+       }
+
+       return stats;
+}
+
 static const struct net_device_ops internal_dev_netdev_ops = {
        .ndo_open = internal_dev_open,
        .ndo_stop = internal_dev_stop,
        .ndo_start_xmit = internal_dev_xmit,
        .ndo_set_mac_address = eth_mac_addr,
        .ndo_change_mtu = internal_dev_change_mtu,
+       .ndo_get_stats64 = internal_get_stats,
 };
 
 static struct rtnl_link_ops internal_dev_link_ops __read_mostly = {
@@ -161,6 +194,11 @@ static struct vport *internal_dev_create(const struct vport_parms *parms)
                err = -ENOMEM;
                goto error_free_vport;
        }
+       vport->dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
+       if (!vport->dev->tstats) {
+               err = -ENOMEM;
+               goto error_free_netdev;
+       }
 
        dev_net_set(vport->dev, ovs_dp_get_net(vport->dp));
        internal_dev = internal_dev_priv(vport->dev);
@@ -173,7 +211,7 @@ static struct vport *internal_dev_create(const struct vport_parms *parms)
        rtnl_lock();
        err = register_netdevice(vport->dev);
        if (err)
-               goto error_free_netdev;
+               goto error_unlock;
 
        dev_set_promiscuity(vport->dev, 1);
        rtnl_unlock();
@@ -181,8 +219,10 @@ static struct vport *internal_dev_create(const struct vport_parms *parms)
 
        return vport;
 
-error_free_netdev:
+error_unlock:
        rtnl_unlock();
+       free_percpu(vport->dev->tstats);
+error_free_netdev:
        free_netdev(vport->dev);
 error_free_vport:
        ovs_vport_free(vport);
@@ -198,7 +238,7 @@ static void internal_dev_destroy(struct vport *vport)
 
        /* unregister_netdevice() waits for an RCU grace period. */
        unregister_netdevice(vport->dev);
-
+       free_percpu(vport->dev->tstats);
        rtnl_unlock();
 }
 
index c11413d5075f882c2b360515285ba520a7303d0c..e1c9c08880373276e8430cadd93f03fe4a1e11a0 100644 (file)
@@ -146,31 +146,12 @@ static struct vport *vxlan_create(const struct vport_parms *parms)
        return ovs_netdev_link(vport, parms->name);
 }
 
-static int vxlan_get_egress_tun_info(struct vport *vport, struct sk_buff *skb,
-                                    struct dp_upcall_info *upcall)
-{
-       struct vxlan_dev *vxlan = netdev_priv(vport->dev);
-       struct net *net = ovs_dp_get_net(vport->dp);
-       __be16 dst_port = vxlan_dev_dst_port(vxlan);
-       __be16 src_port;
-       int port_min;
-       int port_max;
-
-       inet_get_local_port_range(net, &port_min, &port_max);
-       src_port = udp_flow_src_port(net, skb, 0, 0, true);
-
-       return ovs_tunnel_get_egress_info(upcall, net,
-                                         skb, IPPROTO_UDP,
-                                         src_port, dst_port);
-}
-
 static struct vport_ops ovs_vxlan_netdev_vport_ops = {
        .type                   = OVS_VPORT_TYPE_VXLAN,
        .create                 = vxlan_create,
        .destroy                = ovs_netdev_tunnel_destroy,
        .get_options            = vxlan_get_options,
        .send                   = ovs_netdev_send,
-       .get_egress_tun_info    = vxlan_get_egress_tun_info,
 };
 
 static int __init ovs_vxlan_tnl_init(void)
index dc81dc619aa2344a5c7912def9d6852fcd37ebda..320c765ce44a07e71daedfd457d37c81ea2e4c49 100644 (file)
@@ -280,35 +280,19 @@ void ovs_vport_del(struct vport *vport)
  */
 void ovs_vport_get_stats(struct vport *vport, struct ovs_vport_stats *stats)
 {
-       struct net_device *dev = vport->dev;
-       int i;
-
-       memset(stats, 0, sizeof(*stats));
-       stats->rx_errors  = dev->stats.rx_errors;
-       stats->tx_errors  = dev->stats.tx_errors;
-       stats->tx_dropped = dev->stats.tx_dropped;
-       stats->rx_dropped = dev->stats.rx_dropped;
-
-       stats->rx_dropped += atomic_long_read(&dev->rx_dropped);
-       stats->tx_dropped += atomic_long_read(&dev->tx_dropped);
-
-       for_each_possible_cpu(i) {
-               const struct pcpu_sw_netstats *percpu_stats;
-               struct pcpu_sw_netstats local_stats;
-               unsigned int start;
-
-               percpu_stats = per_cpu_ptr(dev->tstats, i);
-
-               do {
-                       start = u64_stats_fetch_begin_irq(&percpu_stats->syncp);
-                       local_stats = *percpu_stats;
-               } while (u64_stats_fetch_retry_irq(&percpu_stats->syncp, start));
-
-               stats->rx_bytes         += local_stats.rx_bytes;
-               stats->rx_packets       += local_stats.rx_packets;
-               stats->tx_bytes         += local_stats.tx_bytes;
-               stats->tx_packets       += local_stats.tx_packets;
-       }
+       const struct rtnl_link_stats64 *dev_stats;
+       struct rtnl_link_stats64 temp;
+
+       dev_stats = dev_get_stats(vport->dev, &temp);
+       stats->rx_errors  = dev_stats->rx_errors;
+       stats->tx_errors  = dev_stats->tx_errors;
+       stats->tx_dropped = dev_stats->tx_dropped;
+       stats->rx_dropped = dev_stats->rx_dropped;
+
+       stats->rx_bytes   = dev_stats->rx_bytes;
+       stats->rx_packets = dev_stats->rx_packets;
+       stats->tx_bytes   = dev_stats->tx_bytes;
+       stats->tx_packets = dev_stats->tx_packets;
 }
 
 /**
@@ -460,6 +444,15 @@ int ovs_vport_receive(struct vport *vport, struct sk_buff *skb,
 
        OVS_CB(skb)->input_vport = vport;
        OVS_CB(skb)->mru = 0;
+       if (unlikely(dev_net(skb->dev) != ovs_dp_get_net(vport->dp))) {
+               u32 mark;
+
+               mark = skb->mark;
+               skb_scrub_packet(skb, true);
+               skb->mark = mark;
+               tun_info = NULL;
+       }
+
        /* Extract flow from 'skb' into 'key'. */
        error = ovs_flow_key_extract(tun_info, skb, &key);
        if (unlikely(error)) {
@@ -486,61 +479,3 @@ void ovs_vport_deferred_free(struct vport *vport)
        call_rcu(&vport->rcu, free_vport_rcu);
 }
 EXPORT_SYMBOL_GPL(ovs_vport_deferred_free);
-
-int ovs_tunnel_get_egress_info(struct dp_upcall_info *upcall,
-                              struct net *net,
-                              struct sk_buff *skb,
-                              u8 ipproto,
-                              __be16 tp_src,
-                              __be16 tp_dst)
-{
-       struct ip_tunnel_info *egress_tun_info = upcall->egress_tun_info;
-       const struct ip_tunnel_info *tun_info = skb_tunnel_info(skb);
-       const struct ip_tunnel_key *tun_key;
-       u32 skb_mark = skb->mark;
-       struct rtable *rt;
-       struct flowi4 fl;
-
-       if (unlikely(!tun_info))
-               return -EINVAL;
-       if (ip_tunnel_info_af(tun_info) != AF_INET)
-               return -EINVAL;
-
-       tun_key = &tun_info->key;
-
-       /* Route lookup to get srouce IP address.
-        * The process may need to be changed if the corresponding process
-        * in vports ops changed.
-        */
-       rt = ovs_tunnel_route_lookup(net, tun_key, skb_mark, &fl, ipproto);
-       if (IS_ERR(rt))
-               return PTR_ERR(rt);
-
-       ip_rt_put(rt);
-
-       /* Generate egress_tun_info based on tun_info,
-        * saddr, tp_src and tp_dst
-        */
-       ip_tunnel_key_init(&egress_tun_info->key,
-                          fl.saddr, tun_key->u.ipv4.dst,
-                          tun_key->tos,
-                          tun_key->ttl,
-                          tp_src, tp_dst,
-                          tun_key->tun_id,
-                          tun_key->tun_flags);
-       egress_tun_info->options_len = tun_info->options_len;
-       egress_tun_info->mode = tun_info->mode;
-       upcall->egress_tun_opts = ip_tunnel_info_opts(egress_tun_info);
-       return 0;
-}
-EXPORT_SYMBOL_GPL(ovs_tunnel_get_egress_info);
-
-int ovs_vport_get_egress_tun_info(struct vport *vport, struct sk_buff *skb,
-                                 struct dp_upcall_info *upcall)
-{
-       /* get_egress_tun_info() is only implemented on tunnel ports. */
-       if (unlikely(!vport->ops->get_egress_tun_info))
-               return -EINVAL;
-
-       return vport->ops->get_egress_tun_info(vport, skb, upcall);
-}
index a413f3ae6a7b540ed7b34fd4b31f69424caeb39f..d341ad6f3afe5734f587c1df347fd72dc2ba2c38 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/skbuff.h>
 #include <linux/spinlock.h>
 #include <linux/u64_stats_sync.h>
-#include <net/route.h>
 
 #include "datapath.h"
 
@@ -53,16 +52,6 @@ int ovs_vport_set_upcall_portids(struct vport *, const struct nlattr *pids);
 int ovs_vport_get_upcall_portids(const struct vport *, struct sk_buff *);
 u32 ovs_vport_find_upcall_portid(const struct vport *, struct sk_buff *);
 
-int ovs_tunnel_get_egress_info(struct dp_upcall_info *upcall,
-                              struct net *net,
-                              struct sk_buff *,
-                              u8 ipproto,
-                              __be16 tp_src,
-                              __be16 tp_dst);
-
-int ovs_vport_get_egress_tun_info(struct vport *vport, struct sk_buff *skb,
-                                 struct dp_upcall_info *upcall);
-
 /**
  * struct vport_portids - array of netlink portids of a vport.
  *                        must be protected by rcu.
@@ -140,8 +129,6 @@ struct vport_parms {
  * have any configuration.
  * @send: Send a packet on the device.
  * zero for dropped packets or negative for error.
- * @get_egress_tun_info: Get the egress tunnel 5-tuple and other info for
- * a packet.
  */
 struct vport_ops {
        enum ovs_vport_type type;
@@ -154,9 +141,6 @@ struct vport_ops {
        int (*get_options)(const struct vport *, struct sk_buff *);
 
        void (*send)(struct vport *, struct sk_buff *);
-       int (*get_egress_tun_info)(struct vport *, struct sk_buff *,
-                                  struct dp_upcall_info *upcall);
-
        struct module *owner;
        struct list_head list;
 };
@@ -215,25 +199,6 @@ static inline const char *ovs_vport_name(struct vport *vport)
 int ovs_vport_ops_register(struct vport_ops *ops);
 void ovs_vport_ops_unregister(struct vport_ops *ops);
 
-static inline struct rtable *ovs_tunnel_route_lookup(struct net *net,
-                                                    const struct ip_tunnel_key *key,
-                                                    u32 mark,
-                                                    struct flowi4 *fl,
-                                                    u8 protocol)
-{
-       struct rtable *rt;
-
-       memset(fl, 0, sizeof(*fl));
-       fl->daddr = key->u.ipv4.dst;
-       fl->saddr = key->u.ipv4.src;
-       fl->flowi4_tos = RT_TOS(key->tos);
-       fl->flowi4_mark = mark;
-       fl->flowi4_proto = protocol;
-
-       rt = ip_route_output_key(net, fl);
-       return rt;
-}
-
 static inline void ovs_vport_send(struct vport *vport, struct sk_buff *skb)
 {
        vport->ops->send(vport, skb);
index 7b8e39a223879c3cb0a9d2a0bc6ff003118379f9..aa4b15c3588445ae67568d35bddbeed6a3508cbd 100644 (file)
@@ -230,6 +230,8 @@ struct packet_skb_cb {
        } sa;
 };
 
+#define vio_le() virtio_legacy_is_little_endian()
+
 #define PACKET_SKB_CB(__skb)   ((struct packet_skb_cb *)((__skb)->cb))
 
 #define GET_PBDQC_FROM_RB(x)   ((struct tpacket_kbdq_core *)(&(x)->prb_bdqc))
@@ -2680,15 +2682,15 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
                        goto out_unlock;
 
                if ((vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) &&
-                   (__virtio16_to_cpu(false, vnet_hdr.csum_start) +
-                    __virtio16_to_cpu(false, vnet_hdr.csum_offset) + 2 >
-                     __virtio16_to_cpu(false, vnet_hdr.hdr_len)))
-                       vnet_hdr.hdr_len = __cpu_to_virtio16(false,
-                                __virtio16_to_cpu(false, vnet_hdr.csum_start) +
-                               __virtio16_to_cpu(false, vnet_hdr.csum_offset) + 2);
+                   (__virtio16_to_cpu(vio_le(), vnet_hdr.csum_start) +
+                    __virtio16_to_cpu(vio_le(), vnet_hdr.csum_offset) + 2 >
+                     __virtio16_to_cpu(vio_le(), vnet_hdr.hdr_len)))
+                       vnet_hdr.hdr_len = __cpu_to_virtio16(vio_le(),
+                                __virtio16_to_cpu(vio_le(), vnet_hdr.csum_start) +
+                               __virtio16_to_cpu(vio_le(), vnet_hdr.csum_offset) + 2);
 
                err = -EINVAL;
-               if (__virtio16_to_cpu(false, vnet_hdr.hdr_len) > len)
+               if (__virtio16_to_cpu(vio_le(), vnet_hdr.hdr_len) > len)
                        goto out_unlock;
 
                if (vnet_hdr.gso_type != VIRTIO_NET_HDR_GSO_NONE) {
@@ -2731,7 +2733,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
        hlen = LL_RESERVED_SPACE(dev);
        tlen = dev->needed_tailroom;
        skb = packet_alloc_skb(sk, hlen + tlen, hlen, len,
-                              __virtio16_to_cpu(false, vnet_hdr.hdr_len),
+                              __virtio16_to_cpu(vio_le(), vnet_hdr.hdr_len),
                               msg->msg_flags & MSG_DONTWAIT, &err);
        if (skb == NULL)
                goto out_unlock;
@@ -2778,8 +2780,8 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
 
        if (po->has_vnet_hdr) {
                if (vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) {
-                       u16 s = __virtio16_to_cpu(false, vnet_hdr.csum_start);
-                       u16 o = __virtio16_to_cpu(false, vnet_hdr.csum_offset);
+                       u16 s = __virtio16_to_cpu(vio_le(), vnet_hdr.csum_start);
+                       u16 o = __virtio16_to_cpu(vio_le(), vnet_hdr.csum_offset);
                        if (!skb_partial_csum_set(skb, s, o)) {
                                err = -EINVAL;
                                goto out_free;
@@ -2787,7 +2789,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
                }
 
                skb_shinfo(skb)->gso_size =
-                       __virtio16_to_cpu(false, vnet_hdr.gso_size);
+                       __virtio16_to_cpu(vio_le(), vnet_hdr.gso_size);
                skb_shinfo(skb)->gso_type = gso_type;
 
                /* Header must be checked, and gso_segs computed. */
@@ -3161,9 +3163,9 @@ static int packet_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
 
                        /* This is a hint as to how much should be linear. */
                        vnet_hdr.hdr_len =
-                               __cpu_to_virtio16(false, skb_headlen(skb));
+                               __cpu_to_virtio16(vio_le(), skb_headlen(skb));
                        vnet_hdr.gso_size =
-                               __cpu_to_virtio16(false, sinfo->gso_size);
+                               __cpu_to_virtio16(vio_le(), sinfo->gso_size);
                        if (sinfo->gso_type & SKB_GSO_TCPV4)
                                vnet_hdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
                        else if (sinfo->gso_type & SKB_GSO_TCPV6)
@@ -3181,9 +3183,9 @@ static int packet_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
 
                if (skb->ip_summed == CHECKSUM_PARTIAL) {
                        vnet_hdr.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
-                       vnet_hdr.csum_start = __cpu_to_virtio16(false,
+                       vnet_hdr.csum_start = __cpu_to_virtio16(vio_le(),
                                          skb_checksum_start_offset(skb));
-                       vnet_hdr.csum_offset = __cpu_to_virtio16(false,
+                       vnet_hdr.csum_offset = __cpu_to_virtio16(vio_le(),
                                                         skb->csum_offset);
                } else if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
                        vnet_hdr.flags = VIRTIO_NET_HDR_F_DATA_VALID;
index fbc5ef88bc0e692ea4cf9cb59f6163905510928e..27a992154804c685d983206b599ef7a5bf96e8af 100644 (file)
@@ -214,8 +214,15 @@ static int rds_tcp_data_recv(read_descriptor_t *desc, struct sk_buff *skb,
                        }
 
                        to_copy = min(tc->t_tinc_data_rem, left);
-                       pskb_pull(clone, offset);
-                       pskb_trim(clone, to_copy);
+                       if (!pskb_pull(clone, offset) ||
+                           pskb_trim(clone, to_copy)) {
+                               pr_warn("rds_tcp_data_recv: pull/trim failed "
+                                       "left %zu data_rem %zu skb_len %d\n",
+                                       left, tc->t_tinc_data_rem, skb->len);
+                               kfree_skb(clone);
+                               desc->error = -ENOMEM;
+                               goto out;
+                       }
                        skb_queue_tail(&tinc->ti_skb_list, clone);
 
                        rdsdebug("skb %p data %p len %d off %u to_copy %zu -> "
index 2d1be4a760fdc4361f23d0aa93a861298eaafe45..32fcdecdb9e2074bad6f3e3002738e9c289317c3 100644 (file)
 
 #define MIRRED_TAB_MASK     7
 static LIST_HEAD(mirred_list);
+static DEFINE_SPINLOCK(mirred_list_lock);
 
 static void tcf_mirred_release(struct tc_action *a, int bind)
 {
        struct tcf_mirred *m = to_mirred(a);
        struct net_device *dev = rcu_dereference_protected(m->tcfm_dev, 1);
 
+       /* We could be called either in a RCU callback or with RTNL lock held. */
+       spin_lock_bh(&mirred_list_lock);
        list_del(&m->tcfm_list);
+       spin_unlock_bh(&mirred_list_lock);
        if (dev)
                dev_put(dev);
 }
@@ -103,10 +107,10 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
        } else {
                if (bind)
                        return 0;
-               if (!ovr) {
-                       tcf_hash_release(a, bind);
+
+               tcf_hash_release(a, bind);
+               if (!ovr)
                        return -EEXIST;
-               }
        }
        m = to_mirred(a);
 
@@ -123,7 +127,9 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
        }
 
        if (ret == ACT_P_CREATED) {
+               spin_lock_bh(&mirred_list_lock);
                list_add(&m->tcfm_list, &mirred_list);
+               spin_unlock_bh(&mirred_list_lock);
                tcf_hash_insert(a);
        }
 
@@ -173,6 +179,7 @@ static int tcf_mirred(struct sk_buff *skb, const struct tc_action *a,
 
        skb2->skb_iif = skb->dev->ifindex;
        skb2->dev = dev;
+       skb_sender_cpu_clear(skb2);
        err = dev_queue_xmit(skb2);
 
        if (err) {
@@ -221,7 +228,8 @@ static int mirred_device_event(struct notifier_block *unused,
        struct tcf_mirred *m;
 
        ASSERT_RTNL();
-       if (event == NETDEV_UNREGISTER)
+       if (event == NETDEV_UNREGISTER) {
+               spin_lock_bh(&mirred_list_lock);
                list_for_each_entry(m, &mirred_list, tcfm_list) {
                        if (rcu_access_pointer(m->tcfm_dev) == dev) {
                                dev_put(dev);
@@ -231,6 +239,8 @@ static int mirred_device_event(struct notifier_block *unused,
                                RCU_INIT_POINTER(m->tcfm_dev, NULL);
                        }
                }
+               spin_unlock_bh(&mirred_list_lock);
+       }
 
        return NOTIFY_DONE;
 }
index 715e01e5910a94a9af40534ec5c0e820b96adc99..f23a3b68bba63b6ea68223f00a1b851186e307b5 100644 (file)
@@ -33,7 +33,6 @@
 
 struct fw_head {
        u32                     mask;
-       bool                    mask_set;
        struct fw_filter __rcu  *ht[HTSIZE];
        struct rcu_head         rcu;
 };
@@ -84,7 +83,7 @@ static int fw_classify(struct sk_buff *skb, const struct tcf_proto *tp,
                        }
                }
        } else {
-               /* old method */
+               /* Old method: classify the packet using its skb mark. */
                if (id && (TC_H_MAJ(id) == 0 ||
                           !(TC_H_MAJ(id ^ tp->q->handle)))) {
                        res->classid = id;
@@ -114,14 +113,9 @@ static unsigned long fw_get(struct tcf_proto *tp, u32 handle)
 
 static int fw_init(struct tcf_proto *tp)
 {
-       struct fw_head *head;
-
-       head = kzalloc(sizeof(struct fw_head), GFP_KERNEL);
-       if (head == NULL)
-               return -ENOBUFS;
-
-       head->mask_set = false;
-       rcu_assign_pointer(tp->root, head);
+       /* We don't allocate fw_head here, because in the old method
+        * we don't need it at all.
+        */
        return 0;
 }
 
@@ -252,7 +246,7 @@ static int fw_change(struct net *net, struct sk_buff *in_skb,
        int err;
 
        if (!opt)
-               return handle ? -EINVAL : 0;
+               return handle ? -EINVAL : 0; /* Succeed if it is old method. */
 
        err = nla_parse_nested(tb, TCA_FW_MAX, opt, fw_policy);
        if (err < 0)
@@ -302,11 +296,17 @@ static int fw_change(struct net *net, struct sk_buff *in_skb,
        if (!handle)
                return -EINVAL;
 
-       if (!head->mask_set) {
-               head->mask = 0xFFFFFFFF;
+       if (!head) {
+               u32 mask = 0xFFFFFFFF;
                if (tb[TCA_FW_MASK])
-                       head->mask = nla_get_u32(tb[TCA_FW_MASK]);
-               head->mask_set = true;
+                       mask = nla_get_u32(tb[TCA_FW_MASK]);
+
+               head = kzalloc(sizeof(*head), GFP_KERNEL);
+               if (!head)
+                       return -ENOBUFS;
+               head->mask = mask;
+
+               rcu_assign_pointer(tp->root, head);
        }
 
        f = kzalloc(sizeof(struct fw_filter), GFP_KERNEL);
index 9d15cb6b8cb1f5e8424e96f6245e9dd206d92405..86b04e31e60b76027214b85ee0c4c0e0de1b04c4 100644 (file)
@@ -368,6 +368,15 @@ static unsigned int hhf_drop(struct Qdisc *sch)
        return bucket - q->buckets;
 }
 
+static unsigned int hhf_qdisc_drop(struct Qdisc *sch)
+{
+       unsigned int prev_backlog;
+
+       prev_backlog = sch->qstats.backlog;
+       hhf_drop(sch);
+       return prev_backlog - sch->qstats.backlog;
+}
+
 static int hhf_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 {
        struct hhf_sched_data *q = qdisc_priv(sch);
@@ -696,7 +705,7 @@ static struct Qdisc_ops hhf_qdisc_ops __read_mostly = {
        .enqueue        =       hhf_enqueue,
        .dequeue        =       hhf_dequeue,
        .peek           =       qdisc_peek_dequeued,
-       .drop           =       hhf_drop,
+       .drop           =       hhf_qdisc_drop,
        .init           =       hhf_init,
        .reset          =       hhf_reset,
        .destroy        =       hhf_destroy,
index 197c3f59ecbf1d7975a987e57c13023ac9e2b357..b00f1f9611d64a7f46fdd37460d9c5ec9711f37f 100644 (file)
@@ -1208,20 +1208,22 @@ void sctp_assoc_update(struct sctp_association *asoc,
  *   within this document.
  *
  * Our basic strategy is to round-robin transports in priorities
- * according to sctp_state_prio_map[] e.g., if no such
+ * according to sctp_trans_score() e.g., if no such
  * transport with state SCTP_ACTIVE exists, round-robin through
  * SCTP_UNKNOWN, etc. You get the picture.
  */
-static const u8 sctp_trans_state_to_prio_map[] = {
-       [SCTP_ACTIVE]   = 3,    /* best case */
-       [SCTP_UNKNOWN]  = 2,
-       [SCTP_PF]       = 1,
-       [SCTP_INACTIVE] = 0,    /* worst case */
-};
-
 static u8 sctp_trans_score(const struct sctp_transport *trans)
 {
-       return sctp_trans_state_to_prio_map[trans->state];
+       switch (trans->state) {
+       case SCTP_ACTIVE:
+               return 3;       /* best case */
+       case SCTP_UNKNOWN:
+               return 2;
+       case SCTP_PF:
+               return 1;
+       default: /* case SCTP_INACTIVE */
+               return 0;       /* worst case */
+       }
 }
 
 static struct sctp_transport *sctp_trans_elect_tie(struct sctp_transport *trans1,
index b7143337e4fa025fdb473732fdc064503e731dd4..3d9ea9a48289af7324d2c96d82938dd978634ce5 100644 (file)
@@ -1186,7 +1186,7 @@ static void sctp_v4_del_protocol(void)
        unregister_inetaddr_notifier(&sctp_inetaddr_notifier);
 }
 
-static int __net_init sctp_net_init(struct net *net)
+static int __net_init sctp_defaults_init(struct net *net)
 {
        int status;
 
@@ -1279,12 +1279,6 @@ static int __net_init sctp_net_init(struct net *net)
 
        sctp_dbg_objcnt_init(net);
 
-       /* Initialize the control inode/socket for handling OOTB packets.  */
-       if ((status = sctp_ctl_sock_init(net))) {
-               pr_err("Failed to initialize the SCTP control sock\n");
-               goto err_ctl_sock_init;
-       }
-
        /* Initialize the local address list. */
        INIT_LIST_HEAD(&net->sctp.local_addr_list);
        spin_lock_init(&net->sctp.local_addr_lock);
@@ -1300,9 +1294,6 @@ static int __net_init sctp_net_init(struct net *net)
 
        return 0;
 
-err_ctl_sock_init:
-       sctp_dbg_objcnt_exit(net);
-       sctp_proc_exit(net);
 err_init_proc:
        cleanup_sctp_mibs(net);
 err_init_mibs:
@@ -1311,15 +1302,12 @@ err_sysctl_register:
        return status;
 }
 
-static void __net_exit sctp_net_exit(struct net *net)
+static void __net_exit sctp_defaults_exit(struct net *net)
 {
        /* Free the local address list */
        sctp_free_addr_wq(net);
        sctp_free_local_addr_list(net);
 
-       /* Free the control endpoint.  */
-       inet_ctl_sock_destroy(net->sctp.ctl_sock);
-
        sctp_dbg_objcnt_exit(net);
 
        sctp_proc_exit(net);
@@ -1327,9 +1315,32 @@ static void __net_exit sctp_net_exit(struct net *net)
        sctp_sysctl_net_unregister(net);
 }
 
-static struct pernet_operations sctp_net_ops = {
-       .init = sctp_net_init,
-       .exit = sctp_net_exit,
+static struct pernet_operations sctp_defaults_ops = {
+       .init = sctp_defaults_init,
+       .exit = sctp_defaults_exit,
+};
+
+static int __net_init sctp_ctrlsock_init(struct net *net)
+{
+       int status;
+
+       /* Initialize the control inode/socket for handling OOTB packets.  */
+       status = sctp_ctl_sock_init(net);
+       if (status)
+               pr_err("Failed to initialize the SCTP control sock\n");
+
+       return status;
+}
+
+static void __net_init sctp_ctrlsock_exit(struct net *net)
+{
+       /* Free the control endpoint.  */
+       inet_ctl_sock_destroy(net->sctp.ctl_sock);
+}
+
+static struct pernet_operations sctp_ctrlsock_ops = {
+       .init = sctp_ctrlsock_init,
+       .exit = sctp_ctrlsock_exit,
 };
 
 /* Initialize the universe into something sensible.  */
@@ -1462,8 +1473,11 @@ static __init int sctp_init(void)
        sctp_v4_pf_init();
        sctp_v6_pf_init();
 
-       status = sctp_v4_protosw_init();
+       status = register_pernet_subsys(&sctp_defaults_ops);
+       if (status)
+               goto err_register_defaults;
 
+       status = sctp_v4_protosw_init();
        if (status)
                goto err_protosw_init;
 
@@ -1471,9 +1485,9 @@ static __init int sctp_init(void)
        if (status)
                goto err_v6_protosw_init;
 
-       status = register_pernet_subsys(&sctp_net_ops);
+       status = register_pernet_subsys(&sctp_ctrlsock_ops);
        if (status)
-               goto err_register_pernet_subsys;
+               goto err_register_ctrlsock;
 
        status = sctp_v4_add_protocol();
        if (status)
@@ -1489,12 +1503,14 @@ out:
 err_v6_add_protocol:
        sctp_v4_del_protocol();
 err_add_protocol:
-       unregister_pernet_subsys(&sctp_net_ops);
-err_register_pernet_subsys:
+       unregister_pernet_subsys(&sctp_ctrlsock_ops);
+err_register_ctrlsock:
        sctp_v6_protosw_exit();
 err_v6_protosw_init:
        sctp_v4_protosw_exit();
 err_protosw_init:
+       unregister_pernet_subsys(&sctp_defaults_ops);
+err_register_defaults:
        sctp_v4_pf_exit();
        sctp_v6_pf_exit();
        sctp_sysctl_unregister();
@@ -1527,12 +1543,14 @@ static __exit void sctp_exit(void)
        sctp_v6_del_protocol();
        sctp_v4_del_protocol();
 
-       unregister_pernet_subsys(&sctp_net_ops);
+       unregister_pernet_subsys(&sctp_ctrlsock_ops);
 
        /* Free protosw registrations */
        sctp_v6_protosw_exit();
        sctp_v4_protosw_exit();
 
+       unregister_pernet_subsys(&sctp_defaults_ops);
+
        /* Unregister with socket layer. */
        sctp_v6_pf_exit();
        sctp_v4_pf_exit();
index 35df1266bf073aa9a7a4145da787ff42e95a7ee1..6098d4c42fa91287d3cde36ac05d860f76d4fe32 100644 (file)
@@ -244,12 +244,13 @@ void sctp_generate_t3_rtx_event(unsigned long peer)
        int error;
        struct sctp_transport *transport = (struct sctp_transport *) peer;
        struct sctp_association *asoc = transport->asoc;
-       struct net *net = sock_net(asoc->base.sk);
+       struct sock *sk = asoc->base.sk;
+       struct net *net = sock_net(sk);
 
        /* Check whether a task is in the sock.  */
 
-       bh_lock_sock(asoc->base.sk);
-       if (sock_owned_by_user(asoc->base.sk)) {
+       bh_lock_sock(sk);
+       if (sock_owned_by_user(sk)) {
                pr_debug("%s: sock is busy\n", __func__);
 
                /* Try again later.  */
@@ -272,10 +273,10 @@ void sctp_generate_t3_rtx_event(unsigned long peer)
                           transport, GFP_ATOMIC);
 
        if (error)
-               asoc->base.sk->sk_err = -error;
+               sk->sk_err = -error;
 
 out_unlock:
-       bh_unlock_sock(asoc->base.sk);
+       bh_unlock_sock(sk);
        sctp_transport_put(transport);
 }
 
@@ -285,11 +286,12 @@ out_unlock:
 static void sctp_generate_timeout_event(struct sctp_association *asoc,
                                        sctp_event_timeout_t timeout_type)
 {
-       struct net *net = sock_net(asoc->base.sk);
+       struct sock *sk = asoc->base.sk;
+       struct net *net = sock_net(sk);
        int error = 0;
 
-       bh_lock_sock(asoc->base.sk);
-       if (sock_owned_by_user(asoc->base.sk)) {
+       bh_lock_sock(sk);
+       if (sock_owned_by_user(sk)) {
                pr_debug("%s: sock is busy: timer %d\n", __func__,
                         timeout_type);
 
@@ -312,10 +314,10 @@ static void sctp_generate_timeout_event(struct sctp_association *asoc,
                           (void *)timeout_type, GFP_ATOMIC);
 
        if (error)
-               asoc->base.sk->sk_err = -error;
+               sk->sk_err = -error;
 
 out_unlock:
-       bh_unlock_sock(asoc->base.sk);
+       bh_unlock_sock(sk);
        sctp_association_put(asoc);
 }
 
@@ -365,10 +367,11 @@ void sctp_generate_heartbeat_event(unsigned long data)
        int error = 0;
        struct sctp_transport *transport = (struct sctp_transport *) data;
        struct sctp_association *asoc = transport->asoc;
-       struct net *net = sock_net(asoc->base.sk);
+       struct sock *sk = asoc->base.sk;
+       struct net *net = sock_net(sk);
 
-       bh_lock_sock(asoc->base.sk);
-       if (sock_owned_by_user(asoc->base.sk)) {
+       bh_lock_sock(sk);
+       if (sock_owned_by_user(sk)) {
                pr_debug("%s: sock is busy\n", __func__);
 
                /* Try again later.  */
@@ -388,11 +391,11 @@ void sctp_generate_heartbeat_event(unsigned long data)
                           asoc->state, asoc->ep, asoc,
                           transport, GFP_ATOMIC);
 
-        if (error)
-                asoc->base.sk->sk_err = -error;
+       if (error)
+               sk->sk_err = -error;
 
 out_unlock:
-       bh_unlock_sock(asoc->base.sk);
+       bh_unlock_sock(sk);
        sctp_transport_put(transport);
 }
 
@@ -403,10 +406,11 @@ void sctp_generate_proto_unreach_event(unsigned long data)
 {
        struct sctp_transport *transport = (struct sctp_transport *) data;
        struct sctp_association *asoc = transport->asoc;
-       struct net *net = sock_net(asoc->base.sk);
+       struct sock *sk = asoc->base.sk;
+       struct net *net = sock_net(sk);
 
-       bh_lock_sock(asoc->base.sk);
-       if (sock_owned_by_user(asoc->base.sk)) {
+       bh_lock_sock(sk);
+       if (sock_owned_by_user(sk)) {
                pr_debug("%s: sock is busy\n", __func__);
 
                /* Try again later.  */
@@ -427,7 +431,7 @@ void sctp_generate_proto_unreach_event(unsigned long data)
                   asoc->state, asoc->ep, asoc, transport, GFP_ATOMIC);
 
 out_unlock:
-       bh_unlock_sock(asoc->base.sk);
+       bh_unlock_sock(sk);
        sctp_association_put(asoc);
 }
 
index b140c092d226edd7d207f077e511d828cc08a615..f14f24ee998344f5c356ef49e3b3fc52d581a39c 100644 (file)
@@ -297,7 +297,7 @@ static int rpc_complete_task(struct rpc_task *task)
        clear_bit(RPC_TASK_ACTIVE, &task->tk_runstate);
        ret = atomic_dec_and_test(&task->tk_count);
        if (waitqueue_active(wq))
-               __wake_up_locked_key(wq, TASK_NORMAL, 1, &k);
+               __wake_up_locked_key(wq, TASK_NORMAL, &k);
        spin_unlock_irqrestore(&wq->lock, flags);
        return ret;
 }
@@ -1092,14 +1092,10 @@ void
 rpc_destroy_mempool(void)
 {
        rpciod_stop();
-       if (rpc_buffer_mempool)
-               mempool_destroy(rpc_buffer_mempool);
-       if (rpc_task_mempool)
-               mempool_destroy(rpc_task_mempool);
-       if (rpc_task_slabp)
-               kmem_cache_destroy(rpc_task_slabp);
-       if (rpc_buffer_slabp)
-               kmem_cache_destroy(rpc_buffer_slabp);
+       mempool_destroy(rpc_buffer_mempool);
+       mempool_destroy(rpc_task_mempool);
+       kmem_cache_destroy(rpc_task_slabp);
+       kmem_cache_destroy(rpc_buffer_slabp);
        rpc_destroy_wait_queue(&delay_queue);
 }
 
index ab5dd621ae0c0795a0d86e1a9fb83c5cc2812486..2e98f4a243e57d4539b3f4048d54c4b53f3c12d5 100644 (file)
@@ -614,6 +614,7 @@ static void xprt_autoclose(struct work_struct *work)
        clear_bit(XPRT_CLOSE_WAIT, &xprt->state);
        xprt->ops->close(xprt);
        xprt_release_write(xprt, NULL);
+       wake_up_bit(&xprt->state, XPRT_LOCKED);
 }
 
 /**
@@ -723,6 +724,7 @@ void xprt_unlock_connect(struct rpc_xprt *xprt, void *cookie)
        xprt->ops->release_xprt(xprt, NULL);
 out:
        spin_unlock_bh(&xprt->transport_lock);
+       wake_up_bit(&xprt->state, XPRT_LOCKED);
 }
 
 /**
@@ -1394,6 +1396,10 @@ out:
 static void xprt_destroy(struct rpc_xprt *xprt)
 {
        dprintk("RPC:       destroying transport %p\n", xprt);
+
+       /* Exclude transport connect/disconnect handlers */
+       wait_on_bit_lock(&xprt->state, XPRT_LOCKED, TASK_UNINTERRUPTIBLE);
+
        del_timer_sync(&xprt->timer);
 
        rpc_xprt_debugfs_unregister(xprt);
index cb25c89da6239154475d6c31736e328d13f19134..f1e8dafbd5079b3406a769ba4854ecba229edca6 100644 (file)
@@ -39,25 +39,6 @@ static int
 fmr_op_open(struct rpcrdma_ia *ia, struct rpcrdma_ep *ep,
            struct rpcrdma_create_data_internal *cdata)
 {
-       struct ib_device_attr *devattr = &ia->ri_devattr;
-       struct ib_mr *mr;
-
-       /* Obtain an lkey to use for the regbufs, which are
-        * protected from remote access.
-        */
-       if (devattr->device_cap_flags & IB_DEVICE_LOCAL_DMA_LKEY) {
-               ia->ri_dma_lkey = ia->ri_device->local_dma_lkey;
-       } else {
-               mr = ib_get_dma_mr(ia->ri_pd, IB_ACCESS_LOCAL_WRITE);
-               if (IS_ERR(mr)) {
-                       pr_err("%s: ib_get_dma_mr for failed with %lX\n",
-                              __func__, PTR_ERR(mr));
-                       return -ENOMEM;
-               }
-               ia->ri_dma_lkey = ia->ri_dma_mr->lkey;
-               ia->ri_dma_mr = mr;
-       }
-
        return 0;
 }
 
index d6653f5d0830378cd08531afb61c0b766ae8b6b9..5318951b3b531ca322f1a0c3639a9079d3599555 100644 (file)
@@ -189,11 +189,6 @@ frwr_op_open(struct rpcrdma_ia *ia, struct rpcrdma_ep *ep,
        struct ib_device_attr *devattr = &ia->ri_devattr;
        int depth, delta;
 
-       /* Obtain an lkey to use for the regbufs, which are
-        * protected from remote access.
-        */
-       ia->ri_dma_lkey = ia->ri_device->local_dma_lkey;
-
        ia->ri_max_frmr_depth =
                        min_t(unsigned int, RPCRDMA_MAX_DATA_SEGS,
                              devattr->max_fast_reg_page_list_len);
index 72cf8b15bbb4e331d49f937c58abd85f7dd70862..617b76f22154c41b41cdccd329cbbe9f00a3fabe 100644 (file)
@@ -23,7 +23,6 @@ static int
 physical_op_open(struct rpcrdma_ia *ia, struct rpcrdma_ep *ep,
                 struct rpcrdma_create_data_internal *cdata)
 {
-       struct ib_device_attr *devattr = &ia->ri_devattr;
        struct ib_mr *mr;
 
        /* Obtain an rkey to use for RPC data payloads.
@@ -37,15 +36,8 @@ physical_op_open(struct rpcrdma_ia *ia, struct rpcrdma_ep *ep,
                       __func__, PTR_ERR(mr));
                return -ENOMEM;
        }
-       ia->ri_dma_mr = mr;
-
-       /* Obtain an lkey to use for regbufs.
-        */
-       if (devattr->device_cap_flags & IB_DEVICE_LOCAL_DMA_LKEY)
-               ia->ri_dma_lkey = ia->ri_device->local_dma_lkey;
-       else
-               ia->ri_dma_lkey = ia->ri_dma_mr->lkey;
 
+       ia->ri_dma_mr = mr;
        return 0;
 }
 
index cb51742840740f790d24797e585e7fb520646a09..f0c3ff67ca987427136baebf67034ad3bf58a27f 100644 (file)
@@ -136,7 +136,8 @@ int rdma_read_chunk_lcl(struct svcxprt_rdma *xprt,
        ctxt->direction = DMA_FROM_DEVICE;
        ctxt->read_hdr = head;
        pages_needed = min_t(int, pages_needed, xprt->sc_max_sge_rd);
-       read = min_t(int, pages_needed << PAGE_SHIFT, rs_length);
+       read = min_t(int, (pages_needed << PAGE_SHIFT) - *page_offset,
+                    rs_length);
 
        for (pno = 0; pno < pages_needed; pno++) {
                int len = min_t(int, rs_length, PAGE_SIZE - pg_off);
@@ -235,7 +236,8 @@ int rdma_read_chunk_frmr(struct svcxprt_rdma *xprt,
        ctxt->direction = DMA_FROM_DEVICE;
        ctxt->frmr = frmr;
        pages_needed = min_t(int, pages_needed, xprt->sc_frmr_pg_list_len);
-       read = min_t(int, pages_needed << PAGE_SHIFT, rs_length);
+       read = min_t(int, (pages_needed << PAGE_SHIFT) - *page_offset,
+                    rs_length);
 
        frmr->kva = page_address(rqstp->rq_arg.pages[pg_no]);
        frmr->direction = DMA_FROM_DEVICE;
@@ -531,7 +533,7 @@ static int rdma_read_complete(struct svc_rqst *rqstp,
        rqstp->rq_arg.page_base = head->arg.page_base;
 
        /* rq_respages starts after the last arg page */
-       rqstp->rq_respages = &rqstp->rq_arg.pages[page_no];
+       rqstp->rq_respages = &rqstp->rq_pages[page_no];
        rqstp->rq_next_page = rqstp->rq_respages + 1;
 
        /* Rebuild rq_arg head and tail. */
index 64443eb754ad0fe7fd0b16633c3aa10cebdc3e26..41e452bc580c0fea0f39fe71924b72dcdff6782f 100644 (file)
@@ -270,8 +270,8 @@ xprt_rdma_destroy(struct rpc_xprt *xprt)
 
        xprt_clear_connected(xprt);
 
-       rpcrdma_buffer_destroy(&r_xprt->rx_buf);
        rpcrdma_ep_destroy(&r_xprt->rx_ep, &r_xprt->rx_ia);
+       rpcrdma_buffer_destroy(&r_xprt->rx_buf);
        rpcrdma_ia_close(&r_xprt->rx_ia);
 
        xprt_rdma_free_addresses(xprt);
index 682996779970c6ccae749c9de566f06a9b205c80..5502d4dade74aa8646f89305b011d215294352e0 100644 (file)
@@ -543,11 +543,8 @@ rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg)
        }
 
        if (memreg == RPCRDMA_FRMR) {
-               /* Requires both frmr reg and local dma lkey */
-               if (((devattr->device_cap_flags &
-                    (IB_DEVICE_MEM_MGT_EXTENSIONS|IB_DEVICE_LOCAL_DMA_LKEY)) !=
-                   (IB_DEVICE_MEM_MGT_EXTENSIONS|IB_DEVICE_LOCAL_DMA_LKEY)) ||
-                     (devattr->max_fast_reg_page_list_len == 0)) {
+               if (!(devattr->device_cap_flags & IB_DEVICE_MEM_MGT_EXTENSIONS) ||
+                   (devattr->max_fast_reg_page_list_len == 0)) {
                        dprintk("RPC:       %s: FRMR registration "
                                "not supported by HCA\n", __func__);
                        memreg = RPCRDMA_MTHCAFMR;
@@ -557,6 +554,7 @@ rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg)
                if (!ia->ri_device->alloc_fmr) {
                        dprintk("RPC:       %s: MTHCAFMR registration "
                                "not supported by HCA\n", __func__);
+                       rc = -EINVAL;
                        goto out3;
                }
        }
@@ -755,19 +753,22 @@ rpcrdma_ep_destroy(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia)
 
        cancel_delayed_work_sync(&ep->rep_connect_worker);
 
-       if (ia->ri_id->qp) {
+       if (ia->ri_id->qp)
                rpcrdma_ep_disconnect(ep, ia);
+
+       rpcrdma_clean_cq(ep->rep_attr.recv_cq);
+       rpcrdma_clean_cq(ep->rep_attr.send_cq);
+
+       if (ia->ri_id->qp) {
                rdma_destroy_qp(ia->ri_id);
                ia->ri_id->qp = NULL;
        }
 
-       rpcrdma_clean_cq(ep->rep_attr.recv_cq);
        rc = ib_destroy_cq(ep->rep_attr.recv_cq);
        if (rc)
                dprintk("RPC:       %s: ib_destroy_cq returned %i\n",
                        __func__, rc);
 
-       rpcrdma_clean_cq(ep->rep_attr.send_cq);
        rc = ib_destroy_cq(ep->rep_attr.send_cq);
        if (rc)
                dprintk("RPC:       %s: ib_destroy_cq returned %i\n",
@@ -1252,7 +1253,7 @@ rpcrdma_alloc_regbuf(struct rpcrdma_ia *ia, size_t size, gfp_t flags)
                goto out_free;
 
        iov->length = size;
-       iov->lkey = ia->ri_dma_lkey;
+       iov->lkey = ia->ri_pd->local_dma_lkey;
        rb->rg_size = size;
        rb->rg_owner = NULL;
        return rb;
index 02512221b8bc885dde93b987c561b344f6e96722..c09414e6f91b0428bd7cc5fd6f2b1c67f8830b23 100644 (file)
@@ -65,7 +65,6 @@ struct rpcrdma_ia {
        struct rdma_cm_id       *ri_id;
        struct ib_pd            *ri_pd;
        struct ib_mr            *ri_dma_mr;
-       u32                     ri_dma_lkey;
        struct completion       ri_done;
        int                     ri_async_rc;
        unsigned int            ri_max_frmr_depth;
index 7be90bc1a7c26c2c4b998e4b21ca319df19f9638..1a85e0ed0b4841792cd5b6a7d86864cbc2d334a3 100644 (file)
@@ -777,7 +777,6 @@ static void xs_sock_mark_closed(struct rpc_xprt *xprt)
        xs_sock_reset_connection_flags(xprt);
        /* Mark transport as closed and wake up all pending tasks */
        xprt_disconnect_done(xprt);
-       xprt_force_disconnect(xprt);
 }
 
 /**
@@ -881,8 +880,11 @@ static void xs_xprt_free(struct rpc_xprt *xprt)
  */
 static void xs_destroy(struct rpc_xprt *xprt)
 {
+       struct sock_xprt *transport = container_of(xprt,
+                       struct sock_xprt, xprt);
        dprintk("RPC:       xs_destroy xprt %p\n", xprt);
 
+       cancel_delayed_work_sync(&transport->connect_worker);
        xs_close(xprt);
        xs_xprt_free(xprt);
        module_put(THIS_MODULE);
@@ -1435,6 +1437,7 @@ out:
 static void xs_tcp_state_change(struct sock *sk)
 {
        struct rpc_xprt *xprt;
+       struct sock_xprt *transport;
 
        read_lock_bh(&sk->sk_callback_lock);
        if (!(xprt = xprt_from_sock(sk)))
@@ -1446,13 +1449,12 @@ static void xs_tcp_state_change(struct sock *sk)
                        sock_flag(sk, SOCK_ZAPPED),
                        sk->sk_shutdown);
 
+       transport = container_of(xprt, struct sock_xprt, xprt);
        trace_rpc_socket_state_change(xprt, sk->sk_socket);
        switch (sk->sk_state) {
        case TCP_ESTABLISHED:
                spin_lock(&xprt->transport_lock);
                if (!xprt_test_and_set_connected(xprt)) {
-                       struct sock_xprt *transport = container_of(xprt,
-                                       struct sock_xprt, xprt);
 
                        /* Reset TCP record info */
                        transport->tcp_offset = 0;
@@ -1461,6 +1463,8 @@ static void xs_tcp_state_change(struct sock *sk)
                        transport->tcp_flags =
                                TCP_RCV_COPY_FRAGHDR | TCP_RCV_COPY_XID;
                        xprt->connect_cookie++;
+                       clear_bit(XPRT_SOCK_CONNECTING, &transport->sock_state);
+                       xprt_clear_connecting(xprt);
 
                        xprt_wake_pending_tasks(xprt, -EAGAIN);
                }
@@ -1496,6 +1500,9 @@ static void xs_tcp_state_change(struct sock *sk)
                smp_mb__after_atomic();
                break;
        case TCP_CLOSE:
+               if (test_and_clear_bit(XPRT_SOCK_CONNECTING,
+                                       &transport->sock_state))
+                       xprt_clear_connecting(xprt);
                xs_sock_mark_closed(xprt);
        }
  out:
@@ -2179,6 +2186,7 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
        /* Tell the socket layer to start connecting... */
        xprt->stat.connect_count++;
        xprt->stat.connect_start = jiffies;
+       set_bit(XPRT_SOCK_CONNECTING, &transport->sock_state);
        ret = kernel_connect(sock, xs_addr(xprt), xprt->addrlen, O_NONBLOCK);
        switch (ret) {
        case 0:
@@ -2240,7 +2248,6 @@ static void xs_tcp_setup_socket(struct work_struct *work)
        case -EINPROGRESS:
        case -EALREADY:
                xprt_unlock_connect(xprt, transport);
-               xprt_clear_connecting(xprt);
                return;
        case -EINVAL:
                /* Happens, for instance, if the user specified a link
index fda38f830a10869713177220f8d2066c6076da0c..77f5d17e261230a6db4f261445311eafb37c7b06 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/notifier.h>
 #include <linux/netdevice.h>
 #include <linux/if_bridge.h>
+#include <linux/if_vlan.h>
 #include <net/ip_fib.h>
 #include <net/switchdev.h>
 
@@ -634,6 +635,8 @@ static int switchdev_port_br_afspec(struct net_device *dev,
                if (nla_len(attr) != sizeof(struct bridge_vlan_info))
                        return -EINVAL;
                vinfo = nla_data(attr);
+               if (!vinfo->vid || vinfo->vid >= VLAN_VID_MASK)
+                       return -EINVAL;
                vlan->flags = vinfo->flags;
                if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) {
                        if (vlan->vid_begin)
index e7000be321b0148469264524ed6fce75c3952955..ed98c1fc3de1428560ea370413084102af9dff7f 100644 (file)
@@ -94,10 +94,14 @@ __init int net_sysctl_init(void)
                goto out;
        ret = register_pernet_subsys(&sysctl_pernet_ops);
        if (ret)
-               goto out;
+               goto out1;
        register_sysctl_root(&net_sysctl_root);
 out:
        return ret;
+out1:
+       unregister_sysctl_table(net_header);
+       net_header = NULL;
+       goto out;
 }
 
 struct ctl_table_header *register_net_sysctl(struct net *net,
index 41042de3ae9bcfad4504e0bcbb29d3bea4512bb5..eadba62afa85dcd9463f5eddd08704539fa63488 100644 (file)
@@ -42,7 +42,8 @@
 #include "core.h"
 
 #define        MAX_PKT_DEFAULT_MCAST   1500    /* bcast link max packet size (fixed) */
-#define        BCLINK_WIN_DEFAULT      20      /* bcast link window size (default) */
+#define        BCLINK_WIN_DEFAULT      50      /* bcast link window size (default) */
+#define        BCLINK_WIN_MIN          32      /* bcast minimum link window size */
 
 const char tipc_bclink_name[] = "broadcast-link";
 
@@ -908,9 +909,10 @@ int tipc_bclink_set_queue_limits(struct net *net, u32 limit)
 
        if (!bcl)
                return -ENOPROTOOPT;
-       if ((limit < TIPC_MIN_LINK_WIN) || (limit > TIPC_MAX_LINK_WIN))
+       if (limit < BCLINK_WIN_MIN)
+               limit = BCLINK_WIN_MIN;
+       if (limit > TIPC_MAX_LINK_WIN)
                return -EINVAL;
-
        tipc_bclink_lock(net);
        tipc_link_set_queue_limits(bcl, limit);
        tipc_bclink_unlock(net);
index 562c926a51cc7baa859115b6a0d444f73febf357..5f73450159df3b7d99349e2b49610b7d9a1d6c47 100644 (file)
@@ -121,7 +121,7 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf)
 {
        struct sk_buff *head = *headbuf;
        struct sk_buff *frag = *buf;
-       struct sk_buff *tail;
+       struct sk_buff *tail = NULL;
        struct tipc_msg *msg;
        u32 fragid;
        int delta;
@@ -141,9 +141,15 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf)
                if (unlikely(skb_unclone(frag, GFP_ATOMIC)))
                        goto err;
                head = *headbuf = frag;
-               skb_frag_list_init(head);
-               TIPC_SKB_CB(head)->tail = NULL;
                *buf = NULL;
+               TIPC_SKB_CB(head)->tail = NULL;
+               if (skb_is_nonlinear(head)) {
+                       skb_walk_frags(head, tail) {
+                               TIPC_SKB_CB(head)->tail = tail;
+                       }
+               } else {
+                       skb_frag_list_init(head);
+               }
                return 0;
        }
 
@@ -539,6 +545,7 @@ bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb, int *err)
        *err = -TIPC_ERR_NO_NAME;
        if (skb_linearize(skb))
                return false;
+       msg = buf_msg(skb);
        if (msg_reroute_cnt(msg))
                return false;
        dnode = addr_domain(net, msg_lookup_scope(msg));
index a82c5848d4bc22129bd1e6ba7f677795febdc9e9..5351a3f97e8ecf17e545459344a8b315f522045a 100644 (file)
@@ -357,7 +357,7 @@ static inline u32 msg_importance(struct tipc_msg *m)
        if (likely((usr <= TIPC_CRITICAL_IMPORTANCE) && !msg_errcode(m)))
                return usr;
        if ((usr == MSG_FRAGMENTER) || (usr == MSG_BUNDLER))
-               return msg_bits(m, 5, 13, 0x7);
+               return msg_bits(m, 9, 0, 0x7);
        return TIPC_SYSTEM_IMPORTANCE;
 }
 
@@ -366,7 +366,7 @@ static inline void msg_set_importance(struct tipc_msg *m, u32 i)
        int usr = msg_user(m);
 
        if (likely((usr == MSG_FRAGMENTER) || (usr == MSG_BUNDLER)))
-               msg_set_bits(m, 5, 13, 0x7, i);
+               msg_set_bits(m, 9, 0, 0x7, i);
        else if (i < TIPC_SYSTEM_IMPORTANCE)
                msg_set_user(m, i);
        else
index 703875fd6cde204ddeaf630b9a6bd11daec6dbfa..2c32a83037a3614ef09fb4b29c8f3337dcdf0f45 100644 (file)
@@ -1116,7 +1116,7 @@ static bool tipc_node_check_state(struct tipc_node *n, struct sk_buff *skb,
        }
 
        /* Ignore duplicate packets */
-       if (less(oseqno, rcv_nxt))
+       if ((usr != LINK_PROTOCOL) && less(oseqno, rcv_nxt))
                return true;
 
        /* Initiate or update failover mode if applicable */
@@ -1146,8 +1146,8 @@ static bool tipc_node_check_state(struct tipc_node *n, struct sk_buff *skb,
        if (!pl || !tipc_link_is_up(pl))
                return true;
 
-       /* Initiate or update synch mode if applicable */
-       if ((usr == TUNNEL_PROTOCOL) && (mtyp == SYNCH_MSG)) {
+       /* Initiate synch mode if applicable */
+       if ((usr == TUNNEL_PROTOCOL) && (mtyp == SYNCH_MSG) && (oseqno == 1)) {
                syncpt = iseqno + exp_pkts - 1;
                if (!tipc_link_is_up(l)) {
                        tipc_link_fsm_evt(l, LINK_ESTABLISH_EVT);
index c170d3138953a2361df5439aeffadd29afa52ad9..6e648d90297a9ecc69a23a68183fde658eed63cd 100644 (file)
@@ -52,6 +52,8 @@
 /* IANA assigned UDP port */
 #define UDP_PORT_DEFAULT       6118
 
+#define UDP_MIN_HEADROOM        28
+
 static const struct nla_policy tipc_nl_udp_policy[TIPC_NLA_UDP_MAX + 1] = {
        [TIPC_NLA_UDP_UNSPEC]   = {.type = NLA_UNSPEC},
        [TIPC_NLA_UDP_LOCAL]    = {.type = NLA_BINARY,
@@ -156,6 +158,9 @@ static int tipc_udp_send_msg(struct net *net, struct sk_buff *skb,
        struct sk_buff *clone;
        struct rtable *rt;
 
+       if (skb_headroom(skb) < UDP_MIN_HEADROOM)
+               pskb_expand_head(skb, UDP_MIN_HEADROOM, 0, GFP_ATOMIC);
+
        clone = skb_clone(skb, GFP_ATOMIC);
        skb_set_inner_protocol(clone, htons(ETH_P_TIPC));
        ub = rcu_dereference_rtnl(b->media_ptr);
index 03ee4d359f6a4922397a1a8a36c015a06aae1cac..94f658235fb49a0c644a84867302cc00a75243d5 100644 (file)
@@ -2064,6 +2064,11 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state)
                goto out;
        }
 
+       if (flags & MSG_PEEK)
+               skip = sk_peek_offset(sk, flags);
+       else
+               skip = 0;
+
        do {
                int chunk;
                struct sk_buff *skb, *last;
@@ -2112,7 +2117,6 @@ unlock:
                        break;
                }
 
-               skip = sk_peek_offset(sk, flags);
                while (skip >= unix_skb_len(skb)) {
                        skip -= unix_skb_len(skb);
                        last = skb;
@@ -2181,6 +2185,17 @@ unlock:
 
                        sk_peek_offset_fwd(sk, chunk);
 
+                       if (UNIXCB(skb).fp)
+                               break;
+
+                       skip = 0;
+                       last = skb;
+                       last_len = skb->len;
+                       unix_state_lock(sk);
+                       skb = skb_peek_next(skb, &sk->sk_receive_queue);
+                       if (skb)
+                               goto again;
+                       unix_state_unlock(sk);
                        break;
                }
        } while (size);
index df5fc6b340f1bbde621fbe84fa44e0af6e2e00af..00e8a349aabccc61cec1f9ebb889bc7dd9d3b5e1 100644 (file)
@@ -1948,13 +1948,13 @@ int __vsock_core_init(const struct vsock_transport *t, struct module *owner)
        err = misc_register(&vsock_device);
        if (err) {
                pr_err("Failed to register misc device\n");
-               return -ENOENT;
+               goto err_reset_transport;
        }
 
        err = proto_register(&vsock_proto, 1);  /* we want our slab */
        if (err) {
                pr_err("Cannot register vsock protocol\n");
-               goto err_misc_deregister;
+               goto err_deregister_misc;
        }
 
        err = sock_register(&vsock_family_ops);
@@ -1969,8 +1969,9 @@ int __vsock_core_init(const struct vsock_transport *t, struct module *owner)
 
 err_unregister_proto:
        proto_unregister(&vsock_proto);
-err_misc_deregister:
+err_deregister_misc:
        misc_deregister(&vsock_device);
+err_reset_transport:
        transport = NULL;
 err_busy:
        mutex_unlock(&vsock_register_mutex);
index 1f63daff39659e08561862cfd71220ffc6949291..7555cad83a752a930a54e4a8ca609846386e0ec1 100644 (file)
 
 static int vmci_transport_recv_dgram_cb(void *data, struct vmci_datagram *dg);
 static int vmci_transport_recv_stream_cb(void *data, struct vmci_datagram *dg);
-static void vmci_transport_peer_attach_cb(u32 sub_id,
-                                         const struct vmci_event_data *ed,
-                                         void *client_data);
 static void vmci_transport_peer_detach_cb(u32 sub_id,
                                          const struct vmci_event_data *ed,
                                          void *client_data);
 static void vmci_transport_recv_pkt_work(struct work_struct *work);
+static void vmci_transport_cleanup(struct work_struct *work);
 static int vmci_transport_recv_listen(struct sock *sk,
                                      struct vmci_transport_packet *pkt);
 static int vmci_transport_recv_connecting_server(
@@ -75,6 +73,10 @@ struct vmci_transport_recv_pkt_info {
        struct vmci_transport_packet pkt;
 };
 
+static LIST_HEAD(vmci_transport_cleanup_list);
+static DEFINE_SPINLOCK(vmci_transport_cleanup_lock);
+static DECLARE_WORK(vmci_transport_cleanup_work, vmci_transport_cleanup);
+
 static struct vmci_handle vmci_transport_stream_handle = { VMCI_INVALID_ID,
                                                           VMCI_INVALID_ID };
 static u32 vmci_transport_qp_resumed_sub_id = VMCI_INVALID_ID;
@@ -791,44 +793,6 @@ out:
        return err;
 }
 
-static void vmci_transport_peer_attach_cb(u32 sub_id,
-                                         const struct vmci_event_data *e_data,
-                                         void *client_data)
-{
-       struct sock *sk = client_data;
-       const struct vmci_event_payload_qp *e_payload;
-       struct vsock_sock *vsk;
-
-       e_payload = vmci_event_data_const_payload(e_data);
-
-       vsk = vsock_sk(sk);
-
-       /* We don't ask for delayed CBs when we subscribe to this event (we
-        * pass 0 as flags to vmci_event_subscribe()).  VMCI makes no
-        * guarantees in that case about what context we might be running in,
-        * so it could be BH or process, blockable or non-blockable.  So we
-        * need to account for all possible contexts here.
-        */
-       local_bh_disable();
-       bh_lock_sock(sk);
-
-       /* XXX This is lame, we should provide a way to lookup sockets by
-        * qp_handle.
-        */
-       if (vmci_handle_is_equal(vmci_trans(vsk)->qp_handle,
-                                e_payload->handle)) {
-               /* XXX This doesn't do anything, but in the future we may want
-                * to set a flag here to verify the attach really did occur and
-                * we weren't just sent a datagram claiming it was.
-                */
-               goto out;
-       }
-
-out:
-       bh_unlock_sock(sk);
-       local_bh_enable();
-}
-
 static void vmci_transport_handle_detach(struct sock *sk)
 {
        struct vsock_sock *vsk;
@@ -871,28 +835,38 @@ static void vmci_transport_peer_detach_cb(u32 sub_id,
                                          const struct vmci_event_data *e_data,
                                          void *client_data)
 {
-       struct sock *sk = client_data;
+       struct vmci_transport *trans = client_data;
        const struct vmci_event_payload_qp *e_payload;
-       struct vsock_sock *vsk;
 
        e_payload = vmci_event_data_const_payload(e_data);
-       vsk = vsock_sk(sk);
-       if (vmci_handle_is_invalid(e_payload->handle))
-               return;
-
-       /* Same rules for locking as for peer_attach_cb(). */
-       local_bh_disable();
-       bh_lock_sock(sk);
 
        /* XXX This is lame, we should provide a way to lookup sockets by
         * qp_handle.
         */
-       if (vmci_handle_is_equal(vmci_trans(vsk)->qp_handle,
-                                e_payload->handle))
-               vmci_transport_handle_detach(sk);
+       if (vmci_handle_is_invalid(e_payload->handle) ||
+           vmci_handle_is_equal(trans->qp_handle, e_payload->handle))
+               return;
 
-       bh_unlock_sock(sk);
-       local_bh_enable();
+       /* We don't ask for delayed CBs when we subscribe to this event (we
+        * pass 0 as flags to vmci_event_subscribe()).  VMCI makes no
+        * guarantees in that case about what context we might be running in,
+        * so it could be BH or process, blockable or non-blockable.  So we
+        * need to account for all possible contexts here.
+        */
+       spin_lock_bh(&trans->lock);
+       if (!trans->sk)
+               goto out;
+
+       /* Apart from here, trans->lock is only grabbed as part of sk destruct,
+        * where trans->sk isn't locked.
+        */
+       bh_lock_sock(trans->sk);
+
+       vmci_transport_handle_detach(trans->sk);
+
+       bh_unlock_sock(trans->sk);
+ out:
+       spin_unlock_bh(&trans->lock);
 }
 
 static void vmci_transport_qp_resumed_cb(u32 sub_id,
@@ -1181,7 +1155,7 @@ vmci_transport_recv_connecting_server(struct sock *listener,
         */
        err = vmci_event_subscribe(VMCI_EVENT_QP_PEER_DETACH,
                                   vmci_transport_peer_detach_cb,
-                                  pending, &detach_sub_id);
+                                  vmci_trans(vpending), &detach_sub_id);
        if (err < VMCI_SUCCESS) {
                vmci_transport_send_reset(pending, pkt);
                err = vmci_transport_error_to_vsock_error(err);
@@ -1321,7 +1295,6 @@ vmci_transport_recv_connecting_client(struct sock *sk,
                    || vmci_trans(vsk)->qpair
                    || vmci_trans(vsk)->produce_size != 0
                    || vmci_trans(vsk)->consume_size != 0
-                   || vmci_trans(vsk)->attach_sub_id != VMCI_INVALID_ID
                    || vmci_trans(vsk)->detach_sub_id != VMCI_INVALID_ID) {
                        skerr = EPROTO;
                        err = -EINVAL;
@@ -1389,7 +1362,6 @@ static int vmci_transport_recv_connecting_client_negotiate(
        struct vsock_sock *vsk;
        struct vmci_handle handle;
        struct vmci_qp *qpair;
-       u32 attach_sub_id;
        u32 detach_sub_id;
        bool is_local;
        u32 flags;
@@ -1399,7 +1371,6 @@ static int vmci_transport_recv_connecting_client_negotiate(
 
        vsk = vsock_sk(sk);
        handle = VMCI_INVALID_HANDLE;
-       attach_sub_id = VMCI_INVALID_ID;
        detach_sub_id = VMCI_INVALID_ID;
 
        /* If we have gotten here then we should be past the point where old
@@ -1444,23 +1415,15 @@ static int vmci_transport_recv_connecting_client_negotiate(
                goto destroy;
        }
 
-       /* Subscribe to attach and detach events first.
+       /* Subscribe to detach events first.
         *
         * XXX We attach once for each queue pair created for now so it is easy
         * to find the socket (it's provided), but later we should only
         * subscribe once and add a way to lookup sockets by queue pair handle.
         */
-       err = vmci_event_subscribe(VMCI_EVENT_QP_PEER_ATTACH,
-                                  vmci_transport_peer_attach_cb,
-                                  sk, &attach_sub_id);
-       if (err < VMCI_SUCCESS) {
-               err = vmci_transport_error_to_vsock_error(err);
-               goto destroy;
-       }
-
        err = vmci_event_subscribe(VMCI_EVENT_QP_PEER_DETACH,
                                   vmci_transport_peer_detach_cb,
-                                  sk, &detach_sub_id);
+                                  vmci_trans(vsk), &detach_sub_id);
        if (err < VMCI_SUCCESS) {
                err = vmci_transport_error_to_vsock_error(err);
                goto destroy;
@@ -1496,7 +1459,6 @@ static int vmci_transport_recv_connecting_client_negotiate(
        vmci_trans(vsk)->produce_size = vmci_trans(vsk)->consume_size =
                pkt->u.size;
 
-       vmci_trans(vsk)->attach_sub_id = attach_sub_id;
        vmci_trans(vsk)->detach_sub_id = detach_sub_id;
 
        vmci_trans(vsk)->notify_ops->process_negotiate(sk);
@@ -1504,9 +1466,6 @@ static int vmci_transport_recv_connecting_client_negotiate(
        return 0;
 
 destroy:
-       if (attach_sub_id != VMCI_INVALID_ID)
-               vmci_event_unsubscribe(attach_sub_id);
-
        if (detach_sub_id != VMCI_INVALID_ID)
                vmci_event_unsubscribe(detach_sub_id);
 
@@ -1607,9 +1566,11 @@ static int vmci_transport_socket_init(struct vsock_sock *vsk,
        vmci_trans(vsk)->qp_handle = VMCI_INVALID_HANDLE;
        vmci_trans(vsk)->qpair = NULL;
        vmci_trans(vsk)->produce_size = vmci_trans(vsk)->consume_size = 0;
-       vmci_trans(vsk)->attach_sub_id = vmci_trans(vsk)->detach_sub_id =
-               VMCI_INVALID_ID;
+       vmci_trans(vsk)->detach_sub_id = VMCI_INVALID_ID;
        vmci_trans(vsk)->notify_ops = NULL;
+       INIT_LIST_HEAD(&vmci_trans(vsk)->elem);
+       vmci_trans(vsk)->sk = &vsk->sk;
+       spin_lock_init(&vmci_trans(vsk)->lock);
        if (psk) {
                vmci_trans(vsk)->queue_pair_size =
                        vmci_trans(psk)->queue_pair_size;
@@ -1629,29 +1590,57 @@ static int vmci_transport_socket_init(struct vsock_sock *vsk,
        return 0;
 }
 
-static void vmci_transport_destruct(struct vsock_sock *vsk)
+static void vmci_transport_free_resources(struct list_head *transport_list)
 {
-       if (vmci_trans(vsk)->attach_sub_id != VMCI_INVALID_ID) {
-               vmci_event_unsubscribe(vmci_trans(vsk)->attach_sub_id);
-               vmci_trans(vsk)->attach_sub_id = VMCI_INVALID_ID;
-       }
+       while (!list_empty(transport_list)) {
+               struct vmci_transport *transport =
+                   list_first_entry(transport_list, struct vmci_transport,
+                                    elem);
+               list_del(&transport->elem);
 
-       if (vmci_trans(vsk)->detach_sub_id != VMCI_INVALID_ID) {
-               vmci_event_unsubscribe(vmci_trans(vsk)->detach_sub_id);
-               vmci_trans(vsk)->detach_sub_id = VMCI_INVALID_ID;
-       }
+               if (transport->detach_sub_id != VMCI_INVALID_ID) {
+                       vmci_event_unsubscribe(transport->detach_sub_id);
+                       transport->detach_sub_id = VMCI_INVALID_ID;
+               }
 
-       if (!vmci_handle_is_invalid(vmci_trans(vsk)->qp_handle)) {
-               vmci_qpair_detach(&vmci_trans(vsk)->qpair);
-               vmci_trans(vsk)->qp_handle = VMCI_INVALID_HANDLE;
-               vmci_trans(vsk)->produce_size = 0;
-               vmci_trans(vsk)->consume_size = 0;
+               if (!vmci_handle_is_invalid(transport->qp_handle)) {
+                       vmci_qpair_detach(&transport->qpair);
+                       transport->qp_handle = VMCI_INVALID_HANDLE;
+                       transport->produce_size = 0;
+                       transport->consume_size = 0;
+               }
+
+               kfree(transport);
        }
+}
+
+static void vmci_transport_cleanup(struct work_struct *work)
+{
+       LIST_HEAD(pending);
+
+       spin_lock_bh(&vmci_transport_cleanup_lock);
+       list_replace_init(&vmci_transport_cleanup_list, &pending);
+       spin_unlock_bh(&vmci_transport_cleanup_lock);
+       vmci_transport_free_resources(&pending);
+}
+
+static void vmci_transport_destruct(struct vsock_sock *vsk)
+{
+       /* Ensure that the detach callback doesn't use the sk/vsk
+        * we are about to destruct.
+        */
+       spin_lock_bh(&vmci_trans(vsk)->lock);
+       vmci_trans(vsk)->sk = NULL;
+       spin_unlock_bh(&vmci_trans(vsk)->lock);
 
        if (vmci_trans(vsk)->notify_ops)
                vmci_trans(vsk)->notify_ops->socket_destruct(vsk);
 
-       kfree(vsk->trans);
+       spin_lock_bh(&vmci_transport_cleanup_lock);
+       list_add(&vmci_trans(vsk)->elem, &vmci_transport_cleanup_list);
+       spin_unlock_bh(&vmci_transport_cleanup_lock);
+       schedule_work(&vmci_transport_cleanup_work);
+
        vsk->trans = NULL;
 }
 
@@ -2146,6 +2135,9 @@ module_init(vmci_transport_init);
 
 static void __exit vmci_transport_exit(void)
 {
+       cancel_work_sync(&vmci_transport_cleanup_work);
+       vmci_transport_free_resources(&vmci_transport_cleanup_list);
+
        if (!vmci_handle_is_invalid(vmci_transport_stream_handle)) {
                if (vmci_datagram_destroy_handle(
                        vmci_transport_stream_handle) != VMCI_SUCCESS)
@@ -2164,6 +2156,7 @@ module_exit(vmci_transport_exit);
 
 MODULE_AUTHOR("VMware, Inc.");
 MODULE_DESCRIPTION("VMCI transport for Virtual Sockets");
+MODULE_VERSION("1.0.2.0-k");
 MODULE_LICENSE("GPL v2");
 MODULE_ALIAS("vmware_vsock");
 MODULE_ALIAS_NETPROTO(PF_VSOCK);
index ce6c9623d5f069029ce58294bcc7de9bc3728fcd..2ad46f39649f8130d9f19ce48ccf8a8b4309797d 100644 (file)
@@ -119,10 +119,12 @@ struct vmci_transport {
        u64 queue_pair_size;
        u64 queue_pair_min_size;
        u64 queue_pair_max_size;
-       u32 attach_sub_id;
        u32 detach_sub_id;
        union vmci_transport_notify notify;
        struct vmci_transport_notify_ops *notify_ops;
+       struct list_head elem;
+       struct sock *sk;
+       spinlock_t lock; /* protects sk. */
 };
 
 int vmci_transport_register(void);
index a8de9e3002000d7eaa76f6764797e5b231d187ff..24e06a2377f6b3601003157d22dd05bb0278f145 100644 (file)
@@ -1928,8 +1928,10 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
        struct nlattr *rp = attrs[XFRMA_REPLAY_VAL];
        struct nlattr *re = attrs[XFRMA_REPLAY_ESN_VAL];
        struct nlattr *lt = attrs[XFRMA_LTIME_VAL];
+       struct nlattr *et = attrs[XFRMA_ETIMER_THRESH];
+       struct nlattr *rt = attrs[XFRMA_REPLAY_THRESH];
 
-       if (!lt && !rp && !re)
+       if (!lt && !rp && !re && !et && !rt)
                return err;
 
        /* pedantic mode - thou shalt sayeth replaceth */
index 3a44d3a272af40119b379fe1930244909499fd8d..af44e564d6ddc1278e6edce3c6b18a7879c76ecd 100644 (file)
@@ -86,5 +86,17 @@ static int (*bpf_l4_csum_replace)(void *ctx, int off, int from, int to, int flag
 #define PT_REGS_RC(x) ((x)->gprs[2])
 #define PT_REGS_SP(x) ((x)->gprs[15])
 
+#elif defined(__aarch64__)
+
+#define PT_REGS_PARM1(x) ((x)->regs[0])
+#define PT_REGS_PARM2(x) ((x)->regs[1])
+#define PT_REGS_PARM3(x) ((x)->regs[2])
+#define PT_REGS_PARM4(x) ((x)->regs[3])
+#define PT_REGS_PARM5(x) ((x)->regs[4])
+#define PT_REGS_RET(x) ((x)->regs[30])
+#define PT_REGS_FP(x) ((x)->regs[29]) /* Works only with CONFIG_FRAME_POINTER */
+#define PT_REGS_RC(x) ((x)->regs[0])
+#define PT_REGS_SP(x) ((x)->sp)
+
 #endif
 #endif
index 9119ac6a82702972d5973c0da0a1e9399d665b8a..c285a3b8a9f1a5d88e4fc229368ac6ad25473f29 100644 (file)
@@ -1,13 +1,13 @@
 /*
  * Here's a sample kernel module showing the use of jprobes to dump
- * the arguments of do_fork().
+ * the arguments of _do_fork().
  *
  * For more information on theory of operation of jprobes, see
  * Documentation/kprobes.txt
  *
  * Build and insert the kernel module as done in the kprobe example.
  * You will see the trace data in /var/log/messages and on the
- * console whenever do_fork() is invoked to create a new process.
+ * console whenever _do_fork() is invoked to create a new process.
  * (Some messages may be suppressed if syslogd is configured to
  * eliminate duplicate messages.)
  */
 #include <linux/kprobes.h>
 
 /*
- * Jumper probe for do_fork.
+ * Jumper probe for _do_fork.
  * Mirror principle enables access to arguments of the probed routine
  * from the probe handler.
  */
 
-/* Proxy routine having the same arguments as actual do_fork() routine */
-static long jdo_fork(unsigned long clone_flags, unsigned long stack_start,
+/* Proxy routine having the same arguments as actual _do_fork() routine */
+static long j_do_fork(unsigned long clone_flags, unsigned long stack_start,
              unsigned long stack_size, int __user *parent_tidptr,
              int __user *child_tidptr)
 {
@@ -36,9 +36,9 @@ static long jdo_fork(unsigned long clone_flags, unsigned long stack_start,
 }
 
 static struct jprobe my_jprobe = {
-       .entry                  = jdo_fork,
+       .entry                  = j_do_fork,
        .kp = {
-               .symbol_name    = "do_fork",
+               .symbol_name    = "_do_fork",
        },
 };
 
index 366db1a9fb65b5662ffdb14564750c60b6f012c7..727eb21c9c5624f2998f321d59db1017339c69a3 100644 (file)
@@ -1,13 +1,13 @@
 /*
  * NOTE: This example is works on x86 and powerpc.
  * Here's a sample kernel module showing the use of kprobes to dump a
- * stack trace and selected registers when do_fork() is called.
+ * stack trace and selected registers when _do_fork() is called.
  *
  * For more information on theory of operation of kprobes, see
  * Documentation/kprobes.txt
  *
  * You will see the trace data in /var/log/messages and on the console
- * whenever do_fork() is invoked to create a new process.
+ * whenever _do_fork() is invoked to create a new process.
  */
 
 #include <linux/kernel.h>
@@ -16,7 +16,7 @@
 
 /* For each probe you need to allocate a kprobe structure */
 static struct kprobe kp = {
-       .symbol_name    = "do_fork",
+       .symbol_name    = "_do_fork",
 };
 
 /* kprobe pre_handler: called just before the probed instruction is executed */
index 1041b6731598137d22752334054cd9054fcdabb6..ebb1d1aed54782f2e4a0126e1de886c63767d056 100644 (file)
@@ -7,7 +7,7 @@
  *
  * usage: insmod kretprobe_example.ko func=<func_name>
  *
- * If no func_name is specified, do_fork is instrumented
+ * If no func_name is specified, _do_fork is instrumented
  *
  * For more information on theory of operation of kretprobes, see
  * Documentation/kprobes.txt
@@ -25,7 +25,7 @@
 #include <linux/limits.h>
 #include <linux/sched.h>
 
-static char func_name[NAME_MAX] = "do_fork";
+static char func_name[NAME_MAX] = "_do_fork";
 module_param_string(func, func_name, NAME_MAX, S_IRUGO);
 MODULE_PARM_DESC(func, "Function to kretprobe; this module will report the"
                        " function's execution time");
index 10d23ca9f6176c5ec9ea8ac71a909d3c39acee26..b071bf476fea7ede6aab95730f5844ac1bf5caa5 100644 (file)
@@ -1,15 +1,15 @@
 /* Extract X.509 certificate in DER form from PKCS#11 or PEM.
  *
- * Copyright Â© 2014 Red Hat, Inc. All Rights Reserved.
- * Copyright Â© 2015 Intel Corporation.
+ * Copyright Â© 2014-2015 Red Hat, Inc. All Rights Reserved.
+ * Copyright Â© 2015      Intel Corporation.
  *
  * Authors: David Howells <dhowells@redhat.com>
  *          David Woodhouse <dwmw2@infradead.org>
  *
  * 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.
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the licence, or (at your option) any later version.
  */
 #define _GNU_SOURCE
 #include <stdio.h>
 #include <stdint.h>
 #include <stdbool.h>
 #include <string.h>
-#include <getopt.h>
 #include <err.h>
-#include <arpa/inet.h>
 #include <openssl/bio.h>
-#include <openssl/evp.h>
 #include <openssl/pem.h>
-#include <openssl/pkcs7.h>
 #include <openssl/err.h>
 #include <openssl/engine.h>
 
index 0cd46e129920e8ad114eb335ae92ce85230d068d..b967e4f9fed2e6cc78b9538c79517a473fc375b8 100755 (executable)
@@ -115,7 +115,7 @@ esac
 BUILD_DEBUG="$(grep -s '^CONFIG_DEBUG_INFO=y' $KCONFIG_CONFIG || true)"
 
 # Setup the directory structure
-rm -rf "$tmpdir" "$fwdir" "$kernel_headers_dir" "$libc_headers_dir" "$dbg_dir"
+rm -rf "$tmpdir" "$fwdir" "$kernel_headers_dir" "$libc_headers_dir" "$dbg_dir" $objtree/debian/files
 mkdir -m 755 -p "$tmpdir/DEBIAN"
 mkdir -p "$tmpdir/lib" "$tmpdir/boot"
 mkdir -p "$fwdir/lib/firmware/$version/"
@@ -408,7 +408,7 @@ binary-arch:
        \$(MAKE) KDEB_SOURCENAME=${sourcename} KDEB_PKGVERSION=${packageversion} bindeb-pkg
 
 clean:
-       rm -rf debian/*tmp
+       rm -rf debian/*tmp debian/files
        mv debian/ debian.backup # debian/ might be cleaned away
        \$(MAKE) clean
        mv debian.backup debian
index 058bba3103e2707911cd493f70a1b39015f9d697..250a7a6450331ae0805aaf3100da46af66dd4827 100755 (executable)
@@ -1,12 +1,15 @@
 /* Sign a module file using the given key.
  *
- * Copyright (C) 2014 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
+ * Copyright Â© 2014-2015 Red Hat, Inc. All Rights Reserved.
+ * Copyright Â© 2015      Intel Corporation.
+ *
+ * Authors: David Howells <dhowells@redhat.com>
+ *          David Woodhouse <dwmw2@infradead.org>
  *
  * 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.
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the licence, or (at your option) any later version.
  */
 #define _GNU_SOURCE
 #include <stdio.h>
 #include <getopt.h>
 #include <err.h>
 #include <arpa/inet.h>
+#include <openssl/opensslv.h>
 #include <openssl/bio.h>
 #include <openssl/evp.h>
 #include <openssl/pem.h>
-#include <openssl/cms.h>
 #include <openssl/err.h>
 #include <openssl/engine.h>
 
+/*
+ * Use CMS if we have openssl-1.0.0 or newer available - otherwise we have to
+ * assume that it's not available and its header file is missing and that we
+ * should use PKCS#7 instead.  Switching to the older PKCS#7 format restricts
+ * the options we have on specifying the X.509 certificate we want.
+ *
+ * Further, older versions of OpenSSL don't support manually adding signers to
+ * the PKCS#7 message so have to accept that we get a certificate included in
+ * the signature message.  Nor do such older versions of OpenSSL support
+ * signing with anything other than SHA1 - so we're stuck with that if such is
+ * the case.
+ */
+#if OPENSSL_VERSION_NUMBER < 0x10000000L
+#define USE_PKCS7
+#endif
+#ifndef USE_PKCS7
+#include <openssl/cms.h>
+#else
+#include <openssl/pkcs7.h>
+#endif
+
 struct module_signature {
        uint8_t         algo;           /* Public-key crypto algorithm [0] */
        uint8_t         hash;           /* Digest algorithm [0] */
@@ -107,30 +131,42 @@ int main(int argc, char **argv)
        struct module_signature sig_info = { .id_type = PKEY_ID_PKCS7 };
        char *hash_algo = NULL;
        char *private_key_name, *x509_name, *module_name, *dest_name;
-       bool save_cms = false, replace_orig;
+       bool save_sig = false, replace_orig;
        bool sign_only = false;
        unsigned char buf[4096];
-       unsigned long module_size, cms_size;
-       unsigned int use_keyid = 0, use_signed_attrs = CMS_NOATTR;
+       unsigned long module_size, sig_size;
+       unsigned int use_signed_attrs;
        const EVP_MD *digest_algo;
        EVP_PKEY *private_key;
+#ifndef USE_PKCS7
        CMS_ContentInfo *cms;
+       unsigned int use_keyid = 0;
+#else
+       PKCS7 *pkcs7;
+#endif
        X509 *x509;
        BIO *b, *bd = NULL, *bm;
        int opt, n;
-
        OpenSSL_add_all_algorithms();
        ERR_load_crypto_strings();
        ERR_clear_error();
 
        key_pass = getenv("KBUILD_SIGN_PIN");
 
+#ifndef USE_PKCS7
+       use_signed_attrs = CMS_NOATTR;
+#else
+       use_signed_attrs = PKCS7_NOATTR;
+#endif
+
        do {
                opt = getopt(argc, argv, "dpk");
                switch (opt) {
-               case 'p': save_cms = true; break;
-               case 'd': sign_only = true; save_cms = true; break;
+               case 'p': save_sig = true; break;
+               case 'd': sign_only = true; save_sig = true; break;
+#ifndef USE_PKCS7
                case 'k': use_keyid = CMS_USE_KEYID; break;
+#endif
                case -1: break;
                default: format();
                }
@@ -154,6 +190,14 @@ int main(int argc, char **argv)
                replace_orig = true;
        }
 
+#ifdef USE_PKCS7
+       if (strcmp(hash_algo, "sha1") != 0) {
+               fprintf(stderr, "sign-file: %s only supports SHA1 signing\n",
+                       OPENSSL_VERSION_TEXT);
+               exit(3);
+       }
+#endif
+
        /* Read the private key and the X.509 cert the PKCS#7 message
         * will point to.
         */
@@ -210,7 +254,8 @@ int main(int argc, char **argv)
        bm = BIO_new_file(module_name, "rb");
        ERR(!bm, "%s", module_name);
 
-       /* Load the CMS message from the digest buffer. */
+#ifndef USE_PKCS7
+       /* Load the signature message from the digest buffer. */
        cms = CMS_sign(NULL, NULL, NULL, NULL,
                       CMS_NOCERTS | CMS_PARTIAL | CMS_BINARY | CMS_DETACHED | CMS_STREAM);
        ERR(!cms, "CMS_sign");
@@ -218,17 +263,31 @@ int main(int argc, char **argv)
        ERR(!CMS_add1_signer(cms, x509, private_key, digest_algo,
                             CMS_NOCERTS | CMS_BINARY | CMS_NOSMIMECAP |
                             use_keyid | use_signed_attrs),
-           "CMS_sign_add_signer");
+           "CMS_add1_signer");
        ERR(CMS_final(cms, bm, NULL, CMS_NOCERTS | CMS_BINARY) < 0,
            "CMS_final");
 
-       if (save_cms) {
-               char *cms_name;
+#else
+       pkcs7 = PKCS7_sign(x509, private_key, NULL, bm,
+                          PKCS7_NOCERTS | PKCS7_BINARY |
+                          PKCS7_DETACHED | use_signed_attrs);
+       ERR(!pkcs7, "PKCS7_sign");
+#endif
+
+       if (save_sig) {
+               char *sig_file_name;
 
-               ERR(asprintf(&cms_name, "%s.p7s", module_name) < 0, "asprintf");
-               b = BIO_new_file(cms_name, "wb");
-               ERR(!b, "%s", cms_name);
-               ERR(i2d_CMS_bio_stream(b, cms, NULL, 0) < 0, "%s", cms_name);
+               ERR(asprintf(&sig_file_name, "%s.p7s", module_name) < 0,
+                   "asprintf");
+               b = BIO_new_file(sig_file_name, "wb");
+               ERR(!b, "%s", sig_file_name);
+#ifndef USE_PKCS7
+               ERR(i2d_CMS_bio_stream(b, cms, NULL, 0) < 0,
+                   "%s", sig_file_name);
+#else
+               ERR(i2d_PKCS7_bio(b, pkcs7) < 0,
+                       "%s", sig_file_name);
+#endif
                BIO_free(b);
        }
 
@@ -244,9 +303,13 @@ int main(int argc, char **argv)
        ERR(n < 0, "%s", module_name);
        module_size = BIO_number_written(bd);
 
+#ifndef USE_PKCS7
        ERR(i2d_CMS_bio_stream(bd, cms, NULL, 0) < 0, "%s", dest_name);
-       cms_size = BIO_number_written(bd) - module_size;
-       sig_info.sig_len = htonl(cms_size);
+#else
+       ERR(i2d_PKCS7_bio(bd, pkcs7) < 0, "%s", dest_name);
+#endif
+       sig_size = BIO_number_written(bd) - module_size;
+       sig_info.sig_len = htonl(sig_size);
        ERR(BIO_write(bd, &sig_info, sizeof(sig_info)) < 0, "%s", dest_name);
        ERR(BIO_write(bd, magic_number, sizeof(magic_number) - 1) < 0, "%s", dest_name);
 
index 73455089feef3a11af0d88880fa6423070c50ea5..03c1652c9a1f593669b6d9e3a0bd2e65e47da239 100644 (file)
@@ -401,7 +401,7 @@ static bool verify_new_ex(struct dev_cgroup *dev_cgroup,
        bool match = false;
 
        RCU_LOCKDEP_WARN(!rcu_read_lock_held() &&
-                        lockdep_is_held(&devcgroup_mutex),
+                        !lockdep_is_held(&devcgroup_mutex),
                         "device_cgroup:verify_new_ex called without proper synchronization");
 
        if (dev_cgroup->behavior == DEVCG_DEFAULT_ALLOW) {
index c7952375ac5325cfb4c403fa1020671b5f31a150..addf060399e09547307d9c023f36d8dbf869a931 100644 (file)
@@ -134,6 +134,12 @@ static noinline void key_gc_unused_keys(struct list_head *keys)
                kdebug("- %u", key->serial);
                key_check(key);
 
+               /* Throw away the key data if the key is instantiated */
+               if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags) &&
+                   !test_bit(KEY_FLAG_NEGATIVE, &key->flags) &&
+                   key->type->destroy)
+                       key->type->destroy(key);
+
                security_key_free(key);
 
                /* deal with the user's key tracking and quota */
@@ -148,10 +154,6 @@ static noinline void key_gc_unused_keys(struct list_head *keys)
                if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags))
                        atomic_dec(&key->user->nikeys);
 
-               /* now throw away the key memory */
-               if (key->type->destroy)
-                       key->type->destroy(key);
-
                key_user_put(key->user);
 
                kfree(key->description);
index 486ef6fa393b2cc9d8ceb8cb11f187f97730bd90..0d625312427831b63ed18784719cd0b424f03a41 100644 (file)
@@ -440,6 +440,9 @@ static struct key *construct_key_and_link(struct keyring_search_context *ctx,
 
        kenter("");
 
+       if (ctx->index_key.type == &key_type_keyring)
+               return ERR_PTR(-EPERM);
+       
        user = key_user_lookup(current_fsuid());
        if (!user)
                return ERR_PTR(-ENOMEM);
index 885683a3b0bdf084985328151d35308d4ebb5afb..e0406211716b003daae37efbc8cdfd73213b31f3 100644 (file)
@@ -9,6 +9,14 @@ menuconfig SND_ARM
          Drivers that are implemented on ASoC can be found in
          "ALSA for SoC audio support" section.
 
+config SND_PXA2XX_LIB
+       tristate
+       select SND_AC97_CODEC if SND_PXA2XX_LIB_AC97
+       select SND_DMAENGINE_PCM
+
+config SND_PXA2XX_LIB_AC97
+       bool
+
 if SND_ARM
 
 config SND_ARMAACI
@@ -21,13 +29,6 @@ config SND_PXA2XX_PCM
        tristate
        select SND_PCM
 
-config SND_PXA2XX_LIB
-       tristate
-       select SND_AC97_CODEC if SND_PXA2XX_LIB_AC97
-
-config SND_PXA2XX_LIB_AC97
-       bool
-
 config SND_PXA2XX_AC97
        tristate "AC97 driver for the Intel PXA2xx chip"
        depends on ARCH_PXA
index 4449d1a990893db4078a102b9da0f92835d5add3..2433f7c81472848be51b9af420ec198b523871b1 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/io.h>
 #include <sound/hdaudio_ext.h>
 
 MODULE_DESCRIPTION("HDA extended core");
index 37f43a1b34ef1f5f48682230055c0f01d9a07449..a249d5486889dca683af566e0818d95ee49b12ae 100644 (file)
@@ -3367,10 +3367,8 @@ int snd_hda_codec_build_pcms(struct hda_codec *codec)
        int dev, err;
 
        err = snd_hda_codec_parse_pcms(codec);
-       if (err < 0) {
-               snd_hda_codec_reset(codec);
+       if (err < 0)
                return err;
-       }
 
        /* attach a new PCM streams */
        list_for_each_entry(cpcm, &codec->pcm_list_head, list) {
index 477742cb70a2d1364b8e6c8cc7c984651ed58681..58c0aad372842125be5529d07aecbbe98e2c8859 100644 (file)
@@ -73,6 +73,7 @@ struct hda_tegra {
        struct clk *hda2codec_2x_clk;
        struct clk *hda2hdmi_clk;
        void __iomem *regs;
+       struct work_struct probe_work;
 };
 
 #ifdef CONFIG_PM
@@ -294,7 +295,9 @@ static int hda_tegra_dev_disconnect(struct snd_device *device)
 static int hda_tegra_dev_free(struct snd_device *device)
 {
        struct azx *chip = device->device_data;
+       struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip);
 
+       cancel_work_sync(&hda->probe_work);
        if (azx_bus(chip)->chip_init) {
                azx_stop_all_streams(chip);
                azx_stop_chip(chip);
@@ -426,6 +429,9 @@ static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev)
 /*
  * constructor
  */
+
+static void hda_tegra_probe_work(struct work_struct *work);
+
 static int hda_tegra_create(struct snd_card *card,
                            unsigned int driver_caps,
                            struct hda_tegra *hda)
@@ -452,6 +458,8 @@ static int hda_tegra_create(struct snd_card *card,
        chip->single_cmd = false;
        chip->snoop = true;
 
+       INIT_WORK(&hda->probe_work, hda_tegra_probe_work);
+
        err = azx_bus_init(chip, NULL, &hda_tegra_io_ops);
        if (err < 0)
                return err;
@@ -499,6 +507,21 @@ static int hda_tegra_probe(struct platform_device *pdev)
        card->private_data = chip;
 
        dev_set_drvdata(&pdev->dev, card);
+       schedule_work(&hda->probe_work);
+
+       return 0;
+
+out_free:
+       snd_card_free(card);
+       return err;
+}
+
+static void hda_tegra_probe_work(struct work_struct *work)
+{
+       struct hda_tegra *hda = container_of(work, struct hda_tegra, probe_work);
+       struct azx *chip = &hda->chip;
+       struct platform_device *pdev = to_platform_device(hda->dev);
+       int err;
 
        err = hda_tegra_first_init(chip, pdev);
        if (err < 0)
@@ -520,11 +543,8 @@ static int hda_tegra_probe(struct platform_device *pdev)
        chip->running = 1;
        snd_hda_set_power_save(&chip->bus, power_save * 1000);
 
-       return 0;
-
-out_free:
-       snd_card_free(card);
-       return err;
+ out_free:
+       return; /* no error return from async probe */
 }
 
 static int hda_tegra_remove(struct platform_device *pdev)
index 584a0343ab0cc132b7c2038679923b6617926cf7..85813de26da87715df7d1d259339e30450c7815a 100644 (file)
@@ -633,6 +633,7 @@ static const struct snd_pci_quirk cs4208_mac_fixup_tbl[] = {
        SND_PCI_QUIRK(0x106b, 0x5e00, "MacBookPro 11,2", CS4208_MBP11),
        SND_PCI_QUIRK(0x106b, 0x7100, "MacBookAir 6,1", CS4208_MBA6),
        SND_PCI_QUIRK(0x106b, 0x7200, "MacBookAir 6,2", CS4208_MBA6),
+       SND_PCI_QUIRK(0x106b, 0x7b00, "MacBookPro 12,1", CS4208_MBP11),
        {} /* terminator */
 };
 
index ca03c40609fcf09d8838ed05f4920de3f03a6cf7..2f0ec7c45fc70d6232339761e5773349d24213a9 100644 (file)
@@ -819,6 +819,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
        SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT_PINCFG_LENOVO_TP410),
        SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT_PINCFG_LENOVO_TP410),
        SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo IdeaPad Z560", CXT_FIXUP_MUTE_LED_EAPD),
+       SND_PCI_QUIRK(0x17aa, 0x390b, "Lenovo G50-80", CXT_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x17aa, 0x397b, "Lenovo S205", CXT_FIXUP_STEREO_DMIC),
index a75b5611d1e40121a5947e7a8f86e828307b7c9a..16b8dcba5c12d2d13ed7c80c4e6f93df69d9944f 100644 (file)
@@ -4188,6 +4188,24 @@ static void alc_fixup_disable_aamix(struct hda_codec *codec,
        }
 }
 
+/* fixup for Thinkpad docks: add dock pins, avoid HP parser fixup */
+static void alc_fixup_tpt440_dock(struct hda_codec *codec,
+                                 const struct hda_fixup *fix, int action)
+{
+       static const struct hda_pintbl pincfgs[] = {
+               { 0x16, 0x21211010 }, /* dock headphone */
+               { 0x19, 0x21a11010 }, /* dock mic */
+               { }
+       };
+       struct alc_spec *spec = codec->spec;
+
+       if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+               spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
+               codec->power_save_node = 0; /* avoid click noises */
+               snd_hda_apply_pincfgs(codec, pincfgs);
+       }
+}
+
 static void alc_shutup_dell_xps13(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
@@ -4562,7 +4580,6 @@ enum {
        ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC,
        ALC293_FIXUP_DELL1_MIC_NO_PRESENCE,
        ALC292_FIXUP_TPT440_DOCK,
-       ALC292_FIXUP_TPT440_DOCK2,
        ALC283_FIXUP_BXBT2807_MIC,
        ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED,
        ALC282_FIXUP_ASPIRE_V5_PINS,
@@ -5029,17 +5046,7 @@ static const struct hda_fixup alc269_fixups[] = {
        },
        [ALC292_FIXUP_TPT440_DOCK] = {
                .type = HDA_FIXUP_FUNC,
-               .v.func = alc269_fixup_pincfg_no_hp_to_lineout,
-               .chained = true,
-               .chain_id = ALC292_FIXUP_TPT440_DOCK2
-       },
-       [ALC292_FIXUP_TPT440_DOCK2] = {
-               .type = HDA_FIXUP_PINS,
-               .v.pins = (const struct hda_pintbl[]) {
-                       { 0x16, 0x21211010 }, /* dock headphone */
-                       { 0x19, 0x21a11010 }, /* dock mic */
-                       { }
-               },
+               .v.func = alc_fixup_tpt440_dock,
                .chained = true,
                .chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
        },
@@ -5299,6 +5306,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x2212, "Thinkpad T440", ALC292_FIXUP_TPT440_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x2214, "Thinkpad X240", ALC292_FIXUP_TPT440_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x2215, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
+       SND_PCI_QUIRK(0x17aa, 0x2223, "ThinkPad T550", ALC292_FIXUP_TPT440_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x2226, "ThinkPad X250", ALC292_FIXUP_TPT440_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC),
        SND_PCI_QUIRK(0x17aa, 0x3978, "IdeaPad Y410P", ALC269_FIXUP_NO_SHUTUP),
index 9d947aef2c8b60b99f63fd9464ad289bef0c7061..def5cc8dff0293c2f70c4c3fcf67da1aea1bf55e 100644 (file)
@@ -4520,7 +4520,11 @@ static int patch_stac92hd73xx(struct hda_codec *codec)
                return err;
 
        spec = codec->spec;
-       codec->power_save_node = 1;
+       /* enable power_save_node only for new 92HD89xx chips, as it causes
+        * click noises on old 92HD73xx chips.
+        */
+       if ((codec->core.vendor_id & 0xfffffff0) != 0x111d7670)
+               codec->power_save_node = 1;
        spec->linear_tone_beep = 0;
        spec->gen.mixer_nid = 0x1d;
        spec->have_spdif_mux = 1;
index 58c3164802b8ceda545e1469f557a814702694be..8c907ebea18960ec8e48942f5746fd2121705736 100644 (file)
@@ -129,6 +129,8 @@ static struct snd_soc_dai_link db1300_i2s_dai = {
        .cpu_dai_name   = "au1xpsc_i2s.2",
        .platform_name  = "au1xpsc-pcm.2",
        .codec_name     = "wm8731.0-001b",
+       .dai_fmt        = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF |
+                         SND_SOC_DAIFMT_CBM_CFM,
        .ops            = &db1200_i2s_wm8731_ops,
 };
 
@@ -146,6 +148,8 @@ static struct snd_soc_dai_link db1550_i2s_dai = {
        .cpu_dai_name   = "au1xpsc_i2s.3",
        .platform_name  = "au1xpsc-pcm.3",
        .codec_name     = "wm8731.0-001b",
+       .dai_fmt        = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF |
+                         SND_SOC_DAIFMT_CBM_CFM,
        .ops            = &db1200_i2s_wm8731_ops,
 };
 
index 38e853add96ecb4236f50225e6089401a0740e22..0bf9d62b91a07132fa1af21f902bfa257cdfee4b 100644 (file)
@@ -296,7 +296,6 @@ static int au1xpsc_i2s_drvprobe(struct platform_device *pdev)
 {
        struct resource *iores, *dmares;
        unsigned long sel;
-       int ret;
        struct au1xpsc_audio_data *wd;
 
        wd = devm_kzalloc(&pdev->dev, sizeof(struct au1xpsc_audio_data),
index 3c2f0f8d6266e358a667aa376fea3d094829845a..f823eb502367dccad4b93e71ac7e06d30c0bccdf 100644 (file)
@@ -50,24 +50,24 @@ struct rt298_priv {
 };
 
 static struct reg_default rt298_index_def[] = {
-       { 0x01, 0xaaaa },
-       { 0x02, 0x8aaa },
+       { 0x01, 0xa5a8 },
+       { 0x02, 0x8e95 },
        { 0x03, 0x0002 },
-       { 0x04, 0xaf01 },
-       { 0x08, 0x000d },
-       { 0x09, 0xd810 },
-       { 0x0a, 0x0120 },
+       { 0x04, 0xaf67 },
+       { 0x08, 0x200f },
+       { 0x09, 0xd010 },
+       { 0x0a, 0x0100 },
        { 0x0b, 0x0000 },
        { 0x0d, 0x2800 },
-       { 0x0f, 0x0000 },
-       { 0x19, 0x0a17 },
+       { 0x0f, 0x0022 },
+       { 0x19, 0x0217 },
        { 0x20, 0x0020 },
        { 0x33, 0x0208 },
        { 0x46, 0x0300 },
-       { 0x49, 0x0004 },
-       { 0x4f, 0x50e9 },
-       { 0x50, 0x2000 },
-       { 0x63, 0x2902 },
+       { 0x49, 0x4004 },
+       { 0x4f, 0x50c9 },
+       { 0x50, 0x3000 },
+       { 0x63, 0x1b02 },
        { 0x67, 0x1111 },
        { 0x68, 0x1016 },
        { 0x69, 0x273f },
@@ -1214,7 +1214,7 @@ static int rt298_i2c_probe(struct i2c_client *i2c,
        mdelay(10);
 
        if (!rt298->pdata.gpio2_en)
-               regmap_write(rt298->regmap, RT298_SET_DMIC2_DEFAULT, 0x4000);
+               regmap_write(rt298->regmap, RT298_SET_DMIC2_DEFAULT, 0x40);
        else
                regmap_write(rt298->regmap, RT298_SET_DMIC2_DEFAULT, 0);
 
index 4972bf3efa91c4849928f480bd08ebc3388a53db..5c101af0ac630dddf1cf12085846d5cfd9c08911 100644 (file)
@@ -519,11 +519,11 @@ static const struct snd_kcontrol_new rt5645_snd_controls[] = {
                RT5645_L_VOL_SFT + 1, RT5645_R_VOL_SFT + 1, 63, 0, adc_vol_tlv),
 
        /* ADC Boost Volume Control */
-       SOC_DOUBLE_TLV("STO1 ADC Boost Gain", RT5645_ADC_BST_VOL1,
+       SOC_DOUBLE_TLV("ADC Boost Capture Volume", RT5645_ADC_BST_VOL1,
                RT5645_STO1_ADC_L_BST_SFT, RT5645_STO1_ADC_R_BST_SFT, 3, 0,
                adc_bst_tlv),
-       SOC_DOUBLE_TLV("STO2 ADC Boost Gain", RT5645_ADC_BST_VOL1,
-               RT5645_STO2_ADC_L_BST_SFT, RT5645_STO2_ADC_R_BST_SFT, 3, 0,
+       SOC_DOUBLE_TLV("Mono ADC Boost Capture Volume", RT5645_ADC_BST_VOL2,
+               RT5645_MONO_ADC_L_BST_SFT, RT5645_MONO_ADC_R_BST_SFT, 3, 0,
                adc_bst_tlv),
 
        /* I2S2 function select */
@@ -732,14 +732,14 @@ static const struct snd_kcontrol_new rt5645_mono_adc_r_mix[] = {
 static const struct snd_kcontrol_new rt5645_dac_l_mix[] = {
        SOC_DAPM_SINGLE("Stereo ADC Switch", RT5645_AD_DA_MIXER,
                        RT5645_M_ADCMIX_L_SFT, 1, 1),
-       SOC_DAPM_SINGLE("DAC1 Switch", RT5645_AD_DA_MIXER,
+       SOC_DAPM_SINGLE_AUTODISABLE("DAC1 Switch", RT5645_AD_DA_MIXER,
                        RT5645_M_DAC1_L_SFT, 1, 1),
 };
 
 static const struct snd_kcontrol_new rt5645_dac_r_mix[] = {
        SOC_DAPM_SINGLE("Stereo ADC Switch", RT5645_AD_DA_MIXER,
                        RT5645_M_ADCMIX_R_SFT, 1, 1),
-       SOC_DAPM_SINGLE("DAC1 Switch", RT5645_AD_DA_MIXER,
+       SOC_DAPM_SINGLE_AUTODISABLE("DAC1 Switch", RT5645_AD_DA_MIXER,
                        RT5645_M_DAC1_R_SFT, 1, 1),
 };
 
@@ -1381,7 +1381,7 @@ static void hp_amp_power(struct snd_soc_codec *codec, int on)
                                regmap_write(rt5645->regmap, RT5645_PR_BASE +
                                        RT5645_MAMP_INT_REG2, 0xfc00);
                                snd_soc_write(codec, RT5645_DEPOP_M2, 0x1140);
-                               mdelay(5);
+                               msleep(40);
                                rt5645->hp_on = true;
                        } else {
                                /* depop parameters */
@@ -2829,13 +2829,12 @@ static int rt5645_jack_detect(struct snd_soc_codec *codec, int jack_insert)
                        snd_soc_dapm_sync(dapm);
                        rt5645->jack_type = SND_JACK_HEADPHONE;
                }
-
-               snd_soc_update_bits(codec, RT5645_CHARGE_PUMP, 0x0300, 0x0200);
-               snd_soc_write(codec, RT5645_DEPOP_M1, 0x001d);
-               snd_soc_write(codec, RT5645_DEPOP_M1, 0x0001);
        } else { /* jack out */
                rt5645->jack_type = 0;
 
+               regmap_update_bits(rt5645->regmap, RT5645_HP_VOL,
+                       RT5645_L_MUTE | RT5645_R_MUTE,
+                       RT5645_L_MUTE | RT5645_R_MUTE);
                regmap_update_bits(rt5645->regmap, RT5645_IN1_CTRL2,
                        RT5645_CBJ_MN_JD, RT5645_CBJ_MN_JD);
                regmap_update_bits(rt5645->regmap, RT5645_IN1_CTRL1,
@@ -2880,8 +2879,6 @@ int rt5645_set_jack_detect(struct snd_soc_codec *codec,
                rt5645->en_button_func = true;
                regmap_update_bits(rt5645->regmap, RT5645_GPIO_CTRL1,
                                RT5645_GP1_PIN_IRQ, RT5645_GP1_PIN_IRQ);
-               regmap_update_bits(rt5645->regmap, RT5645_DEPOP_M1,
-                               RT5645_HP_CB_MASK, RT5645_HP_CB_PU);
                regmap_update_bits(rt5645->regmap, RT5645_GEN_CTRL1,
                                RT5645_DIG_GATE_CTRL, RT5645_DIG_GATE_CTRL);
        }
@@ -3205,6 +3202,13 @@ static const struct dmi_system_id dmi_platform_intel_braswell[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Celes"),
                },
        },
+       {
+               .ident = "Google Ultima",
+               .callback = strago_quirk_cb,
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Ultima"),
+               },
+       },
        { }
 };
 
index 0e4cfc6ac64984acb1bd395a7477b7cf21cfc020..8c964cfb120ddc4130e5d39e9ab96ae34623eb34 100644 (file)
@@ -39,8 +39,8 @@
 #define RT5645_STO1_ADC_DIG_VOL                        0x1c
 #define RT5645_MONO_ADC_DIG_VOL                        0x1d
 #define RT5645_ADC_BST_VOL1                    0x1e
-/* Mixer - D-D */
 #define RT5645_ADC_BST_VOL2                    0x20
+/* Mixer - D-D */
 #define RT5645_STO1_ADC_MIXER                  0x27
 #define RT5645_MONO_ADC_MIXER                  0x28
 #define RT5645_AD_DA_MIXER                     0x29
 #define RT5645_STO1_ADC_R_BST_SFT              12
 #define RT5645_STO1_ADC_COMP_MASK              (0x3 << 10)
 #define RT5645_STO1_ADC_COMP_SFT               10
-#define RT5645_STO2_ADC_L_BST_MASK             (0x3 << 8)
-#define RT5645_STO2_ADC_L_BST_SFT              8
-#define RT5645_STO2_ADC_R_BST_MASK             (0x3 << 6)
-#define RT5645_STO2_ADC_R_BST_SFT              6
-#define RT5645_STO2_ADC_COMP_MASK              (0x3 << 4)
-#define RT5645_STO2_ADC_COMP_SFT               4
+
+/* ADC Boost Volume Control (0x20) */
+#define RT5645_MONO_ADC_L_BST_MASK             (0x3 << 14)
+#define RT5645_MONO_ADC_L_BST_SFT              14
+#define RT5645_MONO_ADC_R_BST_MASK             (0x3 << 12)
+#define RT5645_MONO_ADC_R_BST_SFT              12
+#define RT5645_MONO_ADC_COMP_MASK              (0x3 << 10)
+#define RT5645_MONO_ADC_COMP_SFT               10
 
 /* Stereo2 ADC Mixer Control (0x26) */
 #define RT5645_STO2_ADC_SRC_MASK               (0x1 << 15)
index bfda25ef0dd43313f066a7afca06c11b8a8ecbe0..f540f82b1f271ec4833d9ea43aa7f4567c0df712 100644 (file)
@@ -1376,8 +1376,8 @@ static int sgtl5000_probe(struct snd_soc_codec *codec)
                        sgtl5000->micbias_resistor << SGTL5000_BIAS_R_SHIFT);
 
        snd_soc_update_bits(codec, SGTL5000_CHIP_MIC_CTRL,
-                       SGTL5000_BIAS_R_MASK,
-                       sgtl5000->micbias_voltage << SGTL5000_BIAS_R_SHIFT);
+                       SGTL5000_BIAS_VOLT_MASK,
+                       sgtl5000->micbias_voltage << SGTL5000_BIAS_VOLT_SHIFT);
        /*
         * disable DAP
         * TODO:
@@ -1549,7 +1549,7 @@ static int sgtl5000_i2c_probe(struct i2c_client *client,
                        else {
                                sgtl5000->micbias_voltage = 0;
                                dev_err(&client->dev,
-                                       "Unsuitable MicBias resistor\n");
+                                       "Unsuitable MicBias voltage\n");
                        }
                } else {
                        sgtl5000->micbias_voltage = 0;
index e3a0bca28bcf5fb7c454de1abf235c1c5ace347d..cc1d3981fa4b6b92c018d596a0aaac1192f141f1 100644 (file)
@@ -549,7 +549,7 @@ static struct snd_soc_dai_driver tas2552_dai[] = {
 /*
  * DAC digital volumes. From -7 to 24 dB in 1 dB steps
  */
-static DECLARE_TLV_DB_SCALE(dac_tlv, -7, 100, 0);
+static DECLARE_TLV_DB_SCALE(dac_tlv, -700, 100, 0);
 
 static const char * const tas2552_din_source_select[] = {
        "Muted",
index 1a82b19b26442e31eb38e8fa38287d9710aa3546..8739126a1f6f60d4c9e3eac08aaf337c2f7b3a2b 100644 (file)
@@ -1509,14 +1509,17 @@ static int aic3x_init(struct snd_soc_codec *codec)
        snd_soc_write(codec, PGAL_2_LLOPM_VOL, DEFAULT_VOL);
        snd_soc_write(codec, PGAR_2_RLOPM_VOL, DEFAULT_VOL);
 
-       /* Line2 to HP Bypass default volume, disconnect from Output Mixer */
-       snd_soc_write(codec, LINE2L_2_HPLOUT_VOL, DEFAULT_VOL);
-       snd_soc_write(codec, LINE2R_2_HPROUT_VOL, DEFAULT_VOL);
-       snd_soc_write(codec, LINE2L_2_HPLCOM_VOL, DEFAULT_VOL);
-       snd_soc_write(codec, LINE2R_2_HPRCOM_VOL, DEFAULT_VOL);
-       /* Line2 Line Out default volume, disconnect from Output Mixer */
-       snd_soc_write(codec, LINE2L_2_LLOPM_VOL, DEFAULT_VOL);
-       snd_soc_write(codec, LINE2R_2_RLOPM_VOL, DEFAULT_VOL);
+       /* On tlv320aic3104, these registers are reserved and must not be written */
+       if (aic3x->model != AIC3X_MODEL_3104) {
+               /* Line2 to HP Bypass default volume, disconnect from Output Mixer */
+               snd_soc_write(codec, LINE2L_2_HPLOUT_VOL, DEFAULT_VOL);
+               snd_soc_write(codec, LINE2R_2_HPROUT_VOL, DEFAULT_VOL);
+               snd_soc_write(codec, LINE2L_2_HPLCOM_VOL, DEFAULT_VOL);
+               snd_soc_write(codec, LINE2R_2_HPRCOM_VOL, DEFAULT_VOL);
+               /* Line2 Line Out default volume, disconnect from Output Mixer */
+               snd_soc_write(codec, LINE2L_2_LLOPM_VOL, DEFAULT_VOL);
+               snd_soc_write(codec, LINE2R_2_RLOPM_VOL, DEFAULT_VOL);
+       }
 
        switch (aic3x->model) {
        case AIC3X_MODEL_3X:
index f2c6ad4b8fde03f489572e5ce2abf326dd2662b8..581ec1502228ff7d3d367b2582ead6d3af619b21 100644 (file)
@@ -577,7 +577,6 @@ static int wm0010_boot(struct snd_soc_codec *codec)
        struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec);
        unsigned long flags;
        int ret;
-       const struct firmware *fw;
        struct spi_message m;
        struct spi_transfer t;
        struct dfw_pllrec pll_rec;
@@ -623,14 +622,6 @@ static int wm0010_boot(struct snd_soc_codec *codec)
        wm0010->state = WM0010_OUT_OF_RESET;
        spin_unlock_irqrestore(&wm0010->irq_lock, flags);
 
-       /* First the bootloader */
-       ret = request_firmware(&fw, "wm0010_stage2.bin", codec->dev);
-       if (ret != 0) {
-               dev_err(codec->dev, "Failed to request stage2 loader: %d\n",
-                       ret);
-               goto abort;
-       }
-
        if (!wait_for_completion_timeout(&wm0010->boot_completion,
                                         msecs_to_jiffies(20)))
                dev_err(codec->dev, "Failed to get interrupt from DSP\n");
@@ -673,7 +664,7 @@ static int wm0010_boot(struct snd_soc_codec *codec)
 
                img_swap = kzalloc(len, GFP_KERNEL | GFP_DMA);
                if (!img_swap)
-                       goto abort;
+                       goto abort_out;
 
                /* We need to re-order for 0010 */
                byte_swap_64((u64 *)&pll_rec, img_swap, len);
@@ -688,16 +679,16 @@ static int wm0010_boot(struct snd_soc_codec *codec)
                spi_message_add_tail(&t, &m);
 
                ret = spi_sync(spi, &m);
-               if (ret != 0) {
+               if (ret) {
                        dev_err(codec->dev, "First PLL write failed: %d\n", ret);
-                       goto abort;
+                       goto abort_swap;
                }
 
                /* Use a second send of the message to get the return status */
                ret = spi_sync(spi, &m);
-               if (ret != 0) {
+               if (ret) {
                        dev_err(codec->dev, "Second PLL write failed: %d\n", ret);
-                       goto abort;
+                       goto abort_swap;
                }
 
                p = (u32 *)out;
@@ -730,6 +721,10 @@ static int wm0010_boot(struct snd_soc_codec *codec)
 
        return 0;
 
+abort_swap:
+       kfree(img_swap);
+abort_out:
+       kfree(out);
 abort:
        /* Put the chip back into reset */
        wm0010_halt(codec);
index e3b7d0c57411870176c5e1e1398101f5641f77ad..dbd88408861a21af9f3d68ecaf72294b3d47734e 100644 (file)
@@ -211,28 +211,38 @@ static int wm8960_put_deemph(struct snd_kcontrol *kcontrol,
        return wm8960_set_deemph(codec);
 }
 
-static const DECLARE_TLV_DB_SCALE(adc_tlv, -9700, 50, 0);
-static const DECLARE_TLV_DB_SCALE(dac_tlv, -12700, 50, 1);
+static const DECLARE_TLV_DB_SCALE(adc_tlv, -9750, 50, 1);
+static const DECLARE_TLV_DB_SCALE(inpga_tlv, -1725, 75, 0);
+static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
 static const DECLARE_TLV_DB_SCALE(bypass_tlv, -2100, 300, 0);
 static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
-static const DECLARE_TLV_DB_SCALE(boost_tlv, -1200, 300, 1);
+static const DECLARE_TLV_DB_SCALE(lineinboost_tlv, -1500, 300, 1);
+static const unsigned int micboost_tlv[] = {
+       TLV_DB_RANGE_HEAD(2),
+       0, 1, TLV_DB_SCALE_ITEM(0, 1300, 0),
+       2, 3, TLV_DB_SCALE_ITEM(2000, 900, 0),
+};
 
 static const struct snd_kcontrol_new wm8960_snd_controls[] = {
 SOC_DOUBLE_R_TLV("Capture Volume", WM8960_LINVOL, WM8960_RINVOL,
-                0, 63, 0, adc_tlv),
+                0, 63, 0, inpga_tlv),
 SOC_DOUBLE_R("Capture Volume ZC Switch", WM8960_LINVOL, WM8960_RINVOL,
        6, 1, 0),
 SOC_DOUBLE_R("Capture Switch", WM8960_LINVOL, WM8960_RINVOL,
        7, 1, 0),
 
 SOC_SINGLE_TLV("Right Input Boost Mixer RINPUT3 Volume",
-              WM8960_INBMIX1, 4, 7, 0, boost_tlv),
+              WM8960_INBMIX1, 4, 7, 0, lineinboost_tlv),
 SOC_SINGLE_TLV("Right Input Boost Mixer RINPUT2 Volume",
-              WM8960_INBMIX1, 1, 7, 0, boost_tlv),
+              WM8960_INBMIX1, 1, 7, 0, lineinboost_tlv),
 SOC_SINGLE_TLV("Left Input Boost Mixer LINPUT3 Volume",
-              WM8960_INBMIX2, 4, 7, 0, boost_tlv),
+              WM8960_INBMIX2, 4, 7, 0, lineinboost_tlv),
 SOC_SINGLE_TLV("Left Input Boost Mixer LINPUT2 Volume",
-              WM8960_INBMIX2, 1, 7, 0, boost_tlv),
+              WM8960_INBMIX2, 1, 7, 0, lineinboost_tlv),
+SOC_SINGLE_TLV("Right Input Boost Mixer RINPUT1 Volume",
+               WM8960_RINPATH, 4, 3, 0, micboost_tlv),
+SOC_SINGLE_TLV("Left Input Boost Mixer LINPUT1 Volume",
+               WM8960_LINPATH, 4, 3, 0, micboost_tlv),
 
 SOC_DOUBLE_R_TLV("Playback Volume", WM8960_LDAC, WM8960_RDAC,
                 0, 255, 0, dac_tlv),
index b4eb975da981a82c66435ddcaf0ee6f656c0b927..39ebd7bf4f5306382c86fb49f3417dc3c908dcad 100644 (file)
@@ -2944,7 +2944,8 @@ static int wm8962_mute(struct snd_soc_dai *dai, int mute)
                                   WM8962_DAC_MUTE, val);
 }
 
-#define WM8962_RATES SNDRV_PCM_RATE_8000_96000
+#define WM8962_RATES (SNDRV_PCM_RATE_8000_48000 |\
+               SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
 
 #define WM8962_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
                        SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
@@ -3759,7 +3760,7 @@ static int wm8962_i2c_probe(struct i2c_client *i2c,
        ret = snd_soc_register_codec(&i2c->dev,
                                     &soc_codec_dev_wm8962, &wm8962_dai, 1);
        if (ret < 0)
-               goto err_enable;
+               goto err_pm_runtime;
 
        regcache_cache_only(wm8962->regmap, true);
 
@@ -3768,6 +3769,8 @@ static int wm8962_i2c_probe(struct i2c_client *i2c,
 
        return 0;
 
+err_pm_runtime:
+       pm_runtime_disable(&i2c->dev);
 err_enable:
        regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
 err:
@@ -3777,6 +3780,7 @@ err:
 static int wm8962_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
+       pm_runtime_disable(&client->dev);
        return 0;
 }
 
@@ -3804,6 +3808,8 @@ static int wm8962_runtime_resume(struct device *dev)
 
        wm8962_reset(wm8962);
 
+       regcache_mark_dirty(wm8962->regmap);
+
        /* SYSCLK defaults to on; make sure it is off so we can safely
         * write to registers if the device is declocked.
         */
index add6bb99661daced09d250eb04af15b37c6ffb44..7d45d98a861fccb65f32987e3760c2b74e487f9a 100644 (file)
@@ -663,7 +663,7 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream,
        u8 rx_ser = 0;
        u8 slots = mcasp->tdm_slots;
        u8 max_active_serializers = (channels + slots - 1) / slots;
-       int active_serializers, numevt, n;
+       int active_serializers, numevt;
        u32 reg;
        /* Default configuration */
        if (mcasp->version < MCASP_VERSION_3)
@@ -745,9 +745,8 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream,
         * The number of words for numevt need to be in steps of active
         * serializers.
         */
-       n = numevt % active_serializers;
-       if (n)
-               numevt += (active_serializers - n);
+       numevt = (numevt / active_serializers) * active_serializers;
+
        while (period_words % numevt && numevt > 0)
                numevt -= active_serializers;
        if (numevt <= 0)
@@ -1299,6 +1298,7 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
                .ops            = &davinci_mcasp_dai_ops,
 
                .symmetric_samplebits   = 1,
+               .symmetric_rates        = 1,
        },
        {
                .name           = "davinci-mcasp.1",
@@ -1685,7 +1685,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
 
        irq = platform_get_irq_byname(pdev, "common");
        if (irq >= 0) {
-               irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s_common\n",
+               irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s_common",
                                          dev_name(&pdev->dev));
                ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
                                                davinci_mcasp_common_irq_handler,
@@ -1702,7 +1702,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
 
        irq = platform_get_irq_byname(pdev, "rx");
        if (irq >= 0) {
-               irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s_rx\n",
+               irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s_rx",
                                          dev_name(&pdev->dev));
                ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
                                                davinci_mcasp_rx_irq_handler,
@@ -1717,7 +1717,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
 
        irq = platform_get_irq_byname(pdev, "tx");
        if (irq >= 0) {
-               irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s_tx\n",
+               irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s_tx",
                                          dev_name(&pdev->dev));
                ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
                                                davinci_mcasp_tx_irq_handler,
index a3e97b46b64e3871ec9362b231d19f9334628229..ba34252b7bba4fdd8d1b7c58a313b490c14aa329 100644 (file)
@@ -131,23 +131,32 @@ static inline void i2s_clear_irqs(struct dw_i2s_dev *dev, u32 stream)
 
        if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
                for (i = 0; i < 4; i++)
-                       i2s_write_reg(dev->i2s_base, TOR(i), 0);
+                       i2s_read_reg(dev->i2s_base, TOR(i));
        } else {
                for (i = 0; i < 4; i++)
-                       i2s_write_reg(dev->i2s_base, ROR(i), 0);
+                       i2s_read_reg(dev->i2s_base, ROR(i));
        }
 }
 
 static void i2s_start(struct dw_i2s_dev *dev,
                      struct snd_pcm_substream *substream)
 {
-
+       u32 i, irq;
        i2s_write_reg(dev->i2s_base, IER, 1);
 
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               for (i = 0; i < 4; i++) {
+                       irq = i2s_read_reg(dev->i2s_base, IMR(i));
+                       i2s_write_reg(dev->i2s_base, IMR(i), irq & ~0x30);
+               }
                i2s_write_reg(dev->i2s_base, ITER, 1);
-       else
+       } else {
+               for (i = 0; i < 4; i++) {
+                       irq = i2s_read_reg(dev->i2s_base, IMR(i));
+                       i2s_write_reg(dev->i2s_base, IMR(i), irq & ~0x03);
+               }
                i2s_write_reg(dev->i2s_base, IRER, 1);
+       }
 
        i2s_write_reg(dev->i2s_base, CER, 1);
 }
index 5aeb6ed4827e821f0f0ec2cbc866ed1a99a73cc4..96f55ae75c719c87d1dcf9084ccc4e6a679a187f 100644 (file)
@@ -488,7 +488,8 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
                priv->dai_fmt |= SND_SOC_DAIFMT_CBM_CFM;
        } else {
                dev_err(&pdev->dev, "unknown Device Tree compatible\n");
-               return -EINVAL;
+               ret = -EINVAL;
+               goto asrc_fail;
        }
 
        /* Common settings for corresponding Freescale CPU DAI driver */
index 8ec6fb208ea073b70bc19b27dab7a12129a035f7..37c5cd4d0e59038ca72c8520bb350de60e42a278 100644 (file)
@@ -249,7 +249,8 @@ MODULE_DEVICE_TABLE(of, fsl_ssi_ids);
 
 static bool fsl_ssi_is_ac97(struct fsl_ssi_private *ssi_private)
 {
-       return !!(ssi_private->dai_fmt & SND_SOC_DAIFMT_AC97);
+       return (ssi_private->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) ==
+               SND_SOC_DAIFMT_AC97;
 }
 
 static bool fsl_ssi_is_i2s_master(struct fsl_ssi_private *ssi_private)
@@ -947,7 +948,7 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
                                CCSR_SSI_SCR_TCH_EN);
        }
 
-       if (fmt & SND_SOC_DAIFMT_AC97)
+       if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_AC97)
                fsl_ssi_setup_ac97(ssi_private);
 
        return 0;
index 48b2d24dd1f0a9a639c6bd7e7549035ed38f8e15..b95132e2f9dc299d82c783810982c2d5b768fb35 100644 (file)
@@ -95,7 +95,8 @@ static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
        case SND_SOC_DAIFMT_I2S:
                /* data on rising edge of bclk, frame low 1clk before data */
-               strcr |= SSI_STCR_TFSI | SSI_STCR_TEFS | SSI_STCR_TXBIT0;
+               strcr |= SSI_STCR_TXBIT0 | SSI_STCR_TSCKP | SSI_STCR_TFSI |
+                       SSI_STCR_TEFS;
                scr |= SSI_SCR_NET;
                if (ssi->flags & IMX_SSI_USE_I2S_SLAVE) {
                        scr &= ~SSI_I2S_MODE_MASK;
@@ -104,33 +105,31 @@ static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
                break;
        case SND_SOC_DAIFMT_LEFT_J:
                /* data on rising edge of bclk, frame high with data */
-               strcr |= SSI_STCR_TXBIT0;
+               strcr |= SSI_STCR_TXBIT0 | SSI_STCR_TSCKP;
                break;
        case SND_SOC_DAIFMT_DSP_B:
                /* data on rising edge of bclk, frame high with data */
-               strcr |= SSI_STCR_TFSL | SSI_STCR_TXBIT0;
+               strcr |= SSI_STCR_TXBIT0 | SSI_STCR_TSCKP | SSI_STCR_TFSL;
                break;
        case SND_SOC_DAIFMT_DSP_A:
                /* data on rising edge of bclk, frame high 1clk before data */
-               strcr |= SSI_STCR_TFSL | SSI_STCR_TXBIT0 | SSI_STCR_TEFS;
+               strcr |= SSI_STCR_TXBIT0 | SSI_STCR_TSCKP | SSI_STCR_TFSL |
+                       SSI_STCR_TEFS;
                break;
        }
 
        /* DAI clock inversion */
        switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
        case SND_SOC_DAIFMT_IB_IF:
-               strcr |= SSI_STCR_TFSI;
-               strcr &= ~SSI_STCR_TSCKP;
+               strcr ^= SSI_STCR_TSCKP | SSI_STCR_TFSI;
                break;
        case SND_SOC_DAIFMT_IB_NF:
-               strcr &= ~(SSI_STCR_TSCKP | SSI_STCR_TFSI);
+               strcr ^= SSI_STCR_TSCKP;
                break;
        case SND_SOC_DAIFMT_NB_IF:
-               strcr |= SSI_STCR_TFSI | SSI_STCR_TSCKP;
+               strcr ^= SSI_STCR_TFSI;
                break;
        case SND_SOC_DAIFMT_NB_NF:
-               strcr &= ~SSI_STCR_TFSI;
-               strcr |= SSI_STCR_TSCKP;
                break;
        }
 
index f6efa9d4acadd5e056ea0a0494ed51da859fbc3a..b27f25f70730b32717b00105b8a1f090c51ba048 100644 (file)
@@ -302,6 +302,10 @@ struct sst_hsw {
        struct sst_hsw_ipc_dx_reply dx;
        void *dx_context;
        dma_addr_t dx_context_paddr;
+       enum sst_hsw_device_id dx_dev;
+       enum sst_hsw_device_mclk dx_mclk;
+       enum sst_hsw_device_mode dx_mode;
+       u32 dx_clock_divider;
 
        /* boot */
        wait_queue_head_t boot_wait;
@@ -1400,10 +1404,10 @@ int sst_hsw_device_set_config(struct sst_hsw *hsw,
 
        trace_ipc_request("set device config", dev);
 
-       config.ssp_interface = dev;
-       config.clock_frequency = mclk;
-       config.mode = mode;
-       config.clock_divider = clock_divider;
+       hsw->dx_dev = config.ssp_interface = dev;
+       hsw->dx_mclk = config.clock_frequency = mclk;
+       hsw->dx_mode = config.mode = mode;
+       hsw->dx_clock_divider = config.clock_divider = clock_divider;
        if (mode == SST_HSW_DEVICE_TDM_CLOCK_MASTER)
                config.channels = 4;
        else
@@ -1704,10 +1708,10 @@ int sst_hsw_dsp_runtime_resume(struct sst_hsw *hsw)
                return -EIO;
        }
 
-       /* Set ADSP SSP port settings */
-       ret = sst_hsw_device_set_config(hsw, SST_HSW_DEVICE_SSP_0,
-                                       SST_HSW_DEVICE_MCLK_FREQ_24_MHZ,
-                                       SST_HSW_DEVICE_CLOCK_MASTER, 9);
+       /* Set ADSP SSP port settings - sadly the FW does not store SSP port
+          settings as part of the PM context. */
+       ret = sst_hsw_device_set_config(hsw, hsw->dx_dev, hsw->dx_mclk,
+                                       hsw->dx_mode, hsw->dx_clock_divider);
        if (ret < 0)
                dev_err(dev, "error: SSP re-initialization failed\n");
 
index d190fe017559b6a9ba40baff2f4dd8f05b88cb8e..f5baf3c38863f4eda4e31f2af8c612a6c23f3493 100644 (file)
@@ -549,6 +549,23 @@ static int mtk_afe_dais_startup(struct snd_pcm_substream *substream,
        memif->substream = substream;
 
        snd_soc_set_runtime_hwparams(substream, &mtk_afe_hardware);
+
+       /*
+        * Capture cannot use ping-pong buffer since hw_ptr at IRQ may be
+        * smaller than period_size due to AFE's internal buffer.
+        * This easily leads to overrun when avail_min is period_size.
+        * One more period can hold the possible unread buffer.
+        */
+       if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+               ret = snd_pcm_hw_constraint_minmax(runtime,
+                                                  SNDRV_PCM_HW_PARAM_PERIODS,
+                                                  3,
+                                                  mtk_afe_hardware.periods_max);
+               if (ret < 0) {
+                       dev_err(afe->dev, "hw_constraint_minmax failed\n");
+                       return ret;
+               }
+       }
        ret = snd_pcm_hw_constraint_integer(runtime,
                                            SNDRV_PCM_HW_PARAM_PERIODS);
        if (ret < 0)
index 39cea80846c313f552a1a39f4ba9e015b9958a5a..f2bf8661dd21f782b1d472a724d69902a56b7b57 100644 (file)
@@ -1,7 +1,6 @@
 config SND_PXA2XX_SOC
        tristate "SoC Audio for the Intel PXA2xx chip"
        depends on ARCH_PXA
-       select SND_ARM
        select SND_PXA2XX_LIB
        help
          Say Y or M if you want to add support for codecs attached to
@@ -25,7 +24,6 @@ config SND_PXA2XX_AC97
 config SND_PXA2XX_SOC_AC97
        tristate
        select AC97_BUS
-       select SND_ARM
        select SND_PXA2XX_LIB_AC97
        select SND_SOC_AC97_BUS
 
index 1f6054650991db5e55484db43e94c68f254b599e..9e4b04e0fbd12b452e270214ed2ee7ce09a31b90 100644 (file)
@@ -49,7 +49,7 @@ static struct snd_ac97_bus_ops pxa2xx_ac97_ops = {
        .reset  = pxa2xx_ac97_cold_reset,
 };
 
-static unsigned long pxa2xx_ac97_pcm_stereo_in_req = 12;
+static unsigned long pxa2xx_ac97_pcm_stereo_in_req = 11;
 static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_stereo_in = {
        .addr           = __PREG(PCDR),
        .addr_width     = DMA_SLAVE_BUSWIDTH_4_BYTES,
@@ -57,7 +57,7 @@ static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_stereo_in = {
        .filter_data    = &pxa2xx_ac97_pcm_stereo_in_req,
 };
 
-static unsigned long pxa2xx_ac97_pcm_stereo_out_req = 11;
+static unsigned long pxa2xx_ac97_pcm_stereo_out_req = 12;
 static struct snd_dmaengine_dai_dma_data pxa2xx_ac97_pcm_stereo_out = {
        .addr           = __PREG(PCDR),
        .addr_width     = DMA_SLAVE_BUSWIDTH_4_BYTES,
index f4bf21a5539b0e0592cc6e622f7714730c22f0ef..ff8bda471b2531fede57ea0dd225bc4081d5ba16 100644 (file)
@@ -3501,7 +3501,7 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w,
 
        default:
                WARN(1, "Unknown event %d\n", event);
-               return -EINVAL;
+               ret = -EINVAL;
        }
 
 out:
index 100d92b5b77ef92da6a7e64efd58ffde1437f769..05977ae1ff2a3250c3fe2043b8124f9370dd1542 100644 (file)
@@ -206,6 +206,34 @@ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
 }
 EXPORT_SYMBOL_GPL(snd_soc_info_volsw);
 
+/**
+ * snd_soc_info_volsw_sx - Mixer info callback for SX TLV controls
+ * @kcontrol: mixer control
+ * @uinfo: control element information
+ *
+ * Callback to provide information about a single mixer control, or a double
+ * mixer control that spans 2 registers of the SX TLV type. SX TLV controls
+ * have a range that represents both positive and negative values either side
+ * of zero but without a sign bit.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_info_volsw_sx(struct snd_kcontrol *kcontrol,
+                         struct snd_ctl_elem_info *uinfo)
+{
+       struct soc_mixer_control *mc =
+               (struct soc_mixer_control *)kcontrol->private_value;
+
+       snd_soc_info_volsw(kcontrol, uinfo);
+       /* Max represents the number of levels in an SX control not the
+        * maximum value, so add the minimum value back on
+        */
+       uinfo->value.integer.max += mc->min;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_info_volsw_sx);
+
 /**
  * snd_soc_get_volsw - single mixer get callback
  * @kcontrol: mixer control
index 362c69ac1d6c7143d1f04c622d4fad0c82811704..53dd085d3ee20fd5db326366db72054990886118 100644 (file)
@@ -101,6 +101,15 @@ static struct snd_soc_codec_driver dummy_codec;
                        SNDRV_PCM_FMTBIT_S32_LE | \
                        SNDRV_PCM_FMTBIT_U32_LE | \
                        SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE)
+/*
+ * The dummy CODEC is only meant to be used in situations where there is no
+ * actual hardware.
+ *
+ * If there is actual hardware even if it does not have a control bus
+ * the hardware will still have constraints like supported samplerates, etc.
+ * which should be modelled. And the data flow graph also should be modelled
+ * using DAPM.
+ */
 static struct snd_soc_dai_driver dummy_dai = {
        .name = "snd-soc-dummy-dai",
        .playback = {
index 0a53053495f3d39cf6363b2255bfa4ad629c6be0..4fb91412ebec80261adda960d0874225ed2d0192 100644 (file)
@@ -1,6 +1,6 @@
 config SND_SPEAR_SOC
        tristate
-       select SND_DMAENGINE_PCM
+       select SND_SOC_GENERIC_DMAENGINE_PCM
 
 config SND_SPEAR_SPDIF_OUT
        tristate
index f6eefe1b8f8f1c6ad28b8c5ee00ee473d0d833ef..843f037a317da31aecc0b1761ddde2dfa24a1334 100644 (file)
@@ -989,8 +989,8 @@ static int uni_player_parse_dt(struct platform_device *pdev,
        if (!info)
                return -ENOMEM;
 
-       of_property_read_u32(pnode, "version", &player->ver);
-       if (player->ver == SND_ST_UNIPERIF_VERSION_UNKNOWN) {
+       if (of_property_read_u32(pnode, "version", &player->ver) ||
+           player->ver == SND_ST_UNIPERIF_VERSION_UNKNOWN) {
                dev_err(dev, "Unknown uniperipheral version ");
                return -EINVAL;
        }
@@ -998,10 +998,16 @@ static int uni_player_parse_dt(struct platform_device *pdev,
        if (player->ver >= SND_ST_UNIPERIF_VERSION_UNI_PLR_TOP_1_0)
                info->underflow_enabled = 1;
 
-       of_property_read_u32(pnode, "uniperiph-id", &info->id);
+       if (of_property_read_u32(pnode, "uniperiph-id", &info->id)) {
+               dev_err(dev, "uniperipheral id not defined");
+               return -EINVAL;
+       }
 
        /* Read the device mode property */
-       of_property_read_string(pnode, "mode", &mode);
+       if (of_property_read_string(pnode, "mode", &mode)) {
+               dev_err(dev, "uniperipheral mode not defined");
+               return -EINVAL;
+       }
 
        if (strcasecmp(mode, "hdmi") == 0)
                info->player_type = SND_ST_UNIPERIF_PLAYER_TYPE_HDMI;
index c502626f339b8ab27251b8e4571bc6a9e0d925fa..f791239a30872927b4c117f43ec457da6532b037 100644 (file)
@@ -316,7 +316,11 @@ static int uni_reader_parse_dt(struct platform_device *pdev,
        if (!info)
                return -ENOMEM;
 
-       of_property_read_u32(node, "version", &reader->ver);
+       if (of_property_read_u32(node, "version", &reader->ver) ||
+           reader->ver == SND_ST_UNIPERIF_VERSION_UNKNOWN) {
+               dev_err(&pdev->dev, "Unknown uniperipheral version ");
+               return -EINVAL;
+       }
 
        /* Save the info structure */
        reader->info = info;
index 82e350e9501ccc0d5ebc82962f60c034466448eb..ac75816ada7c31b133586693e5c73a41dc79348f 100644 (file)
@@ -69,7 +69,8 @@ snd_emux_init_seq_oss(struct snd_emux *emu)
        struct snd_seq_oss_reg *arg;
        struct snd_seq_device *dev;
 
-       if (snd_seq_device_new(emu->card, 0, SNDRV_SEQ_DEV_ID_OSS,
+       /* using device#1 here for avoiding conflicts with OPL3 */
+       if (snd_seq_device_new(emu->card, 1, SNDRV_SEQ_DEV_ID_OSS,
                               sizeof(struct snd_seq_oss_reg), &dev) < 0)
                return;
 
index 2975632d51e2341e7e1a60286e0fa822cbec0279..c8fe6d17711915e50978b3b2cbba6804af5cf9fe 100644 (file)
@@ -41,6 +41,7 @@ FEATURE_TESTS ?=                      \
        libelf-getphdrnum               \
        libelf-mmap                     \
        libnuma                         \
+       numa_num_possible_cpus          \
        libperl                         \
        libpython                       \
        libpython-version               \
@@ -51,7 +52,8 @@ FEATURE_TESTS ?=                      \
        timerfd                         \
        libdw-dwarf-unwind              \
        zlib                            \
-       lzma
+       lzma                            \
+       get_cpuid
 
 FEATURE_DISPLAY ?=                     \
        dwarf                           \
@@ -61,13 +63,15 @@ FEATURE_DISPLAY ?=                  \
        libbfd                          \
        libelf                          \
        libnuma                         \
+       numa_num_possible_cpus          \
        libperl                         \
        libpython                       \
        libslang                        \
        libunwind                       \
        libdw-dwarf-unwind              \
        zlib                            \
-       lzma
+       lzma                            \
+       get_cpuid
 
 # Set FEATURE_CHECK_(C|LD)FLAGS-all for all FEATURE_TESTS features.
 # If in the future we need per-feature checks/flags for features not
index 74ca42093d70d72fac5a4b1776237be9873f480a..e43a2971bf5669a8cae7722e8d5058fb9ada56ea 100644 (file)
@@ -19,6 +19,7 @@ FILES=                                        \
        test-libelf-getphdrnum.bin      \
        test-libelf-mmap.bin            \
        test-libnuma.bin                \
+       test-numa_num_possible_cpus.bin \
        test-libperl.bin                \
        test-libpython.bin              \
        test-libpython-version.bin      \
@@ -34,7 +35,8 @@ FILES=                                        \
        test-compile-x32.bin            \
        test-zlib.bin                   \
        test-lzma.bin                   \
-       test-bpf.bin
+       test-bpf.bin                    \
+       test-get_cpuid.bin
 
 CC := $(CROSS_COMPILE)gcc -MD
 PKG_CONFIG := $(CROSS_COMPILE)pkg-config
@@ -87,6 +89,9 @@ test-libelf-getphdrnum.bin:
 test-libnuma.bin:
        $(BUILD) -lnuma
 
+test-numa_num_possible_cpus.bin:
+       $(BUILD) -lnuma
+
 test-libunwind.bin:
        $(BUILD) -lelf
 
@@ -162,6 +167,9 @@ test-zlib.bin:
 test-lzma.bin:
        $(BUILD) -llzma
 
+test-get_cpuid.bin:
+       $(BUILD)
+
 test-bpf.bin:
        $(BUILD)
 
index 84689a67814a9a622bd3f12b69fe5a8f5733a499..33cf6f20bd4ec6812ac6b53cfe1b301053d8c940 100644 (file)
 # include "test-libnuma.c"
 #undef main
 
+#define main main_test_numa_num_possible_cpus
+# include "test-numa_num_possible_cpus.c"
+#undef main
+
 #define main main_test_timerfd
 # include "test-timerfd.c"
 #undef main
 # include "test-lzma.c"
 #undef main
 
+#define main main_test_get_cpuid
+# include "test-get_cpuid.c"
+#undef main
+
 int main(int argc, char *argv[])
 {
        main_test_libpython();
@@ -136,6 +144,7 @@ int main(int argc, char *argv[])
        main_test_libbfd();
        main_test_backtrace();
        main_test_libnuma();
+       main_test_numa_num_possible_cpus();
        main_test_timerfd();
        main_test_stackprotector_all();
        main_test_libdw_dwarf_unwind();
@@ -143,6 +152,7 @@ int main(int argc, char *argv[])
        main_test_zlib();
        main_test_pthread_attr_setaffinity_np();
        main_test_lzma();
+       main_test_get_cpuid();
 
        return 0;
 }
diff --git a/tools/build/feature/test-get_cpuid.c b/tools/build/feature/test-get_cpuid.c
new file mode 100644 (file)
index 0000000..d7a2c40
--- /dev/null
@@ -0,0 +1,7 @@
+#include <cpuid.h>
+
+int main(void)
+{
+       unsigned int eax = 0, ebx = 0, ecx = 0, edx = 0;
+       return __get_cpuid(0x15, &eax, &ebx, &ecx, &edx);
+}
diff --git a/tools/build/feature/test-numa_num_possible_cpus.c b/tools/build/feature/test-numa_num_possible_cpus.c
new file mode 100644 (file)
index 0000000..2606e94
--- /dev/null
@@ -0,0 +1,6 @@
+#include <numa.h>
+
+int main(void)
+{
+       return numa_num_possible_cpus();
+}
index 4d885934b9190e9dc995d6f5fb80b3a90ef218a3..cf42b090477b9795ac1f48dff6c1c7b93bed7f65 100644 (file)
@@ -3795,7 +3795,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
        struct format_field *field;
        struct printk_map *printk;
        long long val, fval;
-       unsigned long addr;
+       unsigned long long addr;
        char *str;
        unsigned char *hex;
        int print;
@@ -3828,13 +3828,30 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
                 */
                if (!(field->flags & FIELD_IS_ARRAY) &&
                    field->size == pevent->long_size) {
-                       addr = *(unsigned long *)(data + field->offset);
+
+                       /* Handle heterogeneous recording and processing
+                        * architectures
+                        *
+                        * CASE I:
+                        * Traces recorded on 32-bit devices (32-bit
+                        * addressing) and processed on 64-bit devices:
+                        * In this case, only 32 bits should be read.
+                        *
+                        * CASE II:
+                        * Traces recorded on 64 bit devices and processed
+                        * on 32-bit devices:
+                        * In this case, 64 bits must be read.
+                        */
+                       addr = (pevent->long_size == 8) ?
+                               *(unsigned long long *)(data + field->offset) :
+                               (unsigned long long)*(unsigned int *)(data + field->offset);
+
                        /* Check if it matches a print format */
                        printk = find_printk(pevent, addr);
                        if (printk)
                                trace_seq_puts(s, printk->printk);
                        else
-                               trace_seq_printf(s, "%lx", addr);
+                               trace_seq_printf(s, "%llx", addr);
                        break;
                }
                str = malloc(len + 1);
index 4a0501d7a3b412337960b07a695a772d2b7c1344..c94c9de3173ee187f87be72c0ffa128885115c89 100644 (file)
@@ -364,21 +364,6 @@ cyc_thresh Specifies how frequently CYC packets are produced - see cyc
 
                CYC packets are not requested by default.
 
-no_force_psb   This is a driver option and is not in the IA32_RTIT_CTL MSR.
-
-               It stops the driver resetting the byte count to zero whenever
-               enabling the trace (for example on context switches) which in
-               turn results in no PSB being forced.  However some processors
-               will produce a PSB anyway.
-
-               In any case, there is still a PSB when the trace is enabled for
-               the first time.
-
-               no_force_psb can be used to slightly decrease the trace size but
-               may make it harder for the decoder to recover from errors.
-
-               no_force_psb is not selected by default.
-
 
 new snapshot option
 -------------------
index eb51325e8ad99adefa7671a7b511626b7c136d1d..284a76e046284983cd769da89cb45604b114a41a 100644 (file)
@@ -768,8 +768,8 @@ static int process_exit_event(struct perf_tool *tool,
        if (!evsel->attr.sample_id_all) {
                sample->cpu = 0;
                sample->time = 0;
-               sample->tid = event->comm.tid;
-               sample->pid = event->comm.pid;
+               sample->tid = event->fork.tid;
+               sample->pid = event->fork.pid;
        }
        print_sample_start(sample, thread, evsel);
        perf_event__fprintf(event, stdout);
index 827557fc751123bf030363d355b5b801911d6cb1..38a08539f4bfc0405000dfd1ce543053409241a8 100644 (file)
@@ -573,9 +573,14 @@ ifndef NO_LIBNUMA
     msg := $(warning No numa.h found, disables 'perf bench numa mem' benchmark, please install numactl-devel/libnuma-devel/libnuma-dev);
     NO_LIBNUMA := 1
   else
-    CFLAGS += -DHAVE_LIBNUMA_SUPPORT
-    EXTLIBS += -lnuma
-    $(call detected,CONFIG_NUMA)
+    ifeq ($(feature-numa_num_possible_cpus), 0)
+      msg := $(warning Old numa library found, disables 'perf bench numa mem' benchmark, please install numactl-devel/libnuma-devel/libnuma-dev >= 2.0.8);
+      NO_LIBNUMA := 1
+    else
+      CFLAGS += -DHAVE_LIBNUMA_SUPPORT
+      EXTLIBS += -lnuma
+      $(call detected,CONFIG_NUMA)
+    endif
   endif
 endif
 
@@ -621,8 +626,13 @@ ifdef LIBBABELTRACE
 endif
 
 ifndef NO_AUXTRACE
-  $(call detected,CONFIG_AUXTRACE)
-  CFLAGS += -DHAVE_AUXTRACE_SUPPORT
+  ifeq ($(feature-get_cpuid), 0)
+    msg := $(warning Your gcc lacks the __get_cpuid() builtin, disables support for auxtrace/Intel PT, please install a newer gcc);
+    NO_AUXTRACE := 1
+  else
+    $(call detected,CONFIG_AUXTRACE)
+    CFLAGS += -DHAVE_AUXTRACE_SUPPORT
+  endif
 endif
 
 # Among the variables below, these:
index 1aa21c90731b3eca400d91c2fec5d2b55a127f03..5b83f56a3b6f25928337d3954d2924322d3154ef 100644 (file)
@@ -34,6 +34,8 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
                .disabled = 1,
                .freq = 1,
        };
+       struct cpu_map *cpus;
+       struct thread_map *threads;
 
        attr.sample_freq = 500;
 
@@ -50,14 +52,19 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
        }
        perf_evlist__add(evlist, evsel);
 
-       evlist->cpus = cpu_map__dummy_new();
-       evlist->threads = thread_map__new_by_tid(getpid());
-       if (!evlist->cpus || !evlist->threads) {
+       cpus = cpu_map__dummy_new();
+       threads = thread_map__new_by_tid(getpid());
+       if (!cpus || !threads) {
                err = -ENOMEM;
                pr_debug("Not enough memory to create thread/cpu maps\n");
-               goto out_delete_evlist;
+               goto out_free_maps;
        }
 
+       perf_evlist__set_maps(evlist, cpus, threads);
+
+       cpus    = NULL;
+       threads = NULL;
+
        if (perf_evlist__open(evlist)) {
                const char *knob = "/proc/sys/kernel/perf_event_max_sample_rate";
 
@@ -107,6 +114,9 @@ next_event:
                err = -1;
        }
 
+out_free_maps:
+       cpu_map__put(cpus);
+       thread_map__put(threads);
 out_delete_evlist:
        perf_evlist__delete(evlist);
        return err;
index 3a8fedef83bc086e5328dea03dcf6107d3ff1e39..add16385f13e5bbb750cec83da3f1fe0d28889af 100644 (file)
@@ -43,6 +43,8 @@ int test__task_exit(void)
        };
        const char *argv[] = { "true", NULL };
        char sbuf[STRERR_BUFSIZE];
+       struct cpu_map *cpus;
+       struct thread_map *threads;
 
        signal(SIGCHLD, sig_handler);
 
@@ -58,14 +60,19 @@ int test__task_exit(void)
         * perf_evlist__prepare_workload we'll fill in the only thread
         * we're monitoring, the one forked there.
         */
-       evlist->cpus = cpu_map__dummy_new();
-       evlist->threads = thread_map__new_by_tid(-1);
-       if (!evlist->cpus || !evlist->threads) {
+       cpus = cpu_map__dummy_new();
+       threads = thread_map__new_by_tid(-1);
+       if (!cpus || !threads) {
                err = -ENOMEM;
                pr_debug("Not enough memory to create thread/cpu maps\n");
-               goto out_delete_evlist;
+               goto out_free_maps;
        }
 
+       perf_evlist__set_maps(evlist, cpus, threads);
+
+       cpus    = NULL;
+       threads = NULL;
+
        err = perf_evlist__prepare_workload(evlist, &target, argv, false,
                                            workload_exec_failed_signal);
        if (err < 0) {
@@ -114,6 +121,9 @@ retry:
                err = -1;
        }
 
+out_free_maps:
+       cpu_map__put(cpus);
+       thread_map__put(threads);
 out_delete_evlist:
        perf_evlist__delete(evlist);
        return err;
index cf86f2d3a5e725cb625505283af7ce80ccc13ff6..c04c60d4863ce71a08014c396aa7342c8af2fa16 100644 (file)
@@ -1968,7 +1968,8 @@ skip_annotation:
                                          &options[nr_options], dso);
                nr_options += add_map_opt(browser, &actions[nr_options],
                                          &options[nr_options],
-                                         browser->selection->map);
+                                         browser->selection ?
+                                               browser->selection->map : NULL);
 
                /* perf script support */
                if (browser->he_selection) {
@@ -1976,6 +1977,15 @@ skip_annotation:
                                                     &actions[nr_options],
                                                     &options[nr_options],
                                                     thread, NULL);
+                       /*
+                        * Note that browser->selection != NULL
+                        * when browser->he_selection is not NULL,
+                        * so we don't need to check browser->selection
+                        * before fetching browser->selection->sym like what
+                        * we do before fetching browser->selection->map.
+                        *
+                        * See hist_browser__show_entry.
+                        */
                        nr_options += add_script_opt(browser,
                                                     &actions[nr_options],
                                                     &options[nr_options],
index 349bc96ca1fedc4946ab9596edd5dd1b3813ac0b..e5f18a288b7489a93e880657401dd1f99014deda 100644 (file)
@@ -17,6 +17,7 @@ libperf-y += levenshtein.o
 libperf-y += llvm-utils.o
 libperf-y += parse-options.o
 libperf-y += parse-events.o
+libperf-y += perf_regs.o
 libperf-y += path.o
 libperf-y += rbtree.o
 libperf-y += bitmap.o
@@ -103,7 +104,6 @@ libperf-$(CONFIG_LIBBABELTRACE) += data-convert-bt.o
 
 libperf-y += scripting-engines/
 
-libperf-$(CONFIG_PERF_REGS) += perf_regs.o
 libperf-$(CONFIG_ZLIB) += zlib.o
 libperf-$(CONFIG_LZMA) += lzma.o
 
index d51a5200c8af77b76e98c85d55f8acee8db304f0..c8fc8a258f4265c42c636d045b195a612cfae3a4 100644 (file)
@@ -124,6 +124,33 @@ void perf_evlist__delete(struct perf_evlist *evlist)
        free(evlist);
 }
 
+static void __perf_evlist__propagate_maps(struct perf_evlist *evlist,
+                                         struct perf_evsel *evsel)
+{
+       /*
+        * We already have cpus for evsel (via PMU sysfs) so
+        * keep it, if there's no target cpu list defined.
+        */
+       if (!evsel->own_cpus || evlist->has_user_cpus) {
+               cpu_map__put(evsel->cpus);
+               evsel->cpus = cpu_map__get(evlist->cpus);
+       } else if (evsel->cpus != evsel->own_cpus) {
+               cpu_map__put(evsel->cpus);
+               evsel->cpus = cpu_map__get(evsel->own_cpus);
+       }
+
+       thread_map__put(evsel->threads);
+       evsel->threads = thread_map__get(evlist->threads);
+}
+
+static void perf_evlist__propagate_maps(struct perf_evlist *evlist)
+{
+       struct perf_evsel *evsel;
+
+       evlist__for_each(evlist, evsel)
+               __perf_evlist__propagate_maps(evlist, evsel);
+}
+
 void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry)
 {
        entry->evlist = evlist;
@@ -133,18 +160,19 @@ void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry)
 
        if (!evlist->nr_entries++)
                perf_evlist__set_id_pos(evlist);
+
+       __perf_evlist__propagate_maps(evlist, entry);
 }
 
 void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
-                                  struct list_head *list,
-                                  int nr_entries)
+                                  struct list_head *list)
 {
-       bool set_id_pos = !evlist->nr_entries;
+       struct perf_evsel *evsel, *temp;
 
-       list_splice_tail(list, &evlist->entries);
-       evlist->nr_entries += nr_entries;
-       if (set_id_pos)
-               perf_evlist__set_id_pos(evlist);
+       __evlist__for_each_safe(list, temp, evsel) {
+               list_del_init(&evsel->node);
+               perf_evlist__add(evlist, evsel);
+       }
 }
 
 void __perf_evlist__set_leader(struct list_head *list)
@@ -210,7 +238,7 @@ static int perf_evlist__add_attrs(struct perf_evlist *evlist,
                list_add_tail(&evsel->node, &head);
        }
 
-       perf_evlist__splice_list_tail(evlist, &head, nr_attrs);
+       perf_evlist__splice_list_tail(evlist, &head);
 
        return 0;
 
@@ -1103,71 +1131,56 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
        return perf_evlist__mmap_ex(evlist, pages, overwrite, 0, false);
 }
 
-static int perf_evlist__propagate_maps(struct perf_evlist *evlist,
-                                      bool has_user_cpus)
-{
-       struct perf_evsel *evsel;
-
-       evlist__for_each(evlist, evsel) {
-               /*
-                * We already have cpus for evsel (via PMU sysfs) so
-                * keep it, if there's no target cpu list defined.
-                */
-               if (evsel->cpus && has_user_cpus)
-                       cpu_map__put(evsel->cpus);
-
-               if (!evsel->cpus || has_user_cpus)
-                       evsel->cpus = cpu_map__get(evlist->cpus);
-
-               evsel->threads = thread_map__get(evlist->threads);
-
-               if ((evlist->cpus && !evsel->cpus) ||
-                   (evlist->threads && !evsel->threads))
-                       return -ENOMEM;
-       }
-
-       return 0;
-}
-
 int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
 {
-       evlist->threads = thread_map__new_str(target->pid, target->tid,
-                                             target->uid);
+       struct cpu_map *cpus;
+       struct thread_map *threads;
+
+       threads = thread_map__new_str(target->pid, target->tid, target->uid);
 
-       if (evlist->threads == NULL)
+       if (!threads)
                return -1;
 
        if (target__uses_dummy_map(target))
-               evlist->cpus = cpu_map__dummy_new();
+               cpus = cpu_map__dummy_new();
        else
-               evlist->cpus = cpu_map__new(target->cpu_list);
+               cpus = cpu_map__new(target->cpu_list);
 
-       if (evlist->cpus == NULL)
+       if (!cpus)
                goto out_delete_threads;
 
-       return perf_evlist__propagate_maps(evlist, !!target->cpu_list);
+       evlist->has_user_cpus = !!target->cpu_list;
+
+       perf_evlist__set_maps(evlist, cpus, threads);
+
+       return 0;
 
 out_delete_threads:
-       thread_map__put(evlist->threads);
-       evlist->threads = NULL;
+       thread_map__put(threads);
        return -1;
 }
 
-int perf_evlist__set_maps(struct perf_evlist *evlist,
-                         struct cpu_map *cpus,
-                         struct thread_map *threads)
+void perf_evlist__set_maps(struct perf_evlist *evlist, struct cpu_map *cpus,
+                          struct thread_map *threads)
 {
-       if (evlist->cpus)
+       /*
+        * Allow for the possibility that one or another of the maps isn't being
+        * changed i.e. don't put it.  Note we are assuming the maps that are
+        * being applied are brand new and evlist is taking ownership of the
+        * original reference count of 1.  If that is not the case it is up to
+        * the caller to increase the reference count.
+        */
+       if (cpus != evlist->cpus) {
                cpu_map__put(evlist->cpus);
+               evlist->cpus = cpus;
+       }
 
-       evlist->cpus = cpus;
-
-       if (evlist->threads)
+       if (threads != evlist->threads) {
                thread_map__put(evlist->threads);
+               evlist->threads = threads;
+       }
 
-       evlist->threads = threads;
-
-       return perf_evlist__propagate_maps(evlist, false);
+       perf_evlist__propagate_maps(evlist);
 }
 
 int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel)
@@ -1387,6 +1400,8 @@ void perf_evlist__close(struct perf_evlist *evlist)
 
 static int perf_evlist__create_syswide_maps(struct perf_evlist *evlist)
 {
+       struct cpu_map    *cpus;
+       struct thread_map *threads;
        int err = -ENOMEM;
 
        /*
@@ -1398,20 +1413,19 @@ static int perf_evlist__create_syswide_maps(struct perf_evlist *evlist)
         * error, and we may not want to do that fallback to a
         * default cpu identity map :-\
         */
-       evlist->cpus = cpu_map__new(NULL);
-       if (evlist->cpus == NULL)
+       cpus = cpu_map__new(NULL);
+       if (!cpus)
                goto out;
 
-       evlist->threads = thread_map__new_dummy();
-       if (evlist->threads == NULL)
-               goto out_free_cpus;
+       threads = thread_map__new_dummy();
+       if (!threads)
+               goto out_put;
 
-       err = 0;
+       perf_evlist__set_maps(evlist, cpus, threads);
 out:
        return err;
-out_free_cpus:
-       cpu_map__put(evlist->cpus);
-       evlist->cpus = NULL;
+out_put:
+       cpu_map__put(cpus);
        goto out;
 }
 
index b39a6198f4ac00ae4c30cdfe659667cc84db7780..115d8b53c6010a5a1d466b04535245d9fd8f8579 100644 (file)
@@ -42,6 +42,7 @@ struct perf_evlist {
        int              nr_mmaps;
        bool             overwrite;
        bool             enabled;
+       bool             has_user_cpus;
        size_t           mmap_len;
        int              id_pos;
        int              is_pos;
@@ -155,9 +156,8 @@ int perf_evlist__enable_event_idx(struct perf_evlist *evlist,
 void perf_evlist__set_selected(struct perf_evlist *evlist,
                               struct perf_evsel *evsel);
 
-int perf_evlist__set_maps(struct perf_evlist *evlist,
-                         struct cpu_map *cpus,
-                         struct thread_map *threads);
+void perf_evlist__set_maps(struct perf_evlist *evlist, struct cpu_map *cpus,
+                          struct thread_map *threads);
 int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target);
 int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel);
 
@@ -179,8 +179,7 @@ bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist);
 bool perf_evlist__valid_read_format(struct perf_evlist *evlist);
 
 void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
-                                  struct list_head *list,
-                                  int nr_entries);
+                                  struct list_head *list);
 
 static inline struct perf_evsel *perf_evlist__first(struct perf_evlist *evlist)
 {
index c53f79123b37f4ab506f3a914263d59c3122cfb6..5410483d52198c5909ec5a502c61567c5119c8ef 100644 (file)
@@ -1033,6 +1033,7 @@ void perf_evsel__exit(struct perf_evsel *evsel)
        perf_evsel__free_config_terms(evsel);
        close_cgroup(evsel->cgrp);
        cpu_map__put(evsel->cpus);
+       cpu_map__put(evsel->own_cpus);
        thread_map__put(evsel->threads);
        zfree(&evsel->group_name);
        zfree(&evsel->name);
index 298e6bbca200bd4740bddc4e6bb1fce7414d5bf4..ef8925f7211a4a311c927e6919d83817745eb1cf 100644 (file)
@@ -98,6 +98,7 @@ struct perf_evsel {
        struct cgroup_sel       *cgrp;
        void                    *handler;
        struct cpu_map          *cpus;
+       struct cpu_map          *own_cpus;
        struct thread_map       *threads;
        unsigned int            sample_size;
        int                     id_pos;
index 41814547da159a14ac00eca8c774f3a46ae20558..fce6634aebe25d19d126120ec1e6e4dd323be46a 100644 (file)
@@ -1438,7 +1438,7 @@ static int process_nrcpus(struct perf_file_section *section __maybe_unused,
        if (ph->needs_swap)
                nr = bswap_32(nr);
 
-       ph->env.nr_cpus_online = nr;
+       ph->env.nr_cpus_avail = nr;
 
        ret = readn(fd, &nr, sizeof(nr));
        if (ret != sizeof(nr))
@@ -1447,7 +1447,7 @@ static int process_nrcpus(struct perf_file_section *section __maybe_unused,
        if (ph->needs_swap)
                nr = bswap_32(nr);
 
-       ph->env.nr_cpus_avail = nr;
+       ph->env.nr_cpus_online = nr;
        return 0;
 }
 
index ea768625ab5b39eaf8ce59059e10349eb7ecd34a..eb0e7f8bf5158c98c95216d4fb9d3eb96568c50b 100644 (file)
@@ -623,7 +623,7 @@ static int intel_bts_process_event(struct perf_session *session,
        if (err)
                return err;
        if (event->header.type == PERF_RECORD_EXIT) {
-               err = intel_bts_process_tid_exit(bts, event->comm.tid);
+               err = intel_bts_process_tid_exit(bts, event->fork.tid);
                if (err)
                        return err;
        }
index bb41c20e6005e1a2d986656fc94eead62de7a4ee..535d86f8e4d17b802a4c0473a7bf7ff937a10b15 100644 (file)
@@ -1494,7 +1494,7 @@ static int intel_pt_process_event(struct perf_session *session,
        if (pt->timeless_decoding) {
                if (event->header.type == PERF_RECORD_EXIT) {
                        err = intel_pt_process_timeless_queues(pt,
-                                                              event->comm.tid,
+                                                              event->fork.tid,
                                                               sample->time);
                }
        } else if (timestamp) {
index d826e6f515db12a3f75517bf93437eb9d0043829..21ed6ee63da9747d1215ac638f936357c8df2e8c 100644 (file)
@@ -287,8 +287,8 @@ __add_event(struct list_head *list, int *idx,
        if (!evsel)
                return NULL;
 
-       if (cpus)
-               evsel->cpus = cpu_map__get(cpus);
+       evsel->cpus     = cpu_map__get(cpus);
+       evsel->own_cpus = cpu_map__get(cpus);
 
        if (name)
                evsel->name = strdup(name);
@@ -1140,10 +1140,9 @@ int parse_events(struct perf_evlist *evlist, const char *str,
        ret = parse_events__scanner(str, &data, PE_START_EVENTS);
        perf_pmu__parse_cleanup();
        if (!ret) {
-               int entries = data.idx - evlist->nr_entries;
                struct perf_evsel *last;
 
-               perf_evlist__splice_list_tail(evlist, &data.list, entries);
+               perf_evlist__splice_list_tail(evlist, &data.list);
                evlist->nr_groups += data.nr_groups;
                last = perf_evlist__last(evlist);
                last->cmdline_group_boundary = true;
index 591905a02b926b6029447a372f2e5f7b7d34864a..9cd70819c7950e2de1aaae29a17b0f951b593bda 100644 (file)
@@ -255,7 +255,7 @@ PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc
        list_add_tail(&term->list, head);
 
        ALLOC_LIST(list);
-       ABORT_ON(parse_events_add_pmu(list, &data->idx, "cpu", head));
+       ABORT_ON(parse_events_add_pmu(data, list, "cpu", head));
        parse_events__free_terms(head);
        $$ = list;
 }
index 885e8ac83997905db7baa0d334015b5cf46e37d9..6b8eb13e14e4d5897fca71c41634a07cc9ec5d16 100644 (file)
@@ -6,6 +6,7 @@ const struct sample_reg __weak sample_reg_masks[] = {
        SMPL_REG_END
 };
 
+#ifdef HAVE_PERF_REGS_SUPPORT
 int perf_reg_value(u64 *valp, struct regs_dump *regs, int id)
 {
        int i, idx = 0;
@@ -29,3 +30,4 @@ out:
        *valp = regs->cache_regs[id];
        return 0;
 }
+#endif
index 2984dcc54d67cd7acb9d02975c4fb1b7b55fdb7c..679d6e493962267f7b219b88c05d06c61ef1d2ea 100644 (file)
@@ -2,6 +2,7 @@
 #define __PERF_REGS_H
 
 #include <linux/types.h>
+#include <linux/compiler.h>
 
 struct regs_dump;
 
index eb5f18b754028e863e3b72970842cc33d2fb997d..c6f9af78f6f5f9651c6339bd3140221b9b951b6d 100644 (file)
@@ -270,12 +270,13 @@ static int kernel_get_module_dso(const char *module, struct dso **pdso)
        int ret = 0;
 
        if (module) {
-               list_for_each_entry(dso, &host_machine->dsos.head, node) {
-                       if (!dso->kernel)
-                               continue;
-                       if (strncmp(dso->short_name + 1, module,
-                                   dso->short_name_len - 2) == 0)
-                               goto found;
+               char module_name[128];
+
+               snprintf(module_name, sizeof(module_name), "[%s]", module);
+               map = map_groups__find_by_name(&host_machine->kmaps, MAP__FUNCTION, module_name);
+               if (map) {
+                       dso = map->dso;
+                       goto found;
                }
                pr_debug("Failed to find module %s.\n", module);
                return -ENOENT;
index 8a4537ee9bc374166c31d05f6e48b6ca6943a4b3..fc3f7c922f99abf57246e0446b154299a1e6085d 100644 (file)
@@ -1580,7 +1580,10 @@ static int __perf_session__process_events(struct perf_session *session,
        file_offset = page_offset;
        head = data_offset - page_offset;
 
-       if (data_size && (data_offset + data_size < file_size))
+       if (data_size == 0)
+               goto out;
+
+       if (data_offset + data_size < file_size)
                file_size = data_offset + data_size;
 
        ui_progress__init(&prog, file_size, "Processing events...");
index 415c359de4654be8f68a30effa530dd06696b52b..2d065d065b676232eecbe8ea94348f4cf3a77f33 100644 (file)
@@ -196,7 +196,8 @@ static void zero_per_pkg(struct perf_evsel *counter)
                memset(counter->per_pkg_mask, 0, MAX_NR_CPUS);
 }
 
-static int check_per_pkg(struct perf_evsel *counter, int cpu, bool *skip)
+static int check_per_pkg(struct perf_evsel *counter,
+                        struct perf_counts_values *vals, int cpu, bool *skip)
 {
        unsigned long *mask = counter->per_pkg_mask;
        struct cpu_map *cpus = perf_evsel__cpus(counter);
@@ -218,6 +219,17 @@ static int check_per_pkg(struct perf_evsel *counter, int cpu, bool *skip)
                counter->per_pkg_mask = mask;
        }
 
+       /*
+        * we do not consider an event that has not run as a good
+        * instance to mark a package as used (skip=1). Otherwise
+        * we may run into a situation where the first CPU in a package
+        * is not running anything, yet the second is, and this function
+        * would mark the package as used after the first CPU and would
+        * not read the values from the second CPU.
+        */
+       if (!(vals->run && vals->ena))
+               return 0;
+
        s = cpu_map__get_socket(cpus, cpu);
        if (s < 0)
                return -1;
@@ -235,7 +247,7 @@ process_counter_values(struct perf_stat_config *config, struct perf_evsel *evsel
        static struct perf_counts_values zero;
        bool skip = false;
 
-       if (check_per_pkg(evsel, cpu, &skip)) {
+       if (check_per_pkg(evsel, count, cpu, &skip)) {
                pr_err("failed to read per-pkg counter\n");
                return -1;
        }
index 53bb5f59ec589c22f7b1cd211cb132a3ca98d702..475d88d0a1c9a772323b3218cfcf5f5900c0e809 100644 (file)
@@ -38,7 +38,7 @@ static inline char *bfd_demangle(void __maybe_unused *v,
 #endif
 
 #ifndef HAVE_ELF_GETPHDRNUM_SUPPORT
-int elf_getphdrnum(Elf *elf, size_t *dst)
+static int elf_getphdrnum(Elf *elf, size_t *dst)
 {
        GElf_Ehdr gehdr;
        GElf_Ehdr *ehdr;
@@ -1271,8 +1271,6 @@ out_close:
 static int kcore__init(struct kcore *kcore, char *filename, int elfclass,
                       bool temp)
 {
-       GElf_Ehdr *ehdr;
-
        kcore->elfclass = elfclass;
 
        if (temp)
@@ -1289,9 +1287,7 @@ static int kcore__init(struct kcore *kcore, char *filename, int elfclass,
        if (!gelf_newehdr(kcore->elf, elfclass))
                goto out_end;
 
-       ehdr = gelf_getehdr(kcore->elf, &kcore->ehdr);
-       if (!ehdr)
-               goto out_end;
+       memset(&kcore->ehdr, 0, sizeof(GElf_Ehdr));
 
        return 0;
 
@@ -1348,23 +1344,18 @@ static int kcore__copy_hdr(struct kcore *from, struct kcore *to, size_t count)
 static int kcore__add_phdr(struct kcore *kcore, int idx, off_t offset,
                           u64 addr, u64 len)
 {
-       GElf_Phdr gphdr;
-       GElf_Phdr *phdr;
-
-       phdr = gelf_getphdr(kcore->elf, idx, &gphdr);
-       if (!phdr)
-               return -1;
-
-       phdr->p_type    = PT_LOAD;
-       phdr->p_flags   = PF_R | PF_W | PF_X;
-       phdr->p_offset  = offset;
-       phdr->p_vaddr   = addr;
-       phdr->p_paddr   = 0;
-       phdr->p_filesz  = len;
-       phdr->p_memsz   = len;
-       phdr->p_align   = page_size;
-
-       if (!gelf_update_phdr(kcore->elf, idx, phdr))
+       GElf_Phdr phdr = {
+               .p_type         = PT_LOAD,
+               .p_flags        = PF_R | PF_W | PF_X,
+               .p_offset       = offset,
+               .p_vaddr        = addr,
+               .p_paddr        = 0,
+               .p_filesz       = len,
+               .p_memsz        = len,
+               .p_align        = page_size,
+       };
+
+       if (!gelf_update_phdr(kcore->elf, idx, &phdr))
                return -1;
 
        return 0;
index 7acafb3c5592d60501561986b1812fb6b121f271..c2cd9bf2348b5eb8e68603c32b7a3bf220c41aad 100644 (file)
@@ -709,7 +709,7 @@ bool find_process(const char *name)
 
        dir = opendir(procfs__mountpoint());
        if (!dir)
-               return -1;
+               return false;
 
        /* Walk through the directory. */
        while (ret && (d = readdir(dir)) != NULL) {
index 9655cb49c7cb8eb6427b078e0472451b777b9910..bde0ef1a63df4876d5149c85f4083eb92561dbb4 100644 (file)
@@ -71,8 +71,11 @@ unsigned int extra_msr_offset32;
 unsigned int extra_msr_offset64;
 unsigned int extra_delta_offset32;
 unsigned int extra_delta_offset64;
+unsigned int aperf_mperf_multiplier = 1;
 int do_smi;
 double bclk;
+double base_hz;
+double tsc_tweak = 1.0;
 unsigned int show_pkg;
 unsigned int show_core;
 unsigned int show_cpu;
@@ -502,7 +505,7 @@ int format_counters(struct thread_data *t, struct core_data *c,
        /* %Busy */
        if (has_aperf) {
                if (!skip_c0)
-                       outp += sprintf(outp, "%8.2f", 100.0 * t->mperf/t->tsc);
+                       outp += sprintf(outp, "%8.2f", 100.0 * t->mperf/t->tsc/tsc_tweak);
                else
                        outp += sprintf(outp, "********");
        }
@@ -510,7 +513,7 @@ int format_counters(struct thread_data *t, struct core_data *c,
        /* Bzy_MHz */
        if (has_aperf)
                outp += sprintf(outp, "%8.0f",
-                       1.0 * t->tsc / units * t->aperf / t->mperf / interval_float);
+                       1.0 * t->tsc * tsc_tweak / units * t->aperf / t->mperf / interval_float);
 
        /* TSC_MHz */
        outp += sprintf(outp, "%8.0f", 1.0 * t->tsc/units/interval_float);
@@ -984,6 +987,8 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
                        return -3;
                if (get_msr(cpu, MSR_IA32_MPERF, &t->mperf))
                        return -4;
+               t->aperf = t->aperf * aperf_mperf_multiplier;
+               t->mperf = t->mperf * aperf_mperf_multiplier;
        }
 
        if (do_smi) {
@@ -1149,6 +1154,19 @@ int slv_pkg_cstate_limits[16] = {PCL__0, PCL__1, PCLRSV, PCLRSV, PCL__4, PCLRSV,
 int amt_pkg_cstate_limits[16] = {PCL__0, PCL__1, PCL__2, PCLRSV, PCLRSV, PCLRSV, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
 int phi_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL_6N, PCL_6R, PCLRSV, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
 
+
+static void
+calculate_tsc_tweak()
+{
+       unsigned long long msr;
+       unsigned int base_ratio;
+
+       get_msr(base_cpu, MSR_NHM_PLATFORM_INFO, &msr);
+       base_ratio = (msr >> 8) & 0xFF;
+       base_hz = base_ratio * bclk * 1000000;
+       tsc_tweak = base_hz / tsc_hz;
+}
+
 static void
 dump_nhm_platform_info(void)
 {
@@ -1926,8 +1944,6 @@ int has_config_tdp(unsigned int family, unsigned int model)
 
        switch (model) {
        case 0x3A:      /* IVB */
-       case 0x3E:      /* IVB Xeon */
-
        case 0x3C:      /* HSW */
        case 0x3F:      /* HSX */
        case 0x45:      /* HSW */
@@ -2543,6 +2559,13 @@ int is_knl(unsigned int family, unsigned int model)
        return 0;
 }
 
+unsigned int get_aperf_mperf_multiplier(unsigned int family, unsigned int model)
+{
+       if (is_knl(family, model))
+               return 1024;
+       return 1;
+}
+
 #define SLM_BCLK_FREQS 5
 double slm_freq_table[SLM_BCLK_FREQS] = { 83.3, 100.0, 133.3, 116.7, 80.0};
 
@@ -2744,6 +2767,9 @@ void process_cpuid()
                }
        }
 
+       if (has_aperf)
+               aperf_mperf_multiplier = get_aperf_mperf_multiplier(family, model);
+
        do_nhm_platform_info = do_nhm_cstates = do_smi = probe_nhm_msrs(family, model);
        do_snb_cstates = has_snb_msrs(family, model);
        do_pc2 = do_snb_cstates && (pkg_cstate_limit >= PCL__2);
@@ -2762,6 +2788,9 @@ void process_cpuid()
        if (debug)
                dump_cstate_pstate_config_info();
 
+       if (has_skl_msrs(family, model))
+               calculate_tsc_tweak();
+
        return;
 }
 
@@ -3090,7 +3119,7 @@ int get_and_dump_counters(void)
 }
 
 void print_version() {
-       fprintf(stderr, "turbostat version 4.7 17-June, 2015"
+       fprintf(stderr, "turbostat version 4.8 26-Sep, 2015"
                " - Len Brown <lenb@kernel.org>\n");
 }
 
index 89b05e2222c913ff47e12673e9850616f585dbf9..cfe121353eec3cd5608e43d1c98144591aceae37 100644 (file)
@@ -16,12 +16,12 @@ TARGETS += powerpc
 TARGETS += ptrace
 TARGETS += seccomp
 TARGETS += size
+TARGETS += static_keys
 TARGETS += sysctl
 ifneq (1, $(quicktest))
 TARGETS += timers
 endif
 TARGETS += user
-TARGETS += jumplabel
 TARGETS += vm
 TARGETS += x86
 TARGETS += zram
index 6b76bfdc847ea58879cc52ccfa2b77ebd296150d..4e400eb83657ce5f35dac44300d61e58244af820 100644 (file)
@@ -1,6 +1,6 @@
 CFLAGS = -Wall
 BINARIES = execveat
-DEPS = execveat.symlink execveat.denatured script
+DEPS = execveat.symlink execveat.denatured script subdir
 all: $(BINARIES) $(DEPS)
 
 subdir:
@@ -22,7 +22,5 @@ TEST_FILES := $(DEPS)
 
 include ../lib.mk
 
-override EMIT_TESTS := echo "mkdir -p subdir; (./execveat && echo \"selftests: execveat [PASS]\") || echo \"selftests: execveat [FAIL]\""
-
 clean:
        rm -rf $(BINARIES) $(DEPS) subdir.moved execveat.moved xxxxx*
index 0acbeca472255f01bf6a987739f2b8d32213095f..4e6ed13e7f66150de10a8f645eff508fc0565cff 100644 (file)
@@ -1,7 +1,7 @@
 all:
 
 TEST_PROGS := ftracetest
-TEST_DIRS := test.d/
+TEST_DIRS := test.d
 
 include ../lib.mk
 
index 97f1c6742066352c6fd0a32599ecff93b3896499..50a93f5f13d64d5b0f9b4851d03f955da9b6e1d9 100644 (file)
@@ -12,13 +12,10 @@ run_tests: all
        $(RUN_TESTS)
 
 define INSTALL_RULE
-       @if [ "X$(TEST_PROGS)$(TEST_PROGS_EXTENDED)$(TEST_FILES)" != "X" ]; then                        \
-               mkdir -p $(INSTALL_PATH);                                                               \
-               for TEST_DIR in $(TEST_DIRS); do                                                        \
-                       cp -r $$TEST_DIR $(INSTALL_PATH);                                               \
-               done;                                                                                   \
-               echo "install -t $(INSTALL_PATH) $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES)";   \
-               install -t $(INSTALL_PATH) $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES);          \
+       @if [ "X$(TEST_PROGS)$(TEST_PROGS_EXTENDED)$(TEST_FILES)" != "X" ]; then                                        \
+               mkdir -p ${INSTALL_PATH};                                                                               \
+               echo "rsync -a $(TEST_DIRS) $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES) $(INSTALL_PATH)/";       \
+               rsync -a $(TEST_DIRS) $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES) $(INSTALL_PATH)/;              \
        fi
 endef
 
index 877a50355d7fd8787575c922db39ea280056fed4..a1a97085847d2e173f836864f35dfccc38229c2a 100644 (file)
@@ -1,11 +1,10 @@
 CFLAGS += -g -I../../../../usr/include/
 
-all:
-       $(CC) $(CFLAGS) membarrier_test.c -o membarrier_test
-
 TEST_PROGS := membarrier_test
 
+all: $(TEST_PROGS)
+
 include ../lib.mk
 
 clean:
-       $(RM) membarrier_test
+       $(RM) $(TEST_PROGS)
index dde3125080074a3588b99ee1beafee82f6a9eded..535f0fef4d0bb524f638774ffc199fde10c97497 100644 (file)
@@ -1,9 +1,6 @@
 #define _GNU_SOURCE
-#define __EXPORTED_HEADERS__
-
 #include <linux/membarrier.h>
-#include <asm-generic/unistd.h>
-#include <sys/syscall.h>
+#include <syscall.h>
 #include <stdio.h>
 #include <errno.h>
 #include <string.h>
index 0e3b41eb85cde2cd553bda36ac0b09f43553ceb8..eebac29acbd91fc6d10b6258f006834834e4b243 100644 (file)
@@ -1,8 +1,8 @@
-CFLAGS = -O2
+CFLAGS += -O2
+LDLIBS = -lrt -lpthread -lpopt
+TEST_PROGS := mq_open_tests mq_perf_tests
 
-all:
-       $(CC) $(CFLAGS) mq_open_tests.c -o mq_open_tests -lrt
-       $(CC) $(CFLAGS) -o mq_perf_tests mq_perf_tests.c -lrt -lpthread -lpopt
+all: $(TEST_PROGS)
 
 include ../lib.mk
 
@@ -11,8 +11,6 @@ override define RUN_TESTS
        @./mq_perf_tests || echo "selftests: mq_perf_tests [FAIL]"
 endef
 
-TEST_PROGS := mq_open_tests mq_perf_tests
-
 override define EMIT_TESTS
        echo "./mq_open_tests /test1 || echo \"selftests: mq_open_tests [FAIL]\""
        echo "./mq_perf_tests || echo \"selftests: mq_perf_tests [FAIL]\""
index d1b6475095967fb029af77ed69956c28b7828226..6cae06117b55297e031a210129e7f5a3f9d4c053 100644 (file)
 
 #define FIXUP_SECTION ".ex_fixup"
 
+static inline unsigned long __fls(unsigned long x);
+
 #include "word-at-a-time.h"
 
 #include "utils.h"
 
+static inline unsigned long __fls(unsigned long x)
+{
+       int lz;
+
+       asm (PPC_CNTLZL "%0,%1" : "=r" (lz) : "r" (x));
+       return sizeof(unsigned long) - 1 - lz;
+}
 
 static int page_size;
 static char *mem_region;
index a004b4cce99ef3098005ea4b4607cc825f46b667..770f47adf2958b9970b993d2fee57c489a9cd1e2 100644 (file)
@@ -1210,6 +1210,10 @@ TEST_F(TRACE_poke, getpid_runs_normally)
 # define ARCH_REGS     struct pt_regs
 # define SYSCALL_NUM   gpr[0]
 # define SYSCALL_RET   gpr[3]
+#elif defined(__s390__)
+# define ARCH_REGS     s390_regs
+# define SYSCALL_NUM   gprs[2]
+# define SYSCALL_RET   gprs[2]
 #else
 # error "Do not know how to find your architecture's registers and syscalls"
 #endif
@@ -1243,7 +1247,8 @@ void change_syscall(struct __test_metadata *_metadata,
        ret = ptrace(PTRACE_GETREGSET, tracee, NT_PRSTATUS, &iov);
        EXPECT_EQ(0, ret);
 
-#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || defined(__powerpc__)
+#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \
+    defined(__powerpc__) || defined(__s390__)
        {
                regs.SYSCALL_NUM = syscall;
        }
@@ -1281,17 +1286,21 @@ void tracer_syscall(struct __test_metadata *_metadata, pid_t tracee,
        ret = ptrace(PTRACE_GETEVENTMSG, tracee, NULL, &msg);
        EXPECT_EQ(0, ret);
 
+       /* Validate and take action on expected syscalls. */
        switch (msg) {
        case 0x1002:
                /* change getpid to getppid. */
+               EXPECT_EQ(__NR_getpid, get_syscall(_metadata, tracee));
                change_syscall(_metadata, tracee, __NR_getppid);
                break;
        case 0x1003:
                /* skip gettid. */
+               EXPECT_EQ(__NR_gettid, get_syscall(_metadata, tracee));
                change_syscall(_metadata, tracee, -1);
                break;
        case 0x1004:
                /* do nothing (allow getppid) */
+               EXPECT_EQ(__NR_getppid, get_syscall(_metadata, tracee));
                break;
        default:
                EXPECT_EQ(0, msg) {
@@ -1409,6 +1418,8 @@ TEST_F(TRACE_syscall, syscall_dropped)
 #  define __NR_seccomp 277
 # elif defined(__powerpc__)
 #  define __NR_seccomp 358
+# elif defined(__s390__)
+#  define __NR_seccomp 348
 # else
 #  warning "seccomp syscall number unknown for this architecture"
 #  define __NR_seccomp 0xffff
@@ -1453,6 +1464,9 @@ TEST(seccomp_syscall)
 
        /* Reject insane operation. */
        ret = seccomp(-1, 0, &prog);
+       ASSERT_NE(ENOSYS, errno) {
+               TH_LOG("Kernel does not support seccomp syscall!");
+       }
        EXPECT_EQ(EINVAL, errno) {
                TH_LOG("Did not reject crazy op value!");
        }
@@ -1501,6 +1515,9 @@ TEST(seccomp_syscall_mode_lock)
        }
 
        ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog);
+       ASSERT_NE(ENOSYS, errno) {
+               TH_LOG("Kernel does not support seccomp syscall!");
+       }
        EXPECT_EQ(0, ret) {
                TH_LOG("Could not install filter!");
        }
@@ -1535,6 +1552,9 @@ TEST(TSYNC_first)
 
        ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FLAG_FILTER_TSYNC,
                      &prog);
+       ASSERT_NE(ENOSYS, errno) {
+               TH_LOG("Kernel does not support seccomp syscall!");
+       }
        EXPECT_EQ(0, ret) {
                TH_LOG("Could not install initial filter with TSYNC!");
        }
@@ -1694,6 +1714,9 @@ TEST_F(TSYNC, siblings_fail_prctl)
 
        /* Check prctl failure detection by requesting sib 0 diverge. */
        ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog);
+       ASSERT_NE(ENOSYS, errno) {
+               TH_LOG("Kernel does not support seccomp syscall!");
+       }
        ASSERT_EQ(0, ret) {
                TH_LOG("setting filter failed");
        }
@@ -1731,6 +1754,9 @@ TEST_F(TSYNC, two_siblings_with_ancestor)
        }
 
        ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &self->root_prog);
+       ASSERT_NE(ENOSYS, errno) {
+               TH_LOG("Kernel does not support seccomp syscall!");
+       }
        ASSERT_EQ(0, ret) {
                TH_LOG("Kernel does not support SECCOMP_SET_MODE_FILTER!");
        }
@@ -1805,6 +1831,9 @@ TEST_F(TSYNC, two_siblings_with_no_filter)
 
        ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FLAG_FILTER_TSYNC,
                      &self->apply_prog);
+       ASSERT_NE(ENOSYS, errno) {
+               TH_LOG("Kernel does not support seccomp syscall!");
+       }
        ASSERT_EQ(0, ret) {
                TH_LOG("Could install filter on all threads!");
        }
@@ -1833,6 +1862,9 @@ TEST_F(TSYNC, two_siblings_with_one_divergence)
        }
 
        ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &self->root_prog);
+       ASSERT_NE(ENOSYS, errno) {
+               TH_LOG("Kernel does not support seccomp syscall!");
+       }
        ASSERT_EQ(0, ret) {
                TH_LOG("Kernel does not support SECCOMP_SET_MODE_FILTER!");
        }
@@ -1890,6 +1922,9 @@ TEST_F(TSYNC, two_siblings_not_under_filter)
        }
 
        ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &self->root_prog);
+       ASSERT_NE(ENOSYS, errno) {
+               TH_LOG("Kernel does not support seccomp syscall!");
+       }
        ASSERT_EQ(0, ret) {
                TH_LOG("Kernel does not support SECCOMP_SET_MODE_FILTER!");
        }
index 977a6afc448921858992bb02249f1855a5730ae7..fb2841601f2fe39b8922c5aa2e163993c9dd5d1f 100644 (file)
        __typeof__(_expected) __exp = (_expected); \
        __typeof__(_seen) __seen = (_seen); \
        if (!(__exp _t __seen)) { \
-               unsigned long long __exp_print = 0; \
-               unsigned long long __seen_print = 0; \
-               /* Avoid casting complaints the scariest way we can. */ \
-               memcpy(&__exp_print, &__exp, sizeof(__exp)); \
-               memcpy(&__seen_print, &__seen, sizeof(__seen)); \
+               unsigned long long __exp_print = (unsigned long long)__exp; \
+               unsigned long long __seen_print = (unsigned long long)__seen; \
                __TH_LOG("Expected %s (%llu) %s %s (%llu)", \
                         #_expected, __exp_print, #_t, \
                         #_seen, __seen_print); \
index d36fab7d8ebd90c1de5a6878171dca75ea518998..3c53cac15de141a7298d2d600517f20c6b3aac36 100644 (file)
@@ -1,6 +1,6 @@
 # Makefile for vm selftests
 
-CFLAGS = -Wall
+CFLAGS = -Wall -I ../../../../usr/include $(EXTRA_CFLAGS)
 BINARIES = compaction_test
 BINARIES += hugepage-mmap
 BINARIES += hugepage-shm
@@ -12,8 +12,11 @@ BINARIES += userfaultfd
 all: $(BINARIES)
 %: %.c
        $(CC) $(CFLAGS) -o $@ $^ -lrt
-userfaultfd: userfaultfd.c
-       $(CC) $(CFLAGS) -O2 -o $@ $^ -lpthread
+userfaultfd: userfaultfd.c ../../../../usr/include/linux/kernel.h
+       $(CC) $(CFLAGS) -O2 -o $@ $< -lpthread
+
+../../../../usr/include/linux/kernel.h:
+       make -C ../../../.. headers_install
 
 TEST_PROGS := run_vmtests
 TEST_FILES := $(BINARIES)
index 2c7cca6f26a45c215b43b44a7f5c9dddceee301c..d77ed41b209413756e779f73746765d09d98c949 100644 (file)
 #include <sys/syscall.h>
 #include <sys/ioctl.h>
 #include <pthread.h>
-#include "../../../../include/uapi/linux/userfaultfd.h"
-
-#ifdef __x86_64__
-#define __NR_userfaultfd 323
-#elif defined(__i386__)
-#define __NR_userfaultfd 374
-#elif defined(__powewrpc__)
-#define __NR_userfaultfd 364
-#else
-#error "missing __NR_userfaultfd definition"
-#endif
+#include <linux/userfaultfd.h>
+
+#ifdef __NR_userfaultfd
 
 static unsigned long nr_cpus, nr_pages, nr_pages_per_cpu, page_size;
 
@@ -430,7 +422,7 @@ static int userfaultfd_stress(void)
        struct uffdio_register uffdio_register;
        struct uffdio_api uffdio_api;
        unsigned long cpu;
-       int uffd_flags;
+       int uffd_flags, err;
        unsigned long userfaults[nr_cpus];
 
        if (posix_memalign(&area, page_size, nr_pages * page_size)) {
@@ -473,6 +465,14 @@ static int userfaultfd_stress(void)
                *area_mutex(area_src, nr) = (pthread_mutex_t)
                        PTHREAD_MUTEX_INITIALIZER;
                count_verify[nr] = *area_count(area_src, nr) = 1;
+               /*
+                * In the transition between 255 to 256, powerpc will
+                * read out of order in my_bcmp and see both bytes as
+                * zero, so leave a placeholder below always non-zero
+                * after the count, to avoid my_bcmp to trigger false
+                * positives.
+                */
+               *(area_count(area_src, nr) + 1) = 1;
        }
 
        pipefd = malloc(sizeof(int) * nr_cpus * 2);
@@ -499,6 +499,7 @@ static int userfaultfd_stress(void)
        pthread_attr_init(&attr);
        pthread_attr_setstacksize(&attr, 16*1024*1024);
 
+       err = 0;
        while (bounces--) {
                unsigned long expected_ioctls;
 
@@ -579,20 +580,13 @@ static int userfaultfd_stress(void)
                /* verification */
                if (bounces & BOUNCE_VERIFY) {
                        for (nr = 0; nr < nr_pages; nr++) {
-                               if (my_bcmp(area_dst,
-                                           area_dst + nr * page_size,
-                                           sizeof(pthread_mutex_t))) {
-                                       fprintf(stderr,
-                                               "error mutex 2 %lu\n",
-                                               nr);
-                                       bounces = 0;
-                               }
                                if (*area_count(area_dst, nr) != count_verify[nr]) {
                                        fprintf(stderr,
                                                "error area_count %Lu %Lu %lu\n",
                                                *area_count(area_src, nr),
                                                count_verify[nr],
                                                nr);
+                                       err = 1;
                                        bounces = 0;
                                }
                        }
@@ -609,7 +603,7 @@ static int userfaultfd_stress(void)
                printf("\n");
        }
 
-       return 0;
+       return err;
 }
 
 int main(int argc, char **argv)
@@ -618,8 +612,8 @@ int main(int argc, char **argv)
                fprintf(stderr, "Usage: <MiB> <bounces>\n"), exit(1);
        nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
        page_size = sysconf(_SC_PAGE_SIZE);
-       if ((unsigned long) area_count(NULL, 0) + sizeof(unsigned long long) >
-           page_size)
+       if ((unsigned long) area_count(NULL, 0) + sizeof(unsigned long long) * 2
+           page_size)
                fprintf(stderr, "Impossible to run this test\n"), exit(2);
        nr_pages_per_cpu = atol(argv[1]) * 1024*1024 / page_size /
                nr_cpus;
@@ -637,3 +631,15 @@ int main(int argc, char **argv)
               nr_pages, nr_pages_per_cpu);
        return userfaultfd_stress();
 }
+
+#else /* __NR_userfaultfd */
+
+#warning "missing __NR_userfaultfd definition"
+
+int main(void)
+{
+       printf("skip: Skipping userfaultfd test (missing __NR_userfaultfd)\n");
+       return 0;
+}
+
+#endif /* __NR_userfaultfd */
index 9a43a59a9bb46b2944b20b26f1af6e8e405b5764..d075ea0e5ca1ac0a42ce0d48e25b30a1a059de48 100644 (file)
@@ -116,8 +116,9 @@ static bool do_test(struct vm86plus_struct *v86, unsigned long eip,
        v86->regs.eip = eip;
        ret = vm86(VM86_ENTER, v86);
 
-       if (ret == -1 && errno == ENOSYS) {
-               printf("[SKIP]\tvm86 not supported\n");
+       if (ret == -1 && (errno == ENOSYS || errno == EPERM)) {
+               printf("[SKIP]\tvm86 %s\n",
+                      errno == ENOSYS ? "not supported" : "not allowed");
                return false;
        }
 
@@ -229,5 +230,9 @@ int main(void)
        }
        clearhandler(SIGSEGV);
 
+       /* Make sure nothing explodes if we fork. */
+       if (fork() > 0)
+               return 0;
+
        return (nerrs == 0 ? 0 : 1);
 }
index 20de9a7612692cc007035055a5b559993b5b8e1d..683a292e329015f3044194e753dd9fa9c62ba48a 100755 (executable)
@@ -1,15 +1,7 @@
 #!/bin/bash
 TCID="zram.sh"
 
-check_prereqs()
-{
-       local msg="skip all tests:"
-
-       if [ $UID != 0 ]; then
-               echo $msg must be run as root >&2
-               exit 0
-       fi
-}
+. ./zram_lib.sh
 
 run_zram () {
 echo "--------------------"
index 424e68ed1487d86cd7d6c62e28348251781f6500..f6a9c73e7a442e7988b0820ebc809a342981df91 100755 (executable)
@@ -23,8 +23,9 @@ trap INT
 check_prereqs()
 {
        local msg="skip all tests:"
+       local uid=$(id -u)
 
-       if [ $UID != 0 ]; then
+       if [ $uid -ne 0 ]; then
                echo $msg must be run as root >&2
                exit 0
        fi
index 505ad51b3b51bec2281fe44dce5786c0fe79088f..39c89a5ea990fab23fbccfd8a6cfa3952502bf98 100644 (file)
@@ -6,7 +6,7 @@ vringh_test: vringh_test.o vringh.o virtio_ring.o
 CFLAGS += -g -O2 -Werror -Wall -I. -I../include/ -I ../../usr/include/ -Wno-pointer-sign -fno-strict-overflow -fno-strict-aliasing -fno-common -MMD -U_FORTIFY_SOURCE
 vpath %.c ../../drivers/virtio ../../drivers/vhost
 mod:
-       ${MAKE} -C `pwd`/../.. M=`pwd`/vhost_test
+       ${MAKE} -C `pwd`/../.. M=`pwd`/vhost_test V=${V}
 .PHONY: all test mod clean
 clean:
        ${RM} *.o vringh_test virtio_test vhost_test/*.o vhost_test/.*.cmd \
index aff61e13306c7bba01f143802a63d6d866f31cf5..26b7926bda8849a8b931fff6750a3ed8217dae89 100644 (file)
@@ -3,6 +3,8 @@
 #define mb() __sync_synchronize()
 
 #define smp_mb()       mb()
+# define dma_rmb()     barrier()
+# define dma_wmb()     barrier()
 # define smp_rmb()     barrier()
 # define smp_wmb()     barrier()
 /* Weak barriers should be used. If not - it's a bug */
diff --git a/tools/virtio/linux/export.h b/tools/virtio/linux/export.h
new file mode 100644 (file)
index 0000000..416875e
--- /dev/null
@@ -0,0 +1,3 @@
+#define EXPORT_SYMBOL_GPL(sym) extern typeof(sym) sym
+#define EXPORT_SYMBOL(sym) extern typeof(sym) sym
+
index 1e8ce6979c1e5e0bd30b5424a1a1cf8b3063bf12..0a3da64638ceda0e94df98f9651fc241ae1f34c1 100644 (file)
@@ -22,6 +22,7 @@
 
 typedef unsigned long long dma_addr_t;
 typedef size_t __kernel_size_t;
+typedef unsigned int __wsum;
 
 struct page {
        unsigned long long dummy;
@@ -47,6 +48,13 @@ static inline void *kmalloc(size_t s, gfp_t gfp)
                return __kmalloc_fake;
        return malloc(s);
 }
+static inline void *kzalloc(size_t s, gfp_t gfp)
+{
+       void *p = kmalloc(s, gfp);
+
+       memset(p, 0, s);
+       return p;
+}
 
 static inline void kfree(void *p)
 {
index 76e38d231e9959d085673b4eda7e4065f4a7fbb7..b9d3a32cbc048ddb7c1c885fb3af523f97944fbc 100644 (file)
@@ -137,6 +137,8 @@ bool kvm_timer_should_fire(struct kvm_vcpu *vcpu)
 void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
 {
        struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
+       bool phys_active;
+       int ret;
 
        /*
         * We're about to run this vcpu again, so there is no need to
@@ -151,6 +153,23 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
         */
        if (kvm_timer_should_fire(vcpu))
                kvm_timer_inject_irq(vcpu);
+
+       /*
+        * We keep track of whether the edge-triggered interrupt has been
+        * signalled to the vgic/guest, and if so, we mask the interrupt and
+        * the physical distributor to prevent the timer from raising a
+        * physical interrupt whenever we run a guest, preventing forward
+        * VCPU progress.
+        */
+       if (kvm_vgic_get_phys_irq_active(timer->map))
+               phys_active = true;
+       else
+               phys_active = false;
+
+       ret = irq_set_irqchip_state(timer->map->irq,
+                                   IRQCHIP_STATE_ACTIVE,
+                                   phys_active);
+       WARN_ON(ret);
 }
 
 /**
@@ -199,6 +218,14 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
         */
        timer->irq = irq;
 
+       /*
+        * The bits in CNTV_CTL are architecturally reset to UNKNOWN for ARMv8
+        * and to 0 for ARMv7.  We provide an implementation that always
+        * resets the timer to be disabled and unmasked and is compliant with
+        * the ARMv7 architecture.
+        */
+       timer->cntv_ctl = 0;
+
        /*
         * Tell the VGIC that the virtual interrupt is tied to a
         * physical interrupt. We do that once per VCPU.
index afbf925b00f4ff079ea28925174e1998e54c44d1..7dd5d62f10a196a4b2fe4bb8f4bc340bf69484bc 100644 (file)
@@ -288,7 +288,7 @@ int vgic_v3_probe(struct device_node *vgic_node,
 
        vgic->vctrl_base = NULL;
        vgic->type = VGIC_V3;
-       vgic->max_gic_vcpus = KVM_MAX_VCPUS;
+       vgic->max_gic_vcpus = VGIC_V3_MAX_CPUS;
 
        kvm_info("%s@%llx IRQ%d\n", vgic_node->name,
                 vcpu_res.start, vgic->maint_irq);
index 9eb489a2c94c2b5ef07146a01ec9ac943034065c..66c66165e712d743ed3da1a501c03a087f442378 100644 (file)
@@ -531,6 +531,34 @@ bool vgic_handle_set_pending_reg(struct kvm *kvm,
        return false;
 }
 
+/*
+ * If a mapped interrupt's state has been modified by the guest such that it
+ * is no longer active or pending, without it have gone through the sync path,
+ * then the map->active field must be cleared so the interrupt can be taken
+ * again.
+ */
+static void vgic_handle_clear_mapped_irq(struct kvm_vcpu *vcpu)
+{
+       struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+       struct list_head *root;
+       struct irq_phys_map_entry *entry;
+       struct irq_phys_map *map;
+
+       rcu_read_lock();
+
+       /* Check for PPIs */
+       root = &vgic_cpu->irq_phys_map_list;
+       list_for_each_entry_rcu(entry, root, entry) {
+               map = &entry->map;
+
+               if (!vgic_dist_irq_is_pending(vcpu, map->virt_irq) &&
+                   !vgic_irq_is_active(vcpu, map->virt_irq))
+                       map->active = false;
+       }
+
+       rcu_read_unlock();
+}
+
 bool vgic_handle_clear_pending_reg(struct kvm *kvm,
                                   struct kvm_exit_mmio *mmio,
                                   phys_addr_t offset, int vcpu_id)
@@ -561,6 +589,7 @@ bool vgic_handle_clear_pending_reg(struct kvm *kvm,
                                          vcpu_id, offset);
                vgic_reg_access(mmio, reg, offset, mode);
 
+               vgic_handle_clear_mapped_irq(kvm_get_vcpu(kvm, vcpu_id));
                vgic_update_state(kvm);
                return true;
        }
@@ -598,6 +627,7 @@ bool vgic_handle_clear_active_reg(struct kvm *kvm,
                        ACCESS_READ_VALUE | ACCESS_WRITE_CLEARBIT);
 
        if (mmio->is_write) {
+               vgic_handle_clear_mapped_irq(kvm_get_vcpu(kvm, vcpu_id));
                vgic_update_state(kvm);
                return true;
        }
@@ -982,6 +1012,12 @@ static int compute_pending_for_cpu(struct kvm_vcpu *vcpu)
        pend_percpu = vcpu->arch.vgic_cpu.pending_percpu;
        pend_shared = vcpu->arch.vgic_cpu.pending_shared;
 
+       if (!dist->enabled) {
+               bitmap_zero(pend_percpu, VGIC_NR_PRIVATE_IRQS);
+               bitmap_zero(pend_shared, nr_shared);
+               return 0;
+       }
+
        pending = vgic_bitmap_get_cpu_map(&dist->irq_pending, vcpu_id);
        enabled = vgic_bitmap_get_cpu_map(&dist->irq_enabled, vcpu_id);
        bitmap_and(pend_percpu, pending, enabled, VGIC_NR_PRIVATE_IRQS);
@@ -1009,11 +1045,6 @@ void vgic_update_state(struct kvm *kvm)
        struct kvm_vcpu *vcpu;
        int c;
 
-       if (!dist->enabled) {
-               set_bit(0, dist->irq_pending_on_cpu);
-               return;
-       }
-
        kvm_for_each_vcpu(c, vcpu, kvm) {
                if (compute_pending_for_cpu(vcpu))
                        set_bit(c, dist->irq_pending_on_cpu);
@@ -1092,6 +1123,15 @@ static void vgic_retire_lr(int lr_nr, int irq, struct kvm_vcpu *vcpu)
        struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
        struct vgic_lr vlr = vgic_get_lr(vcpu, lr_nr);
 
+       /*
+        * We must transfer the pending state back to the distributor before
+        * retiring the LR, otherwise we may loose edge-triggered interrupts.
+        */
+       if (vlr.state & LR_STATE_PENDING) {
+               vgic_dist_irq_set_pending(vcpu, irq);
+               vlr.hwirq = 0;
+       }
+
        vlr.state = 0;
        vgic_set_lr(vcpu, lr_nr, vlr);
        clear_bit(lr_nr, vgic_cpu->lr_used);
@@ -1132,7 +1172,8 @@ static void vgic_queue_irq_to_lr(struct kvm_vcpu *vcpu, int irq,
                kvm_debug("Set active, clear distributor: 0x%x\n", vlr.state);
                vgic_irq_clear_active(vcpu, irq);
                vgic_update_state(vcpu->kvm);
-       } else if (vgic_dist_irq_is_pending(vcpu, irq)) {
+       } else {
+               WARN_ON(!vgic_dist_irq_is_pending(vcpu, irq));
                vlr.state |= LR_STATE_PENDING;
                kvm_debug("Set pending: 0x%x\n", vlr.state);
        }
@@ -1144,26 +1185,11 @@ static void vgic_queue_irq_to_lr(struct kvm_vcpu *vcpu, int irq,
                struct irq_phys_map *map;
                map = vgic_irq_map_search(vcpu, irq);
 
-               /*
-                * If we have a mapping, and the virtual interrupt is
-                * being injected, then we must set the state to
-                * active in the physical world. Otherwise the
-                * physical interrupt will fire and the guest will
-                * exit before processing the virtual interrupt.
-                */
                if (map) {
-                       int ret;
-
-                       BUG_ON(!map->active);
                        vlr.hwirq = map->phys_irq;
                        vlr.state |= LR_HW;
                        vlr.state &= ~LR_EOI_INT;
 
-                       ret = irq_set_irqchip_state(map->irq,
-                                                   IRQCHIP_STATE_ACTIVE,
-                                                   true);
-                       WARN_ON(ret);
-
                        /*
                         * Make sure we're not going to sample this
                         * again, as a HW-backed interrupt cannot be
@@ -1411,7 +1437,7 @@ static int vgic_sync_hwirq(struct kvm_vcpu *vcpu, struct vgic_lr vlr)
                return 0;
 
        map = vgic_irq_map_search(vcpu, vlr.irq);
-       BUG_ON(!map || !map->active);
+       BUG_ON(!map);
 
        ret = irq_get_irqchip_state(map->irq,
                                    IRQCHIP_STATE_ACTIVE,
@@ -1419,13 +1445,8 @@ static int vgic_sync_hwirq(struct kvm_vcpu *vcpu, struct vgic_lr vlr)
 
        WARN_ON(ret);
 
-       if (map->active) {
-               ret = irq_set_irqchip_state(map->irq,
-                                           IRQCHIP_STATE_ACTIVE,
-                                           false);
-               WARN_ON(ret);
+       if (map->active)
                return 0;
-       }
 
        return 1;
 }
@@ -1597,8 +1618,12 @@ static int vgic_update_irq_pending(struct kvm *kvm, int cpuid,
        } else {
                if (level_triggered) {
                        vgic_dist_irq_clear_level(vcpu, irq_num);
-                       if (!vgic_dist_irq_soft_pend(vcpu, irq_num))
+                       if (!vgic_dist_irq_soft_pend(vcpu, irq_num)) {
                                vgic_dist_irq_clear_pending(vcpu, irq_num);
+                               vgic_cpu_irq_clear(vcpu, irq_num);
+                               if (!compute_pending_for_cpu(vcpu))
+                                       clear_bit(cpuid, dist->irq_pending_on_cpu);
+                       }
                }
 
                ret = false;
index 5cbf190d238cd083e128ae9ec78da52b745d6338..6bca74ca533109a5e23ec40b045286095400ebad 100644 (file)
@@ -24,9 +24,9 @@ struct kvm_coalesced_mmio_dev {
 int kvm_coalesced_mmio_init(struct kvm *kvm);
 void kvm_coalesced_mmio_free(struct kvm *kvm);
 int kvm_vm_ioctl_register_coalesced_mmio(struct kvm *kvm,
-                                                                                                                                                               struct kvm_coalesced_mmio_zone *zone);
+                                       struct kvm_coalesced_mmio_zone *zone);
 int kvm_vm_ioctl_unregister_coalesced_mmio(struct kvm *kvm,
-                                                                                                                                                               struct kvm_coalesced_mmio_zone *zone);
+                                       struct kvm_coalesced_mmio_zone *zone);
 
 #else
 
index 9ff4193dfa493c3e226c3fd554061b171ca7b9c5..79db45336e3a25cb15696ca8659a87572e168585 100644 (file)
@@ -771,40 +771,14 @@ static enum kvm_bus ioeventfd_bus_from_flags(__u32 flags)
        return KVM_MMIO_BUS;
 }
 
-static int
-kvm_assign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)
+static int kvm_assign_ioeventfd_idx(struct kvm *kvm,
+                               enum kvm_bus bus_idx,
+                               struct kvm_ioeventfd *args)
 {
-       enum kvm_bus              bus_idx;
-       struct _ioeventfd        *p;
-       struct eventfd_ctx       *eventfd;
-       int                       ret;
-
-       bus_idx = ioeventfd_bus_from_flags(args->flags);
-       /* must be natural-word sized, or 0 to ignore length */
-       switch (args->len) {
-       case 0:
-       case 1:
-       case 2:
-       case 4:
-       case 8:
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       /* check for range overflow */
-       if (args->addr + args->len < args->addr)
-               return -EINVAL;
 
-       /* check for extra flags that we don't understand */
-       if (args->flags & ~KVM_IOEVENTFD_VALID_FLAG_MASK)
-               return -EINVAL;
-
-       /* ioeventfd with no length can't be combined with DATAMATCH */
-       if (!args->len &&
-           args->flags & (KVM_IOEVENTFD_FLAG_PIO |
-                          KVM_IOEVENTFD_FLAG_DATAMATCH))
-               return -EINVAL;
+       struct eventfd_ctx *eventfd;
+       struct _ioeventfd *p;
+       int ret;
 
        eventfd = eventfd_ctx_fdget(args->fd);
        if (IS_ERR(eventfd))
@@ -843,16 +817,6 @@ kvm_assign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)
        if (ret < 0)
                goto unlock_fail;
 
-       /* When length is ignored, MMIO is also put on a separate bus, for
-        * faster lookups.
-        */
-       if (!args->len && !(args->flags & KVM_IOEVENTFD_FLAG_PIO)) {
-               ret = kvm_io_bus_register_dev(kvm, KVM_FAST_MMIO_BUS,
-                                             p->addr, 0, &p->dev);
-               if (ret < 0)
-                       goto register_fail;
-       }
-
        kvm->buses[bus_idx]->ioeventfd_count++;
        list_add_tail(&p->list, &kvm->ioeventfds);
 
@@ -860,8 +824,6 @@ kvm_assign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)
 
        return 0;
 
-register_fail:
-       kvm_io_bus_unregister_dev(kvm, bus_idx, &p->dev);
 unlock_fail:
        mutex_unlock(&kvm->slots_lock);
 
@@ -873,14 +835,13 @@ fail:
 }
 
 static int
-kvm_deassign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)
+kvm_deassign_ioeventfd_idx(struct kvm *kvm, enum kvm_bus bus_idx,
+                          struct kvm_ioeventfd *args)
 {
-       enum kvm_bus              bus_idx;
        struct _ioeventfd        *p, *tmp;
        struct eventfd_ctx       *eventfd;
        int                       ret = -ENOENT;
 
-       bus_idx = ioeventfd_bus_from_flags(args->flags);
        eventfd = eventfd_ctx_fdget(args->fd);
        if (IS_ERR(eventfd))
                return PTR_ERR(eventfd);
@@ -901,10 +862,6 @@ kvm_deassign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)
                        continue;
 
                kvm_io_bus_unregister_dev(kvm, bus_idx, &p->dev);
-               if (!p->length) {
-                       kvm_io_bus_unregister_dev(kvm, KVM_FAST_MMIO_BUS,
-                                                 &p->dev);
-               }
                kvm->buses[bus_idx]->ioeventfd_count--;
                ioeventfd_release(p);
                ret = 0;
@@ -918,6 +875,71 @@ kvm_deassign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)
        return ret;
 }
 
+static int kvm_deassign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)
+{
+       enum kvm_bus bus_idx = ioeventfd_bus_from_flags(args->flags);
+       int ret = kvm_deassign_ioeventfd_idx(kvm, bus_idx, args);
+
+       if (!args->len && bus_idx == KVM_MMIO_BUS)
+               kvm_deassign_ioeventfd_idx(kvm, KVM_FAST_MMIO_BUS, args);
+
+       return ret;
+}
+
+static int
+kvm_assign_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)
+{
+       enum kvm_bus              bus_idx;
+       int ret;
+
+       bus_idx = ioeventfd_bus_from_flags(args->flags);
+       /* must be natural-word sized, or 0 to ignore length */
+       switch (args->len) {
+       case 0:
+       case 1:
+       case 2:
+       case 4:
+       case 8:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* check for range overflow */
+       if (args->addr + args->len < args->addr)
+               return -EINVAL;
+
+       /* check for extra flags that we don't understand */
+       if (args->flags & ~KVM_IOEVENTFD_VALID_FLAG_MASK)
+               return -EINVAL;
+
+       /* ioeventfd with no length can't be combined with DATAMATCH */
+       if (!args->len &&
+           args->flags & (KVM_IOEVENTFD_FLAG_PIO |
+                          KVM_IOEVENTFD_FLAG_DATAMATCH))
+               return -EINVAL;
+
+       ret = kvm_assign_ioeventfd_idx(kvm, bus_idx, args);
+       if (ret)
+               goto fail;
+
+       /* When length is ignored, MMIO is also put on a separate bus, for
+        * faster lookups.
+        */
+       if (!args->len && bus_idx == KVM_MMIO_BUS) {
+               ret = kvm_assign_ioeventfd_idx(kvm, KVM_FAST_MMIO_BUS, args);
+               if (ret < 0)
+                       goto fast_fail;
+       }
+
+       return 0;
+
+fast_fail:
+       kvm_deassign_ioeventfd_idx(kvm, bus_idx, args);
+fail:
+       return ret;
+}
+
 int
 kvm_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)
 {
index a25a73147f714458dd6c55fe7426649f9dd5baa2..8db1d93619936a55567120f3852a4fb4d7ee3307 100644 (file)
@@ -66,8 +66,8 @@
 MODULE_AUTHOR("Qumranet");
 MODULE_LICENSE("GPL");
 
-/* halt polling only reduces halt latency by 5-7 us, 500us is enough */
-static unsigned int halt_poll_ns = 500000;
+/* Architectures should define their poll value according to the halt latency */
+static unsigned int halt_poll_ns = KVM_HALT_POLL_NS_DEFAULT;
 module_param(halt_poll_ns, uint, S_IRUGO | S_IWUSR);
 
 /* Default doubles per-vcpu halt_poll_ns. */
@@ -2004,6 +2004,7 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
        if (vcpu->halt_poll_ns) {
                ktime_t stop = ktime_add_ns(ktime_get(), vcpu->halt_poll_ns);
 
+               ++vcpu->stat.halt_attempted_poll;
                do {
                        /*
                         * This sets KVM_REQ_UNHALT if an interrupt
@@ -2043,7 +2044,8 @@ out:
                else if (vcpu->halt_poll_ns < halt_poll_ns &&
                        block_ns < halt_poll_ns)
                        grow_halt_poll_ns(vcpu);
-       }
+       } else
+               vcpu->halt_poll_ns = 0;
 
        trace_kvm_vcpu_wakeup(block_ns, waited);
 }
@@ -3156,10 +3158,25 @@ static void kvm_io_bus_destroy(struct kvm_io_bus *bus)
 static inline int kvm_io_bus_cmp(const struct kvm_io_range *r1,
                                 const struct kvm_io_range *r2)
 {
-       if (r1->addr < r2->addr)
+       gpa_t addr1 = r1->addr;
+       gpa_t addr2 = r2->addr;
+
+       if (addr1 < addr2)
                return -1;
-       if (r1->addr + r1->len > r2->addr + r2->len)
+
+       /* If r2->len == 0, match the exact address.  If r2->len != 0,
+        * accept any overlapping write.  Any order is acceptable for
+        * overlapping ranges, because kvm_io_bus_get_first_dev ensures
+        * we process all of them.
+        */
+       if (r2->len) {
+               addr1 += r1->len;
+               addr2 += r2->len;
+       }
+
+       if (addr1 > addr2)
                return 1;
+
        return 0;
 }