Merge tag 'mfd-fixes-4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 14 Oct 2015 16:47:38 +0000 (09:47 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 14 Oct 2015 16:47:38 +0000 (09:47 -0700)
Pull MFD fixes from Lee Jones:
 "Bug Fixes:

   - Return correct error code i.e. not zero

   - Fix build error when !CONFIG_PM_SLEEP"

* tag 'mfd-fixes-4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd:
  mfd: max77843: Fix max77843_chg_init() return on error
  mfd: intel-lpss: Fix build error when !CONFIG_PM_SLEEP

856 files changed:
Documentation/Changes
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/pci/pci-rcar-gen2.txt
Documentation/devicetree/bindings/regulator/pbias-regulator.txt
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/input/multi-touch-protocol.txt
Documentation/networking/vrf.txt [new file with mode: 0644]
Documentation/power/pci.txt
Documentation/ptp/testptp.c
Documentation/sysctl/net.txt
Documentation/thermal/power_allocator.txt
MAINTAINERS
Makefile
arch/alpha/include/asm/word-at-a-time.h
arch/alpha/kernel/pci.c
arch/arc/include/asm/Kbuild
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/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/exynos4412.dtsi
arch/arm/boot/dts/exynos5250-smdk5250.dts
arch/arm/boot/dts/exynos5420.dtsi
arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi
arch/arm/boot/dts/imx53-qsrb.dts
arch/arm/boot/dts/imx53.dtsi
arch/arm/boot/dts/imx6qdl-rex.dtsi
arch/arm/boot/dts/omap2430.dtsi
arch/arm/boot/dts/omap3-beagle.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/stih407.dtsi
arch/arm/boot/dts/stih410.dtsi
arch/arm/boot/dts/sun7i-a20.dtsi
arch/arm/configs/omap2plus_defconfig
arch/arm/include/asm/kvm_host.h
arch/arm/include/asm/unistd.h
arch/arm/include/uapi/asm/unistd.h
arch/arm/kernel/calls.S
arch/arm/mach-exynos/mcpm-exynos.c
arch/arm/mach-exynos/regs-pmu.h
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/pm.h
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/include/mach/addr-map.h
arch/arm/mach-pxa/pxa3xx.c
arch/arm/mm/alignment.c
arch/arm/plat-pxa/ssp.c
arch/arm64/boot/dts/mediatek/mt8173.dtsi
arch/arm64/boot/dts/rockchip/rk3368.dtsi
arch/arm64/include/asm/kvm_host.h
arch/arm64/include/asm/pgtable.h
arch/arm64/kernel/debug-monitors.c
arch/arm64/kernel/efi.c
arch/arm64/kernel/entry-ftrace.S
arch/arm64/kernel/insn.c
arch/arm64/kernel/setup.c
arch/arm64/mm/fault.c
arch/avr32/include/asm/Kbuild
arch/blackfin/include/asm/Kbuild
arch/c6x/include/asm/Kbuild
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/pci/pci.c
arch/m32r/include/asm/Kbuild
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/linkage.h
arch/m68k/include/asm/unistd.h
arch/m68k/include/uapi/asm/unistd.h
arch/m68k/kernel/syscalltable.S
arch/metag/include/asm/Kbuild
arch/microblaze/include/asm/Kbuild
arch/microblaze/pci/pci-common.c
arch/mips/ath79/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/mips-cm.h
arch/mips/include/asm/mipsregs.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/loongson64/common/env.c
arch/mips/mm/dma-default.c
arch/mips/mm/init.c
arch/mips/net/bpf_jit_asm.S
arch/mips/pci/pci.c
arch/mn10300/include/asm/Kbuild
arch/mn10300/unit-asb2305/pci.c
arch/nios2/include/asm/Kbuild
arch/powerpc/include/asm/kvm_host.h
arch/powerpc/include/asm/systbl.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/pci-common.c
arch/powerpc/kvm/book3s.c
arch/powerpc/kvm/book3s_hv.c
arch/powerpc/kvm/book3s_hv_rmhandlers.S
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/numa/mode_emu.c
arch/s390/numa/numa.c
arch/score/include/asm/Kbuild
arch/sparc/crypto/aes_glue.c
arch/sparc/crypto/camellia_glue.c
arch/sparc/crypto/des_glue.c
arch/tile/gxio/mpipe.c
arch/tile/include/asm/word-at-a-time.h
arch/tile/kernel/usb.c
arch/um/include/asm/Kbuild
arch/unicore32/include/asm/Kbuild
arch/x86/Kconfig
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/pvclock-abi.h
arch/x86/include/asm/xen/hypercall.h
arch/x86/include/uapi/asm/bitsperlong.h
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_msr.c
arch/x86/kernel/cpu/scattered.c
arch/x86/kernel/crash.c
arch/x86/kernel/paravirt.c
arch/x86/kernel/process.c
arch/x86/kernel/process_32.c
arch/x86/kernel/process_64.c
arch/x86/kvm/mmu.c
arch/x86/kvm/svm.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/mm/init_64.c
arch/x86/pci/common.c
arch/x86/platform/efi/efi.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/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
crypto/ahash.c
crypto/asymmetric_keys/x509_public_key.c
drivers/acpi/ec.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/power/opp.c
drivers/base/regmap/regmap-debugfs.c
drivers/block/loop.c
drivers/block/null_blk.c
drivers/block/nvme-core.c
drivers/block/virtio_blk.c
drivers/block/xen-blkback/xenbus.c
drivers/block/xen-blkfront.c
drivers/bus/Kconfig
drivers/char/hw_random/xgene-rng.c
drivers/clk/samsung/clk-cpu.c
drivers/clk/ti/clk-3xxx.c
drivers/clk/ti/clk-7xx.c
drivers/clk/ti/clkt_dflt.c
drivers/clocksource/rockchip_timer.c
drivers/clocksource/timer-keystone.c
drivers/cpufreq/acpi-cpufreq.c
drivers/cpufreq/cpufreq.c
drivers/crypto/marvell/cesa.h
drivers/crypto/marvell/cipher.c
drivers/crypto/marvell/hash.c
drivers/crypto/qat/qat_common/adf_aer.c
drivers/devfreq/devfreq.c
drivers/dma/at_xdmac.c
drivers/dma/dmaengine.c
drivers/dma/dw/core.c
drivers/dma/idma64.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/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.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_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_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_v11_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_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_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_runtime_pm.c
drivers/gpu/drm/mgag200/mgag200_fb.c
drivers/gpu/drm/mgag200/mgag200_main.c
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nouveau_fbcon.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_device.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_dp_mst.c
drivers/gpu/drm/radeon/radeon_fb.c
drivers/gpu/drm/radeon/radeon_kms.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/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/hv/channel_mgmt.c
drivers/hwmon/abx500.c
drivers/hwmon/gpio-fan.c
drivers/hwmon/pwm-fan.c
drivers/idle/intel_idle.c
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/mlx5/mlx5_ib.h
drivers/infiniband/hw/mlx5/qp.c
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/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/imx6ul_tsc.c
drivers/input/touchscreen/mms114.c
drivers/iommu/Kconfig
drivers/iommu/amd_iommu.c
drivers/iommu/amd_iommu_init.c
drivers/iommu/arm-smmu-v3.c
drivers/iommu/intel-iommu.c
drivers/iommu/io-pgtable-arm.c
drivers/iommu/iova.c
drivers/irqchip/irq-atmel-aic5.c
drivers/irqchip/irq-gic-v3-its-pci-msi.c
drivers/irqchip/irq-gic-v3-its.c
drivers/irqchip/irq-mips-gic.c
drivers/mcb/mcb-pci.c
drivers/md/bitmap.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/raid0.c
drivers/md/raid1.c
drivers/md/raid10.c
drivers/md/raid5.c
drivers/misc/cxl/sysfs.c
drivers/misc/mei/debugfs.c
drivers/misc/mei/hbm.c
drivers/mmc/core/core.c
drivers/mmc/core/host.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/dsa/mv88e6xxx.c
drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
drivers/net/ethernet/arc/emac_arc.c
drivers/net/ethernet/broadcom/bcmsysport.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
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/chelsio/cxgb4/t4_pci_id_tbl.h
drivers/net/ethernet/emulex/benet/be.h
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/freescale/gianfar.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_main.c
drivers/net/ethernet/intel/i40evf/i40e_adminq.c
drivers/net/ethernet/marvell/mvneta.c
drivers/net/ethernet/mellanox/mlx4/en_rx.c
drivers/net/ethernet/mellanox/mlx4/mcg.c
drivers/net/ethernet/mellanox/mlx5/core/fw.c
drivers/net/ethernet/micrel/ks8851.c
drivers/net/ethernet/moxa/moxart_ether.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/stmicro/stmmac/stmmac_mdio.c
drivers/net/ethernet/sun/sunvnet.c
drivers/net/ethernet/ti/netcp_core.c
drivers/net/ethernet/ti/netcp_ethss.c
drivers/net/ethernet/via/Kconfig
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/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.c
drivers/net/phy/mdio_bus.c
drivers/net/phy/phy_device.c
drivers/net/phy/vitesse.c
drivers/net/ppp/ppp_generic.c
drivers/net/usb/Kconfig
drivers/net/usb/Makefile
drivers/net/usb/ch9200.c [new file with mode: 0644]
drivers/net/vrf.c
drivers/net/vxlan.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-rcar-gen2.c
drivers/pci/pci-driver.c
drivers/pci/probe.c
drivers/pci/quirks.c
drivers/phy/phy-berlin-sata.c
drivers/phy/phy-qcom-ufs.c
drivers/phy/phy-rockchip-usb.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/scsi/3w-9xxx.c
drivers/scsi/libiscsi.c
drivers/scsi/scsi_dh.c
drivers/scsi/scsi_lib.c
drivers/sh/pm_runtime.c
drivers/spi/spi-atmel.c
drivers/spi/spi-bcm2835.c
drivers/spi/spi-davinci.c
drivers/spi/spi-meson-spifc.c
drivers/spi/spi-mt65xx.c
drivers/spi/spi-pxa2xx.c
drivers/spi/spi-xtensa-xtfpga.c
drivers/spi/spi.c
drivers/spi/spidev.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/lustre/README.txt
drivers/staging/most/Kconfig
drivers/staging/most/hdm-dim2/Kconfig
drivers/staging/most/hdm-usb/Kconfig
drivers/staging/most/mostcore/Kconfig
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/thermal_core.c
drivers/thermal/ti-soc-thermal/Kconfig
drivers/thunderbolt/nhi.c
drivers/tty/n_tty.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/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/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/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/inode.c
fs/btrfs/send.c
fs/btrfs/super.c
fs/btrfs/transaction.c
fs/btrfs/transaction.h
fs/cifs/cifsencrypt.c
fs/cifs/cifsfs.h
fs/cifs/inode.c
fs/cifs/smb2ops.c
fs/cifs/smb2pdu.c
fs/dax.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/ubifs/xattr.c
fs/userfaultfd.c
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/linux/acpi.h
include/linux/backing-dev.h
include/linux/blk-mq.h
include/linux/blkdev.h
include/linux/cgroup-defs.h
include/linux/init_task.h
include/linux/iova.h
include/linux/irqdomain.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/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/string.h
include/linux/sunrpc/xprtsock.h
include/linux/thermal.h
include/linux/usb/renesas_usbhs.h
include/linux/wait.h
include/net/af_unix.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/target/target_core_base.h
include/uapi/asm-generic/unistd.h
include/uapi/linux/lwtunnel.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/handle.c
kernel/irq/proc.c
kernel/locking/lockdep.c
kernel/rcu/tree.c
kernel/sched/core.c
kernel/sched/sched.h
kernel/sched/wait.c
kernel/time/clocksource.c
lib/iommu-common.c
lib/rhashtable.c
lib/string.c
mm/dmapool.c
mm/filemap.c
mm/hugetlb.c
mm/memcontrol.c
mm/migrate.c
mm/mmap.c
mm/slab.c
mm/vmscan.c
net/atm/clip.c
net/bluetooth/smp.c
net/bridge/br_multicast.c
net/core/dev.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/icmp.c
net/ipv4/inet_connection_sock.c
net/ipv4/inet_timewait_sock.c
net/ipv4/ip_tunnel_core.c
net/ipv4/route.c
net/ipv4/tcp_cubic.c
net/ipv4/tcp_minisocks.c
net/ipv4/tcp_output.c
net/ipv4/udp.c
net/ipv4/xfrm4_policy.c
net/ipv6/addrconf.c
net/ipv6/ip6_fib.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_output.c
net/ipv6/ip6_tunnel.c
net/ipv6/route.c
net/l2tp/l2tp_core.c
net/mac80211/cfg.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/conntrack.c
net/openvswitch/datapath.c
net/openvswitch/flow_netlink.c
net/openvswitch/flow_table.c
net/openvswitch/flow_table.h
net/packet/af_packet.c
net/sched/cls_fw.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/tipc/msg.c
net/unix/af_unix.c
samples/kprobes/jprobe_example.c
samples/kprobes/kprobe_example.c
samples/kprobes/kretprobe_example.c
scripts/extract-cert.c
scripts/sign-file.c
security/keys/gc.c
sound/arm/Kconfig
sound/pci/hda/hda_tegra.c
sound/pci/hda/patch_cirrus.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/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-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/config/Makefile
tools/perf/util/Build
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/membarrier/Makefile
tools/testing/selftests/membarrier/membarrier_test.c
tools/testing/selftests/vm/Makefile
tools/testing/selftests/vm/userfaultfd.c
virt/kvm/kvm_main.c

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
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 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
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..6160ffbcb3d331b8712eec389a2d4dc95c3bac64 100644 (file)
@@ -15,17 +15,18 @@ 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:
 - mediatek,pad-select: specify which pins group(ck/mi/mo/cs) spi
@@ -44,8 +45,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";
+       clocks = <&topckgen CLK_TOP_SYSPLL3_D2>,
+                <&topckgen CLK_TOP_SPI_SEL>,
+                <&pericfg CLK_PERI_SPI0>;
+       clock-names = "parent-clk", "sel-clk", "spi-clk";
+
        mediatek,pad-select = <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 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 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 274f85405584e1249c8b089b789f1a4d11973500..5f467845ef725f42cca522e9f02bf93292c42d4a 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
@@ -3394,7 +3400,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
@@ -3998,7 +4003,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 +4018,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
@@ -5952,7 +5957,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 +5965,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*
@@ -8500,7 +8505,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
@@ -9904,13 +9908,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 +10341,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 +11200,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 +11252,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 +11265,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 +11377,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*
index 84f4b31e3c6eaa14411812ec3617e1b894175f26..416660d05739d5a5fe05dcb10b463f883b8c04f2 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
 VERSION = 4
 PATCHLEVEL = 3
 SUBLEVEL = 0
-EXTRAVERSION = -rc2
-NAME = Hurr durr I'ma sheep
+EXTRAVERSION = -rc5
+NAME = Blurry Fish Butt
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
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 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 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 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..568adf5efde059f8c9a5ee56d182ea8def05788e 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 */
                                };
 
                                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 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 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 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 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 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 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 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 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 3df1e975f72aa57af59c19f3f564f0de9388b535..c4072d9f32c7718c9be3a92626f01d80ff74b3c1 100644 (file)
@@ -33,6 +33,7 @@
 #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
 
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 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 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 07d2e100caabf935c019beda8c2a830e3d2ae3f7..b3a0dff67e3fc48bb34b13567778d0f178298834 100644 (file)
@@ -44,10 +44,11 @@ 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
 
 config SOC_AM33XX
        bool "TI AM33XX"
@@ -70,10 +71,13 @@ 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
 
 config ARCH_OMAP2PLUS
        bool
index 24c9afc9e8a70206bbb799c106345a9bd59bef5b..6133eaac685df545ec5a6665db0ae72051d8c2fa 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", },
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 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 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 a3ebb517cca1af2941f7a8118cd30c9cc4d15b83..a727282bfa99605b51c3fd498af006829442b286 100644 (file)
@@ -502,7 +502,7 @@ static void balloon3_irq_handler(struct irq_desc *desc)
                                        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 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 ce0f8d6242e2a047429a031f7ab9e6e53193d917..06005d3f2ba33523d1ee4f9e96499290a9908572 100644 (file)
@@ -47,6 +47,13 @@ extern void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int));
 #define ISRAM_START    0x5c000000
 #define ISRAM_SIZE     SZ_256K
 
+/*
+ * 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)
+
 static void __iomem *sram;
 static unsigned long wakeup_src;
 
@@ -362,7 +369,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 +431,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 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 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 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 4562459456a62c68e08d3480dc135eb1831dca1f..ed039688c221444e6e4526a0444eb5573d00609b 100644 (file)
@@ -33,6 +33,7 @@
 #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>
index b0329be95cb129f3b283f3d75e4dfeff64214bff..26b066690593cd6304e81fdd24465a25ace2f396 100644 (file)
@@ -79,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)
@@ -496,7 +496,7 @@ 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))
                pte = pte_mkdirty(pte);
index cebf78661a553775003bfee8ec89f65e33e3ec55..253021ef2769078e69793288a8cc067aebb76d34 100644 (file)
@@ -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 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 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 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 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 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 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 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 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 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 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 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 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 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 15ecb4831e125838477a4805810381e1f1bb6725..eeb3953ed8ac8d8051ccbe3df9af8270915329b3 100644 (file)
@@ -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 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 3a54dbca9f7e0b9d0ab11d0a65aad59ddb9bc29b..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
 
 
 
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 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 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 a74e181058b0fc8ce001fffc68bce8f95bc7f02d..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)
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 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 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 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 195886a583bab5c3d4dbc88782785cff95d309a9..827a38d7a9dbe32adfcaf7937c276f6cfce222a4 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
index 4d65499ee1c115b32193dea7a9015c9e03e82e9c..126d0c4f9b7ddc9b98a90564180d24191204875a 100644 (file)
@@ -369,3 +369,4 @@ SYSCALL_SPU(bpf)
 COMPAT_SYS(execveat)
 PPC64ONLY(switch_endian)
 SYSCALL_SPU(userfaultfd)
+SYSCALL_SPU(membarrier)
index 4a055b6c2a64f0f4153a1c2dea557289d2e56941..13411be86041ced7c5e81921f93ec50d21c1afdc 100644 (file)
@@ -12,7 +12,7 @@
 #include <uapi/asm/unistd.h>
 
 
-#define __NR_syscalls          365
+#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 6ad58d4c879bf6a1018420540d73dc2efc5fc7da..6337738018aad4768c1276079ab89562d186fc70 100644 (file)
 #define __NR_execveat          362
 #define __NR_switch_endian     363
 #define __NR_userfaultfd       364
+#define __NR_membarrier                365
 
 #endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */
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 cf009167d208db3ebf3d74a2e1f29b3bfb091d26..099c79d8c160fd59c2d0e28217c1348f03c08cbf 100644 (file)
@@ -829,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;
 
@@ -869,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) {
@@ -892,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..2280497868886990678c19c01f5cf1c22b25f7a5 100644 (file)
@@ -2692,9 +2692,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++;
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 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 6ce4a0b7e8dafb7bed2fec0a824e0aeb886e6066..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
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 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 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 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 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 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 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 328c8352480c5dcfd34d72a70d01d6a57e5bb515..96d058a871007e7b119bd3a6d3ff14eb9a5a61eb 100644 (file)
@@ -1308,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 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 e6cf2ad350d15a8e6ca207a2618c77d820aacc22..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 */
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 349f80a82b8207411f3e377f8fa924bb19d060f0..2beee03820889b6c6b436e884a4e83e023d76f9a 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
 
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 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 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 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 3fefebfbdf4bb4f68e5a5bf1647550ad0cd71a75..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
 };
 
@@ -2891,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,
@@ -2907,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,
@@ -3516,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 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 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 6d0e62ae8516760d6ae4af7deaa31418e82238fa..39e585a554b71d2a469c8b8c3ba487be7edc87a7 100644 (file)
@@ -506,3 +506,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(*(unsigned long *)sp);
+       do {
+               if (fp < bottom || fp > top)
+                       return 0;
+               ip = READ_ONCE(*(unsigned long *)(fp + sizeof(unsigned long)));
+               if (!in_sched_functions(ip))
+                       return ip;
+               fp = READ_ONCE(*(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 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 64076740251e7f3b8197fe87eeff262891ac995a..06ef4908ba61d2e25ead615953a2f42c923a9219 100644 (file)
@@ -8617,17 +8617,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 6bbb0dfb99d0a5e222131c9b2f8e0fb38e990cb3..92511d4b72364a978db0b38628b9449907ee1832 100644 (file)
@@ -1708,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;
@@ -2007,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;
@@ -2190,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:
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 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 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 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..ed96474d75cb62fb261526736727c67ea2238d46 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)
 {
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..7785ae96267a197926c700f74bcd6524892a8c01 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);
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 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 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 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 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 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 a295b98c6baed2df8bdd9484a62e44ca9bbfdc7a..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);
index b97fc3fe0916a6b6fd3fb2be32be44ce3c137b39..6f04771f1019798cc2feabf73eff2ddbadc84b81 100644 (file)
@@ -618,16 +618,15 @@ static void req_completion(struct nvme_queue *nvmeq, void *ctx,
                        spin_unlock_irqrestore(req->q->queue_lock, flags);
                        return;
                }
+
                if (req->cmd_type == REQ_TYPE_DRV_PRIV) {
                        if (cmd_rq->ctx == CMD_CTX_CANCELLED)
-                               req->errors = -EINTR;
-                       else
-                               req->errors = status;
+                               status = -EINTR;
                } else {
-                       req->errors = nvme_error_status(status);
+                       status = 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;
@@ -650,7 +649,7 @@ static void req_completion(struct nvme_queue *nvmeq, void *ctx,
        }
        nvme_free_iod(nvmeq->dev, iod);
 
-       blk_mq_complete_request(req);
+       blk_mq_complete_request(req, status);
 }
 
 /* length is in bytes.  gfp flags indicates whether we may sleep. */
@@ -863,8 +862,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;
                }
        }
@@ -2439,6 +2437,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 +2464,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 +2968,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 +3009,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 +3059,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 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..611170896b8c94ce1d7494d62116ba1fde574fce 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();
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 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 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 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 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 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 798277227de7f3a897a4ad79fcaabe787412fcfb..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);
 }
 
index ef5ed9470de9a59d371e34e7db24a434d1f11a9f..25c4c15103a0cd8759e006eaa10d9f9edbfb5872 100644 (file)
@@ -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 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 3927ed9fdbd51f16d765aede8fef14418994ab55..ca848cc6a8fd1313bc56e5b93674b3d795814779 100644 (file)
@@ -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 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 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 668939a14206b4113991b69636915d562ea3d55c..6647fb26ef25ce21dba9bffb87cb31e5abe73d80 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)
 {
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 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 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 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 6411e824467164831eef8af634051f95b8faba69..fcd2ed5589022eb05087a055111b5a6b53efa067 100644 (file)
@@ -2888,7 +2888,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;
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..9745ed3a9aef866443e269022142c52ec3fc3d65 100644 (file)
@@ -2995,6 +2995,12 @@ static int kv_dpm_late_init(void *handle)
 {
        /* powerdown unused blocks for now */
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+       int ret;
+
+       /* 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 +3044,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 e23df5fd3836b1b70169a1ee125782c1e754b875..bf27a07dbce36993e7ed668ff567f5565a6e0995 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);
 }
@@ -1202,10 +1214,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 +1469,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 +1478,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 +1511,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 +1991,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 +2278,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 +2686,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 +2709,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 +2765,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);
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 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..cf418be7d30a52d0e25ac42201b61b0e42f16dbe 100644 (file)
@@ -15087,9 +15087,12 @@ static void readout_plane_state(struct intel_crtc *crtc,
 
                plane_state = to_intel_plane_state(p->base.state);
 
-               if (p->base.type == DRM_PLANE_TYPE_PRIMARY)
+               if (p->base.type == DRM_PLANE_TYPE_PRIMARY) {
                        plane_state->visible = primary_get_hw_state(crtc);
-               else {
+                       if (plane_state->visible)
+                               crtc->base.state->plane_mask |=
+                                       1 << drm_plane_index(&p->base);
+               } else {
                        if (active)
                                p->disable_plane(&p->base, &crtc->base);
 
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..7412caedcf7f98a2a5e494c41e2bad97f34d4e34 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));
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 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 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 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..65adb9c723772d9f0011573d320182823b18d37a 100644 (file)
@@ -1624,8 +1624,9 @@ 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);
+                       struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+
+                       atombios_set_backlight_level(radeon_encoder, dig->backlight_level);
                }
                break;
        case DRM_MODE_DPMS_STANDBY:
@@ -1706,8 +1707,7 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
                                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);
+                       atombios_set_backlight_level(radeon_encoder, dig->backlight_level);
                if (ext_encoder)
                        atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
                break;
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..6cddae44fa6e4cafa59de1b3d7528b82959b6fd9 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;
 
@@ -286,12 +285,19 @@ static struct drm_connector *radeon_dp_add_mst_connector(struct drm_dp_mst_topol
        drm_object_attach_property(&connector->base, dev->mode_config.path_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 +330,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 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 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..44489cce7458402cf8a48a6176e3ed4625b603d5 100644 (file)
@@ -1326,14 +1326,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 +1383,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 +1523,44 @@ 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) {
+                       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");
+
+                       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) {
+                       /* 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");
+               }
        }
        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 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..8a76821177a6c0c1a3cc9659b4f119943d48b3ce 100644 (file)
@@ -681,6 +681,14 @@ static bool vmw_cmdbuf_try_alloc(struct vmw_cmdbuf_man *man,
                                         0, 0,
                                         DRM_MM_SEARCH_DEFAULT,
                                         DRM_MM_CREATE_DEFAULT);
+       if (ret) {
+               (void) 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;
 
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..64b50409fa0749558844cf561aac983e36197241 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,7 @@ static void vmw_user_surface_base_release(struct ttm_base_object **p_base)
        struct vmw_resource *res = &user_srf->srf.res;
 
        *p_base = NULL;
+       ttm_base_object_unref(&user_srf->backup_base);
        vmw_resource_unreference(&res);
 }
 
@@ -851,7 +853,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 +1324,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 +1339,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 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 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 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 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 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 ca2873698d75444066312640a1eb84dc5e2190db..4cd5428a2399a2cc73757c49382842094714d1bc 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,
@@ -548,6 +548,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..f74316e679d2fc2b7b27212d47fc806e95844f01 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,8 @@ 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);
 }
 
 static void ipoib_reap_neigh(struct work_struct *work)
index 09a1748f9d131423f020020456d61d2f6c44a8b1..136cbefe00f87aeb79b02d6508d42fdac5741069 100644 (file)
@@ -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 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 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 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..08d2775887f7add00e44858cc6bf4a5eece6e260 100644 (file)
@@ -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 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..35365f046923db7df50f43f318310711e7fd5e31 100644 (file)
@@ -2301,6 +2301,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 +3216,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 +3714,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 +3728,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 +3737,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 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 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 ac7ae2b3cb83726e336ce310d95e2b890da8224d..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;
 }
 
index af2f16bb8a94d3912787b1893431c97e541fc0ec..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++)
@@ -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 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 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..aeacad9be51dcb1c10c78df1398abddb9e8bc4f1 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,8 +844,7 @@ 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;
 
@@ -873,6 +873,16 @@ static int persistent_ctr(struct dm_exception_store *store,
                return -ENOMEM;
        }
 
+       if (options) {
+               char overflow = toupper(options[0]);
+               if (overflow == 'O')
+                       store->userspace_supports_overflow = true;
+               else {
+                       DMERR("Unsupported persistent store option: %s", options);
+                       return -EINVAL;
+               }
+       }
+
        store->context = ps;
 
        return 0;
@@ -888,7 +898,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..6fcbfb0633665a7c7b91d036b771cd997560e3de 100644 (file)
@@ -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..c702de18207ae76ab56f1235ed5c98a9095ed050 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);
@@ -8160,6 +8164,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 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..ddd8a5f572aa1c023db07b3eab6b72bc0371c1dd 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;
@@ -2383,8 +2382,8 @@ 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);
                        raid_end_bio_io(r1_bio);
                }
@@ -2843,8 +2842,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 +2944,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..9f69dc526f8cbf271f45b4d7745a442aa6324329 100644 (file)
@@ -2688,8 +2688,8 @@ 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);
                        raid_end_bio_io(r10_bio);
                }
@@ -3486,8 +3486,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 +3681,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 +3694,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..49bb8d3ff9be8c7741a5bebc6b210fde38989a09 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) &&
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 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 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 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 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 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 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 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..3bc701e4c59eb56cc19e11c917dd34c24062754e 100644 (file)
@@ -3155,6 +3155,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 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..821540913343db10f59ae3a03835a084ca82063d 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;
index 12687bf52b9518eaa1c4bb538ff26fcc88ce7acc..7bf51a1a0a77e12a4812662767dd21767813dc1b 100644 (file)
@@ -5176,6 +5176,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 +5231,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 4b69d061d90f7983fb0ee4929b7f6074922d3690..710715fcb23dea7765ce3fc579c88fcd29ecb0da 100644 (file)
@@ -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;
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..62488a67149d1f0ac38279517427853ebbcec6fc 100644 (file)
@@ -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 851c1a159be8a1566d8a792c52bf4e83ea6877d7..2fdf978ae6a5d10a6751f3ec702ef3636fca543f 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
index f08450b907745afefcdd6da766f7a32ae3aa57c2..929d47152bf271b1ddba3d8dc284d1941131261a 100644 (file)
@@ -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 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 4c7de8c446599f5b0198fb3d4d015d9540f9f962..e7a5000aa12cd4c49f9dae9283664df921491455 100644 (file)
@@ -1270,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 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 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 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 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 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 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..6bff8d82ceab7a428e73048504a5dd63f4a1c1bd 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)
@@ -2997,6 +2982,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++)
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 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..8f5c02eed47de09883b43b8b587717993064ef0b 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)) {
@@ -626,6 +626,7 @@ 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 */
        struct flowi4 fl4;
        __u8 tos, ttl;
        __be16 sport;
@@ -653,6 +654,8 @@ static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev)
        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 +671,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)))
@@ -748,12 +748,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 +815,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 +840,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,7 +867,7 @@ 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;
@@ -890,7 +886,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 +909,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 +931,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 +971,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..248478c6f6e49522681a3eeb8a80fd8eaefd32fc 100644 (file)
@@ -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 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 4d4d25efc1e10a2b87e3c8ab993ae3ba6167a7dd..280c7c311f72442c4877815ece73c2a36745be49 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;
@@ -173,6 +173,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 +193,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 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 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 1610b79ae3866725a12f9af8a2ed83255999217a..fbb9325d1f6e539421f2ad592d718bcede68acea 100644 (file)
@@ -583,4 +583,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
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 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..bbac1d35ed4e37450a3282b4b7f9dc41dabcd4e8 100644 (file)
@@ -2392,10 +2392,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 +2636,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 +2669,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)
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 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 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 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 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 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 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 edb044a7b56d348a269634212155edce3a89f9b8..0a2168e69bbcd31c91a995dae5439a1485cc0a7d 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);
        }
 
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 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 bf9ed380bb1c0754addbd27aedf7d874cee89ff2..63318e2afba1900bc3923d3b4023143699a4842e 100644 (file)
@@ -1720,6 +1720,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 +1757,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 e7874a6171ecdb4b5b5e7c99bb706aaca2135e2d..3e8eeb23d4e9c4e8d9c91084181a6c0ad2e51cd2 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;
        }
 
index 3cf9faa6cc3fe871174ec1b2777472b0ac4c6883..a85d863d4a442f2f30633db5de0ff469ee9c6348 100644 (file)
@@ -992,11 +992,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 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 5f6315c47920efcb42dc52b5c93c26ce60cb7de4..ecb6c58238c4f56867e73e3f074ddf90f1b04ee3 100644 (file)
@@ -85,7 +85,7 @@ struct mtk_spi {
        void __iomem *base;
        u32 state;
        u32 pad_sel;
-       struct clk *spi_clk, *parent_clk;
+       struct clk *parent_clk, *sel_clk, *spi_clk;
        struct spi_transfer *cur_transfer;
        u32 xfer_len;
        struct scatterlist *tx_sgl, *rx_sgl;
@@ -173,22 +173,6 @@ static void mtk_spi_config(struct mtk_spi *mdata,
                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)
 {
@@ -228,11 +212,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,
@@ -509,7 +497,6 @@ 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;
@@ -576,13 +563,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 +570,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;
@@ -630,7 +624,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 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 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..a5f53de813d337bc86fd36ed3b837d299ab11b99 100644 (file)
@@ -1610,8 +1610,7 @@ static struct class spi_master_class = {
  *
  * 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.
  */
 struct spi_master *spi_alloc_master(struct device *dev, unsigned size)
 {
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 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 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 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 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 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 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..c79d33676672daca6047ebead9d8afb70a49007d 100644 (file)
@@ -180,51 +180,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 +300,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..43291f93afeb59a90a3b39cbb045a26b3bd1ad5b 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;
@@ -3461,8 +3470,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 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 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 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 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 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 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 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 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 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 7ae6df7ea1d2d04962ef4554a6a2fa1efb977006..bcfb14bfc1e49eb36d507c53ccd1c3f4f23135f9 100644 (file)
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -569,8 +569,20 @@ int __dax_pmd_fault(struct vm_area_struct *vma, unsigned long address,
        if (!buffer_size_valid(&bh) || bh.b_size < PMD_SIZE)
                goto fallback;
 
+       sector = bh.b_blocknr << (blkbits - 9);
+
        if (buffer_unwritten(&bh) || buffer_new(&bh)) {
                int i;
+
+               length = bdev_direct_access(bh.b_bdev, sector, &kaddr, &pfn,
+                                               bh.b_size);
+               if (length < 0) {
+                       result = VM_FAULT_SIGBUS;
+                       goto out;
+               }
+               if ((length < PMD_SIZE) || (pfn & PG_PMD_COLOUR))
+                       goto fallback;
+
                for (i = 0; i < PTRS_PER_PMD; i++)
                        clear_pmem(kaddr + i * PAGE_SIZE, PAGE_SIZE);
                wmb_pmem();
@@ -623,7 +635,6 @@ int __dax_pmd_fault(struct vm_area_struct *vma, unsigned long address,
                result = VM_FAULT_NOPAGE;
                spin_unlock(ptl);
        } else {
-               sector = bh.b_blocknr << (blkbits - 9);
                length = bdev_direct_access(bh.b_bdev, sector, &kaddr, &pfn,
                                                bh.b_size);
                if (length < 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..ee5aa4daaea0dbf6c1840649ac505f60313aa8dd 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;
@@ -1658,15 +1659,18 @@ send_response:
                        mlog(ML_ERROR, "failed to dispatch assert master work\n");
                        response = DLM_MASTER_RESP_ERROR;
                        dlm_lockres_put(res);
-               } else
+               } else {
+                       dispatched = 1;
                        __dlm_lockres_grab_inflight_worker(dlm, res);
+               }
                spin_unlock(&res->spinlock);
        } else {
                if (res)
                        dlm_lockres_put(res);
        }
 
-       dlm_put(dlm);
+       if (!dispatched)
+               dlm_put(dlm);
        return response;
 }
 
@@ -2090,7 +2094,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..3d90ad7ff91fe4748386218807f7131bd61d7d69 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,8 +1720,10 @@ 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);
                } else {
                        /* put.. incase we are not the master */
@@ -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 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 f9aeb40a7197475ec52ba414852ff356129b0aab..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);
 }
 
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..0f408b002d989ee8bca9489d6c1add673b315a51 100644 (file)
@@ -374,6 +374,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 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 5a5d79ee256f24aa2de8fa92778e8e85cdfcd4b2..d5eb4ad1c534a8074b64ee75d4b597563e36e89a 100644 (file)
@@ -13,6 +13,7 @@
 #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>
@@ -252,13 +253,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);
 }
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 99da9ebc73776af0a5efb69a73310f522b952b25..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 */
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 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 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 ad800e62cb7a603fdd5f7fb1a752edb03417dbb4..6452ff4c463fd8715edc9a5043bc812521a18d6a 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;
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..2d15e383144038ca12d5e876bf4e5cbfe5f84feb 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
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..6b00f18f5e6b725cabca142137be4eb58eb3df48 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
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 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..cb1b9bbda332116b6e2173b011ff9fd58f83f431 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(struct sock *sk)
+{
+       return (struct unix_sock *)sk;
+}
 
 #define peer_wait peer_wq.wait
 
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..186f3a1e1b1f6ddd898d0f5871cb46222ae6b80d 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 void inline inet_twsk_schedule(struct inet_timewait_sock *tw, int timeo)
+{
+       __inet_twsk_schedule(tw, timeo, false);
+}
+
+static void inline 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 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 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 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 de41a68fc038df70b8578e6ec1174fbcf53a1f0f..e25a83b67ccea18568f932636b72bd0e9ba182d0 100644 (file)
@@ -22,7 +22,6 @@
 
 /**
  * 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.
@@ -35,6 +34,7 @@ void handle_bad_irq(struct irq_desc *desc)
        kstat_incr_irqs_this_cpu(desc);
        ack_bad_irq(irq);
 }
+EXPORT_SYMBOL_GPL(handle_bad_irq);
 
 /*
  * Special, empty irq handler:
index e3a8c9577ba641c38747a0925a7896eca7ef4d79..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"
 
@@ -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 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 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 2f9c9288481779c309f31c19dc3b74831ef70b3d..10a8faa1b0d4a5f737bd9008eb8f9a7e817b6ec9 100644 (file)
@@ -2517,11 +2517,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);
@@ -4934,7 +4934,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
@@ -4951,7 +4959,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);
@@ -4966,7 +4974,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
 }
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 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 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 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..1cc5467cf36ce7852f7a0474d5fd3237b3dfff10 100644 (file)
@@ -2473,6 +2473,21 @@ 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;
+               }
+
                status = a_ops->write_begin(file, mapping, pos, bytes, flags,
                                                &page, &fsdata);
                if (unlikely(status < 0))
@@ -2480,17 +2495,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,14 +2519,6 @@ 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;
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 6ddaeba34e097a7553d33b8add26e26a27d3c81a..1fedbde68f595c2b83d5aa84962a667c1ada120a 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++) {
@@ -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 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 c739d6db7193e854dc2e4495bcaf9ed4678e1e6b..79bcc9f92e482de9047c3927e068ff392db5c1bc 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1490,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
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 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 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 877c84834d81a601ee4934fb287d1afccd4ee598..6bb6470f5b7bbbfaa60de8e33277b63aadbdb641 100644 (file)
@@ -4713,6 +4713,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 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..05a04ea871728d2c18f68571321e9435df1f3b18 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. */
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..c59fa5d9c22c449b4bfa9f058575d44324cfd7f9 100644 (file)
@@ -634,6 +634,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 +665,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 +701,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 +723,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 +762,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 +773,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 +788,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
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..f03db8b7abee68806468c104470da4054a8bf755 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);
        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 = dst_clone(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,9 +804,10 @@ 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);
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..6c2af797f2f92b93cf4ea28d1d5deee4e725f757 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;
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..7bb9c39e0a4d1a6a30b7aece9d3b0c17e447c20a 100644 (file)
@@ -685,20 +685,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 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 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 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..1100ffe4a722d7bbae1ec30ee165ecc565cc2e72 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);
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 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..900113376d4e0e528dc5a5d349687ae908ca08d6 100644 (file)
@@ -5127,13 +5127,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 418d9823692b6e78077d44c1ed8b15e998e2316b..7d2e0023c72dbe2e466b35ffb1c6f0c0446af6da 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);
        }
 }
 
@@ -846,7 +851,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 +877,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 +938,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 +1034,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 +1059,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 +1071,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 +1422,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..92b1aa38f121507b662e2c964423952bf995b81e 100644 (file)
@@ -586,20 +586,22 @@ int ip6_fragment(struct sock *sk, struct sk_buff *skb,
        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 +618,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 +625,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 +726,6 @@ slow_path:
         */
 
        *prevhdr = NEXTHDR_FRAGMENT;
-       hroom = LL_RESERVED_SPACE(rt->dst.dev);
        troom = rt->dst.dev->needed_tailroom;
 
        /*
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 53617d71518850dfc26220dd15923b8027c5249a..cb32ce250db0c0fd8cdc19a066f3956a893f2fba 100644 (file)
@@ -1193,7 +1193,8 @@ struct dst_entry *ip6_route_output(struct net *net, const struct sock *sk,
 
        fl6->flowi6_iif = LOOPBACK_IFINDEX;
 
-       if ((sk && sk->sk_bound_dev_if) || rt6_need_strict(&fl6->daddr))
+       if ((sk && sk->sk_bound_dev_if) || rt6_need_strict(&fl6->daddr) ||
+           fl6->flowi6_oif)
                flags |= RT6_LOOKUP_F_IFACE;
 
        if (!ipv6_addr_any(&fl6->saddr))
@@ -1322,8 +1323,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 +1886,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 +2030,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 +2518,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);
 
@@ -3303,7 +3307,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 +3323,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 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 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..8f060d7f9a0e107a410d3ffe71722f49059f7bc8 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) {
@@ -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
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 e8e524ad8a01cb3e62b531cf13659784f2f123ef..002a755fa07ea8c6c71c762716a5be8700c0a36c 100644 (file)
@@ -275,13 +275,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:
index 6fbd2decb19e2682bacd1d1cfedf186b4724bd9c..b816ff87152834065841ff41e96d2f0d9ee4e307 100644 (file)
@@ -952,7 +952,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 +1080,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 c92d6a262bc5100771b7f0fd25e39742350f5ca7..5c030a4d73382f6123345f4a6b608ea1b1684ae0 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)
@@ -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.  */
@@ -349,6 +355,13 @@ static const struct ovs_len_tbl ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = {
        [OVS_KEY_ATTR_CT_LABEL]  = { .len = sizeof(struct ovs_key_ct_label) },
 };
 
+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;
@@ -1052,10 +1086,13 @@ 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));
+               }
        }
 }
 
@@ -1922,8 +1959,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))
index d22d8e948d0f4b126894a71f8dcc30bc7d6d024d..f2ea83ba47631d4f650aa3dcf2f9c66cf4fd1c6f 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++;
 }
 
@@ -475,7 +476,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 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 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 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..8a477e27bad75f4b9a6c8feeceb745ffe9407c71 100644 (file)
@@ -755,19 +755,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 +1255,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 562c926a51cc7baa859115b6a0d444f73febf357..c5ac436235e0823c016123394fef6a0cf321092c 100644 (file)
@@ -539,6 +539,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 03ee4d359f6a4922397a1a8a36c015a06aae1cac..ef31b40ad55000a5fd029d7479b546483cc782b3 100644 (file)
@@ -2179,8 +2179,21 @@ unlock:
                        if (UNIXCB(skb).fp)
                                scm.fp = scm_fp_dup(UNIXCB(skb).fp);
 
-                       sk_peek_offset_fwd(sk, chunk);
+                       if (skip) {
+                               sk_peek_offset_fwd(sk, chunk);
+                               skip -= chunk;
+                       }
 
+                       if (UNIXCB(skb).fp)
+                               break;
+
+                       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 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 6ce5945a0b892e79f2e98e645615cbc37b79f4d1..b071bf476fea7ede6aab95730f5844ac1bf5caa5 100644 (file)
 #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 c3899ca4811cc2e0add94f8f31e31b93be432fff..250a7a6450331ae0805aaf3100da46af66dd4827 100755 (executable)
 #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] */
@@ -110,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();
                }
@@ -157,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.
         */
@@ -213,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");
@@ -221,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
 
-               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);
+       if (save_sig) {
+               char *sig_file_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);
        }
 
@@ -247,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 c7952375ac5325cfb4c403fa1020671b5f31a150..39eac1fd5706c6370df8b18fe5ac42e85e1b2ed3 100644 (file)
@@ -134,6 +134,10 @@ static noinline void key_gc_unused_keys(struct list_head *keys)
                kdebug("- %u", key->serial);
                key_check(key);
 
+               /* Throw away the key data */
+               if (key->type->destroy)
+                       key->type->destroy(key);
+
                security_key_free(key);
 
                /* deal with the user's key tracking and quota */
@@ -148,10 +152,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 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 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 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 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..2fbc6ef8cbdb394fd4ffa2b612f50d111fcdc4e5 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;
 }
 
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 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 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 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 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 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 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 04146a2e1d8191e3e152954824594555884f5f6d..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. */