Merge remote-tracking branches 'spi/fix/ep93xx', 'spi/fix/rockchip', 'spi/fix/sunxi...
authorMark Brown <broonie@kernel.org>
Thu, 30 Jun 2016 12:17:29 +0000 (13:17 +0100)
committerMark Brown <broonie@kernel.org>
Thu, 30 Jun 2016 12:17:29 +0000 (13:17 +0100)
986 files changed:
.mailmap
CREDITS
Documentation/ABI/testing/configfs-usb-gadget-uvc
Documentation/ABI/testing/sysfs-bus-iio-proximity-as3935
Documentation/DocBook/device-drivers.tmpl
Documentation/arm64/silicon-errata.txt
Documentation/devicetree/bindings/display/imx/ldb.txt
Documentation/devicetree/bindings/hwmon/ina2xx.txt
Documentation/devicetree/bindings/i2c/i2c-arb-gpio-challenge.txt
Documentation/devicetree/bindings/i2c/i2c-demux-pinctrl.txt
Documentation/devicetree/bindings/i2c/i2c-mux-gpio.txt
Documentation/devicetree/bindings/i2c/i2c-mux-pinctrl.txt
Documentation/devicetree/bindings/i2c/i2c-mux-reg.txt
Documentation/devicetree/bindings/net/marvell-bt-sd8xxx.txt
Documentation/devicetree/bindings/vendor-prefixes.txt
Documentation/filesystems/devpts.txt
Documentation/kdump/gdbmacros.txt
Documentation/leds/leds-class.txt
Documentation/networking/dsa/dsa.txt
Documentation/networking/ip-sysctl.txt
Documentation/scsi/scsi_eh.txt
Documentation/security/keys.txt
MAINTAINERS
Makefile
arch/Kconfig
arch/alpha/include/asm/pgalloc.h
arch/arc/Kconfig
arch/arc/Makefile
arch/arc/boot/dts/abilis_tb100.dtsi
arch/arc/boot/dts/abilis_tb101.dtsi
arch/arc/boot/dts/axc001.dtsi
arch/arc/boot/dts/axc003.dtsi
arch/arc/boot/dts/axc003_idu.dtsi
arch/arc/boot/dts/eznps.dts
arch/arc/boot/dts/nsim_700.dts
arch/arc/boot/dts/nsimosci.dts
arch/arc/boot/dts/nsimosci_hs.dts
arch/arc/boot/dts/nsimosci_hs_idu.dts
arch/arc/boot/dts/skeleton.dtsi
arch/arc/boot/dts/skeleton_hs.dtsi
arch/arc/boot/dts/skeleton_hs_idu.dtsi
arch/arc/boot/dts/vdk_axc003.dtsi
arch/arc/boot/dts/vdk_axc003_idu.dtsi
arch/arc/include/asm/atomic.h
arch/arc/include/asm/entry-compact.h
arch/arc/include/asm/mmu_context.h
arch/arc/include/asm/pgalloc.h
arch/arc/include/asm/pgtable.h
arch/arc/include/asm/processor.h
arch/arc/include/asm/smp.h
arch/arc/include/asm/spinlock.h
arch/arc/include/asm/thread_info.h
arch/arc/include/asm/uaccess.h
arch/arc/include/uapi/asm/swab.h
arch/arc/kernel/entry-compact.S
arch/arc/kernel/intc-compact.c
arch/arc/kernel/perf_event.c
arch/arc/kernel/setup.c
arch/arc/kernel/signal.c
arch/arc/kernel/troubleshoot.c
arch/arc/mm/cache.c
arch/arc/mm/dma.c
arch/arm/boot/dts/Makefile
arch/arm/boot/dts/am437x-sk-evm.dts
arch/arm/boot/dts/am57xx-idk-common.dtsi
arch/arm/boot/dts/dm8148-evm.dts
arch/arm/boot/dts/dm8148-t410.dts
arch/arm/boot/dts/dra7.dtsi
arch/arm/boot/dts/dra74x.dtsi
arch/arm/boot/dts/exynos5250-snow-common.dtsi
arch/arm/boot/dts/exynos5420-peach-pit.dts
arch/arm/boot/dts/omap3-evm-37xx.dts
arch/arm/boot/dts/omap3-igep.dtsi
arch/arm/boot/dts/omap3-igep0020-common.dtsi
arch/arm/boot/dts/omap3-n900.dts
arch/arm/boot/dts/omap3-n950-n9.dtsi
arch/arm/boot/dts/omap3-zoom3.dts
arch/arm/boot/dts/omap5-board-common.dtsi
arch/arm/boot/dts/omap5-igep0050.dts
arch/arm/boot/dts/omap5-uevm.dts
arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts
arch/arm/boot/dts/stih407-family.dtsi
arch/arm/boot/dts/sun6i-a31s-primo81.dts
arch/arm/boot/dts/sun6i-a31s-yones-toptech-bs1078-v2.dts
arch/arm/configs/exynos_defconfig
arch/arm/configs/multi_v7_defconfig
arch/arm/include/asm/pgalloc.h
arch/arm/include/asm/pgtable-2level.h
arch/arm/include/asm/pgtable-3level.h
arch/arm/include/asm/pgtable.h
arch/arm/kernel/ptrace.c
arch/arm/kernel/smp.c
arch/arm/mach-exynos/Kconfig
arch/arm/mach-imx/mach-imx6ul.c
arch/arm/mach-omap1/ams-delta-fiq-handler.S
arch/arm/mach-omap1/ams-delta-fiq.c
arch/arm/mach-omap1/include/mach/ams-delta-fiq.h
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/omap-secure.h
arch/arm/mach-omap2/omap-smp.c
arch/arm/mach-omap2/powerdomain.c
arch/arm/mach-omap2/powerdomains7xx_data.c
arch/arm/mach-omap2/timer.c
arch/arm/mach-vexpress/spc.c
arch/arm/plat-samsung/devs.c
arch/arm64/Kconfig
arch/arm64/Kconfig.debug
arch/arm64/Makefile
arch/arm64/boot/dts/lg/lg1312.dtsi
arch/arm64/boot/dts/rockchip/rk3399.dtsi
arch/arm64/include/asm/elf.h
arch/arm64/include/asm/kgdb.h
arch/arm64/include/asm/memory.h
arch/arm64/include/asm/page.h
arch/arm64/include/asm/pgalloc.h
arch/arm64/include/asm/smp.h
arch/arm64/include/asm/spinlock.h
arch/arm64/include/asm/uaccess.h
arch/arm64/include/asm/unistd.h
arch/arm64/include/asm/unistd32.h
arch/arm64/kernel/cpuinfo.c
arch/arm64/kernel/hibernate.c
arch/arm64/kernel/kgdb.c
arch/arm64/kernel/smp.c
arch/arm64/kernel/traps.c
arch/arm64/kvm/hyp/vgic-v3-sr.c
arch/arm64/kvm/sys_regs.c
arch/arm64/mm/context.c
arch/arm64/mm/dump.c
arch/arm64/mm/fault.c
arch/arm64/mm/flush.c
arch/arm64/mm/hugetlbpage.c
arch/avr32/include/asm/pgalloc.h
arch/cris/include/asm/pgalloc.h
arch/frv/mm/pgalloc.c
arch/hexagon/include/asm/pgalloc.h
arch/ia64/Kconfig
arch/ia64/include/asm/thread_info.h
arch/ia64/kernel/init_task.c
arch/m68k/include/asm/mcf_pgalloc.h
arch/m68k/include/asm/motorola_pgalloc.h
arch/m68k/include/asm/sun3_pgalloc.h
arch/metag/include/asm/pgalloc.h
arch/microblaze/include/asm/pgalloc.h
arch/microblaze/mm/pgtable.c
arch/mips/include/asm/kvm_host.h
arch/mips/include/asm/pgalloc.h
arch/mips/kvm/emulate.c
arch/mips/kvm/interrupt.h
arch/mips/kvm/locore.S
arch/mips/kvm/mips.c
arch/mn10300/include/asm/thread_info.h
arch/mn10300/kernel/kgdb.c
arch/mn10300/mm/pgtable.c
arch/nios2/include/asm/pgalloc.h
arch/openrisc/include/asm/pgalloc.h
arch/openrisc/mm/ioremap.c
arch/parisc/include/asm/pgalloc.h
arch/parisc/include/asm/traps.h
arch/parisc/kernel/processor.c
arch/parisc/kernel/time.c
arch/parisc/kernel/unaligned.c
arch/parisc/kernel/unwind.c
arch/powerpc/Kconfig
arch/powerpc/include/asm/book3s/32/pgalloc.h
arch/powerpc/include/asm/book3s/64/mmu-hash.h
arch/powerpc/include/asm/book3s/64/pgalloc.h
arch/powerpc/include/asm/book3s/64/radix.h
arch/powerpc/include/asm/book3s/64/tlbflush-radix.h
arch/powerpc/include/asm/book3s/64/tlbflush.h
arch/powerpc/include/asm/book3s/pgalloc.h
arch/powerpc/include/asm/nohash/64/pgalloc.h
arch/powerpc/include/asm/reg.h
arch/powerpc/kernel/eeh_driver.c
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kernel/prom_init.c
arch/powerpc/kernel/ptrace.c
arch/powerpc/mm/hash_native_64.c
arch/powerpc/mm/hash_utils_64.c
arch/powerpc/mm/hugetlbpage.c
arch/powerpc/mm/mmu_context_book3s64.c
arch/powerpc/mm/pgtable-book3s64.c
arch/powerpc/mm/pgtable-radix.c
arch/powerpc/mm/pgtable_32.c
arch/powerpc/mm/pgtable_64.c
arch/powerpc/mm/tlb-radix.c
arch/powerpc/platforms/512x/clock-commonclk.c
arch/powerpc/platforms/cell/spufs/coredump.c
arch/powerpc/platforms/pseries/eeh_pseries.c
arch/powerpc/platforms/pseries/iommu.c
arch/s390/configs/default_defconfig
arch/s390/configs/gcov_defconfig
arch/s390/configs/performance_defconfig
arch/s390/configs/zfcpdump_defconfig
arch/s390/defconfig
arch/s390/include/asm/kvm_host.h
arch/s390/kernel/perf_cpum_cf.c
arch/s390/kvm/intercept.c
arch/s390/kvm/kvm-s390.c
arch/s390/mm/fault.c
arch/s390/mm/pgalloc.c
arch/s390/mm/pgtable.c
arch/s390/net/bpf_jit.h
arch/s390/net/bpf_jit_comp.c
arch/score/include/asm/pgalloc.h
arch/sh/include/asm/pgalloc.h
arch/sh/mm/pgtable.c
arch/sparc/include/asm/head_64.h
arch/sparc/include/asm/pgalloc_64.h
arch/sparc/include/asm/ttable.h
arch/sparc/kernel/Makefile
arch/sparc/kernel/rtrap_64.S
arch/sparc/kernel/signal32.c
arch/sparc/kernel/signal_32.c
arch/sparc/kernel/signal_64.c
arch/sparc/kernel/sigutil_32.c
arch/sparc/kernel/sigutil_64.c
arch/sparc/kernel/urtt_fill.S [new file with mode: 0644]
arch/sparc/mm/init_64.c
arch/tile/include/asm/thread_info.h
arch/tile/kernel/process.c
arch/tile/mm/pgtable.c
arch/um/kernel/mem.c
arch/unicore32/include/asm/pgalloc.h
arch/x86/Kconfig
arch/x86/boot/Makefile
arch/x86/events/intel/rapl.c
arch/x86/events/intel/uncore_snbep.c
arch/x86/include/asm/intel-family.h [new file with mode: 0644]
arch/x86/include/asm/kprobes.h
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/msr.h
arch/x86/include/asm/pgalloc.h
arch/x86/include/asm/stacktrace.h
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/dumpstack.c
arch/x86/kernel/dumpstack_32.c
arch/x86/kernel/dumpstack_64.c
arch/x86/kernel/espfix_64.c
arch/x86/kernel/irq_32.c
arch/x86/kernel/kprobes/core.c
arch/x86/kernel/traps.c
arch/x86/kvm/cpuid.c
arch/x86/kvm/mmu.c
arch/x86/kvm/svm.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/mm/pgtable.c
arch/x86/platform/efi/efi_64.c
arch/x86/xen/mmu.c
arch/x86/xen/p2m.c
arch/xtensa/include/asm/pgalloc.h
block/blk-lib.c
block/blk-mq.c
crypto/asymmetric_keys/Kconfig
drivers/acpi/acpi_processor.c
drivers/acpi/acpi_video.c
drivers/acpi/acpica/exconfig.c
drivers/acpi/acpica/hwregs.c
drivers/acpi/acpica/nsparse.c
drivers/acpi/bus.c
drivers/acpi/ec.c
drivers/acpi/internal.h
drivers/acpi/processor_throttling.c
drivers/ata/libata-eh.c
drivers/atm/firestream.c
drivers/atm/iphase.c
drivers/base/Makefile
drivers/base/isa.c
drivers/base/module.c
drivers/base/power/opp/cpu.c
drivers/base/power/opp/of.c
drivers/base/power/opp/opp.h
drivers/block/aoe/aoecmd.c
drivers/block/nbd.c
drivers/block/xen-blkfront.c
drivers/char/ipmi/ipmi_msghandler.c
drivers/clk/Kconfig
drivers/clk/microchip/clk-pic32mzda.c
drivers/cpufreq/cpufreq.c
drivers/cpufreq/intel_pstate.c
drivers/cpufreq/pcc-cpufreq.c
drivers/crypto/ccp/ccp-crypto-aes-xts.c
drivers/crypto/omap-sham.c
drivers/devfreq/devfreq.c
drivers/devfreq/event/exynos-nocp.c
drivers/dma-buf/dma-buf.c
drivers/dma-buf/reservation.c
drivers/dma/at_xdmac.c
drivers/dma/mv_xor.c
drivers/edac/edac_mc.c
drivers/edac/sb_edac.c
drivers/extcon/extcon-palmas.c
drivers/firmware/efi/arm-init.c
drivers/gpio/Kconfig
drivers/gpio/gpio-104-dio-48e.c
drivers/gpio/gpio-104-idi-48.c
drivers/gpio/gpio-bcm-kona.c
drivers/gpio/gpio-lpc32xx.c
drivers/gpio/gpio-zynq.c
drivers/gpio/gpiolib-of.c
drivers/gpio/gpiolib.c
drivers/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c
drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
drivers/gpu/drm/amd/amdgpu/ci_dpm.c
drivers/gpu/drm/amd/amdgpu/cik.c
drivers/gpu/drm/amd/amdgpu/cik_sdma.c
drivers/gpu/drm/amd/amdgpu/fiji_dpm.c
drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
drivers/gpu/drm/amd/amdgpu/iceland_dpm.c
drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
drivers/gpu/drm/amd/amdgpu/tonga_dpm.c
drivers/gpu/drm/amd/amdgpu/vi.c
drivers/gpu/drm/amd/amdkfd/kfd_process.c
drivers/gpu/drm/amd/amdkfd/kfd_topology.c
drivers/gpu/drm/amd/include/amd_shared.h
drivers/gpu/drm/amd/include/atombios.h
drivers/gpu/drm/amd/include/cgs_common.h
drivers/gpu/drm/amd/powerplay/amd_powerplay.c
drivers/gpu/drm/amd/powerplay/eventmgr/eventmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c
drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr_ppt.h
drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.h
drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_powertune.c
drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_thermal.c
drivers/gpu/drm/amd/powerplay/hwmgr/pp_acpi.c
drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.c
drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.h
drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/tonga_pptable.h
drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.c
drivers/gpu/drm/amd/powerplay/inc/polaris10_ppsmc.h
drivers/gpu/drm/amd/powerplay/inc/pp_acpi.h
drivers/gpu/drm/amd/powerplay/inc/smu74.h
drivers/gpu/drm/amd/powerplay/inc/smu74_discrete.h
drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c
drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c
drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c
drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c
drivers/gpu/drm/arm/hdlcd_crtc.c
drivers/gpu/drm/arm/hdlcd_drv.c
drivers/gpu/drm/arm/hdlcd_drv.h
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
drivers/gpu/drm/drm_atomic.c
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_crtc_helper.c
drivers/gpu/drm/drm_dp_mst_topology.c
drivers/gpu/drm/drm_fb_cma_helper.c
drivers/gpu/drm/drm_gem_cma_helper.c
drivers/gpu/drm/drm_modes.c
drivers/gpu/drm/etnaviv/etnaviv_iommu.c
drivers/gpu/drm/exynos/exynos7_drm_decon.c
drivers/gpu/drm/exynos/exynos_dp.c
drivers/gpu/drm/exynos/exynos_drm_core.c
drivers/gpu/drm/exynos/exynos_drm_fimd.c
drivers/gpu/drm/exynos/exynos_drm_g2d.c
drivers/gpu/drm/exynos/exynos_drm_plane.c
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/intel_bios.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_dp_link_training.c
drivers/gpu/drm/i915/intel_dpll_mgr.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_dsi.c
drivers/gpu/drm/i915/intel_fbc.c
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_vbt_defs.h
drivers/gpu/drm/imx/imx-drm-core.c
drivers/gpu/drm/imx/imx-drm.h
drivers/gpu/drm/imx/imx-ldb.c
drivers/gpu/drm/imx/imx-tve.c
drivers/gpu/drm/imx/ipuv3-crtc.c
drivers/gpu/drm/imx/ipuv3-plane.c
drivers/gpu/drm/imx/parallel-display.c
drivers/gpu/drm/mediatek/mtk_dpi.c
drivers/gpu/drm/mediatek/mtk_dsi.c
drivers/gpu/drm/mgag200/mgag200_mode.c
drivers/gpu/drm/msm/adreno/adreno_gpu.c
drivers/gpu/drm/msm/msm_fbdev.c
drivers/gpu/drm/msm/msm_gem.c
drivers/gpu/drm/msm/msm_gem_submit.c
drivers/gpu/drm/msm/msm_rd.c
drivers/gpu/drm/msm/msm_ringbuffer.c
drivers/gpu/drm/nouveau/include/nvkm/core/device.h
drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/disp.h
drivers/gpu/drm/nouveau/nouveau_fbcon.c
drivers/gpu/drm/nouveau/nv04_fbcon.c
drivers/gpu/drm/nouveau/nv50_fbcon.c
drivers/gpu/drm/nouveau/nvc0_fbcon.c
drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild
drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h
drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c
drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
drivers/gpu/drm/nouveau/nvkm/subdev/bios/disp.c
drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/base.c
drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm107.c
drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm200.c
drivers/gpu/drm/omapdrm/Kconfig
drivers/gpu/drm/omapdrm/displays/connector-hdmi.c
drivers/gpu/drm/omapdrm/displays/encoder-opa362.c
drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c
drivers/gpu/drm/omapdrm/displays/panel-dpi.c
drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c
drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c
drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c
drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c
drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c
drivers/gpu/drm/omapdrm/dss/dsi.c
drivers/gpu/drm/omapdrm/dss/dss.c
drivers/gpu/drm/omapdrm/dss/hdmi4.c
drivers/gpu/drm/omapdrm/dss/hdmi4_core.c
drivers/gpu/drm/omapdrm/dss/hdmi5.c
drivers/gpu/drm/omapdrm/dss/hdmi5_core.c
drivers/gpu/drm/omapdrm/dss/hdmi_phy.c
drivers/gpu/drm/omapdrm/dss/hdmi_pll.c
drivers/gpu/drm/omapdrm/dss/hdmi_wp.c
drivers/gpu/drm/omapdrm/omap_debugfs.c
drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
drivers/gpu/drm/omapdrm/omap_fb.c
drivers/gpu/drm/omapdrm/omap_gem.c
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/sti/sti_crtc.c
drivers/gpu/drm/sun4i/Kconfig
drivers/gpu/drm/sun4i/sun4i_backend.c
drivers/gpu/drm/sun4i/sun4i_dotclock.c
drivers/gpu/drm/sun4i/sun4i_drv.c
drivers/gpu/drm/sun4i/sun4i_rgb.c
drivers/gpu/drm/sun4i/sun4i_tcon.c
drivers/gpu/drm/vc4/vc4_crtc.c
drivers/gpu/drm/vc4/vc4_drv.c
drivers/gpu/drm/vc4/vc4_kms.c
drivers/gpu/drm/vc4/vc4_regs.h
drivers/gpu/drm/vmwgfx/vmwgfx_msg.c
drivers/hid/hid-elo.c
drivers/hid/hid-multitouch.c
drivers/hid/usbhid/hiddev.c
drivers/hwmon/dell-smm-hwmon.c
drivers/hwmon/fam15h_power.c
drivers/hwmon/lm90.c
drivers/hwtracing/coresight/coresight-tmc-etr.c
drivers/hwtracing/coresight/coresight.c
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-octeon.c
drivers/i2c/muxes/i2c-mux-reg.c
drivers/iio/accel/st_accel_buffer.c
drivers/iio/accel/st_accel_core.c
drivers/iio/common/st_sensors/st_sensors_buffer.c
drivers/iio/common/st_sensors/st_sensors_core.c
drivers/iio/common/st_sensors/st_sensors_trigger.c
drivers/iio/dac/Kconfig
drivers/iio/dac/ad5592r-base.c
drivers/iio/gyro/st_gyro_buffer.c
drivers/iio/gyro/st_gyro_core.c
drivers/iio/humidity/am2315.c
drivers/iio/humidity/hdc100x.c
drivers/iio/imu/bmi160/bmi160_core.c
drivers/iio/industrialio-trigger.c
drivers/iio/light/apds9960.c
drivers/iio/light/bh1780.c
drivers/iio/light/max44000.c
drivers/iio/magnetometer/st_magn_buffer.c
drivers/iio/magnetometer/st_magn_core.c
drivers/iio/pressure/bmp280.c
drivers/iio/pressure/st_pressure_buffer.c
drivers/iio/pressure/st_pressure_core.c
drivers/iio/proximity/as3935.c
drivers/infiniband/core/cache.c
drivers/infiniband/core/cm.c
drivers/infiniband/core/cma.c
drivers/infiniband/core/device.c
drivers/infiniband/core/iwpm_msg.c
drivers/infiniband/core/mad.c
drivers/infiniband/core/sysfs.c
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/core/verbs.c
drivers/infiniband/hw/hfi1/affinity.c
drivers/infiniband/hw/hfi1/chip.c
drivers/infiniband/hw/hfi1/file_ops.c
drivers/infiniband/hw/hfi1/init.c
drivers/infiniband/hw/hfi1/mad.c
drivers/infiniband/hw/hfi1/mad.h
drivers/infiniband/hw/hfi1/pio.c
drivers/infiniband/hw/hfi1/qsfp.c
drivers/infiniband/hw/hfi1/trace.c
drivers/infiniband/hw/hfi1/user_sdma.c
drivers/infiniband/hw/hfi1/verbs_txreq.c
drivers/infiniband/hw/hfi1/verbs_txreq.h
drivers/infiniband/hw/i40iw/i40iw.h
drivers/infiniband/hw/i40iw/i40iw_verbs.c
drivers/infiniband/hw/mlx4/ah.c
drivers/infiniband/hw/mlx4/mad.c
drivers/infiniband/hw/mlx4/main.c
drivers/infiniband/hw/mlx4/mlx4_ib.h
drivers/infiniband/hw/mlx4/mr.c
drivers/infiniband/hw/mlx4/qp.c
drivers/infiniband/hw/mlx5/cq.c
drivers/infiniband/hw/mlx5/mad.c
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/mlx5/qp.c
drivers/infiniband/hw/qib/qib_file_ops.c
drivers/infiniband/hw/usnic/usnic_uiom.c
drivers/infiniband/sw/rdmavt/qp.c
drivers/infiniband/sw/rdmavt/vt.c
drivers/infiniband/ulp/ipoib/ipoib.h
drivers/infiniband/ulp/ipoib/ipoib_cm.c
drivers/infiniband/ulp/ipoib/ipoib_ib.c
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/infiniband/ulp/ipoib/ipoib_multicast.c
drivers/infiniband/ulp/ipoib/ipoib_vlan.c
drivers/infiniband/ulp/srp/ib_srp.c
drivers/infiniband/ulp/srpt/ib_srpt.c
drivers/infiniband/ulp/srpt/ib_srpt.h
drivers/iommu/arm-smmu-v3.c
drivers/iommu/intel-iommu.c
drivers/iommu/rockchip-iommu.c
drivers/irqchip/irq-gic-v3-its.c
drivers/irqchip/irq-gic-v3.c
drivers/irqchip/irq-mips-gic.c
drivers/irqchip/irq-pic32-evic.c
drivers/leds/led-core.c
drivers/leds/trigger/ledtrig-heartbeat.c
drivers/mcb/mcb-core.c
drivers/media/usb/uvc/uvc_v4l2.c
drivers/media/v4l2-core/v4l2-mc.c
drivers/memory/omap-gpmc.c
drivers/misc/mei/client.c
drivers/mmc/core/mmc.c
drivers/mmc/host/sunxi-mmc.c
drivers/mtd/ubi/build.c
drivers/mtd/ubi/eba.c
drivers/mtd/ubi/kapi.c
drivers/net/ethernet/arc/emac_mdio.c
drivers/net/ethernet/atheros/alx/alx.h
drivers/net/ethernet/atheros/alx/main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/chelsio/cxgb4/t4_pci_id_tbl.h
drivers/net/ethernet/ethoc.c
drivers/net/ethernet/ezchip/nps_enet.c
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/freescale/gianfar.c
drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
drivers/net/ethernet/marvell/mvneta_bm.c
drivers/net/ethernet/mediatek/mtk_eth_soc.c
drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
drivers/net/ethernet/mellanox/mlx4/en_netdev.c
drivers/net/ethernet/mellanox/mlx4/en_port.c
drivers/net/ethernet/mellanox/mlx4/en_tx.c
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
drivers/net/ethernet/mellanox/mlx5/core/qp.c
drivers/net/ethernet/mellanox/mlx5/core/vport.c
drivers/net/ethernet/mellanox/mlxsw/spectrum.c
drivers/net/ethernet/mellanox/mlxsw/spectrum.h
drivers/net/ethernet/qlogic/qed/qed_dcbx.c
drivers/net/ethernet/qlogic/qed/qed_dev.c
drivers/net/ethernet/qlogic/qed/qed_main.c
drivers/net/ethernet/qlogic/qed/qed_sriov.h
drivers/net/ethernet/qlogic/qede/qede_ethtool.c
drivers/net/ethernet/qlogic/qede/qede_main.c
drivers/net/ethernet/qlogic/qlge/qlge_main.c
drivers/net/ethernet/sfc/ef10.c
drivers/net/ethernet/sfc/efx.c
drivers/net/ethernet/sfc/mcdi_port.c
drivers/net/ethernet/sfc/net_driver.h
drivers/net/ethernet/sfc/rx.c
drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
drivers/net/ethernet/ti/cpsw.c
drivers/net/team/team.c
drivers/net/usb/pegasus.c
drivers/net/usb/smsc95xx.c
drivers/net/virtio_net.c
drivers/net/vmxnet3/vmxnet3_drv.c
drivers/net/vmxnet3/vmxnet3_int.h
drivers/net/vxlan.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/realtek/rtlwifi/core.c
drivers/nvme/host/pci.c
drivers/of/fdt.c
drivers/of/irq.c
drivers/of/of_reserved_mem.c
drivers/pci/vc.c
drivers/perf/arm_pmu.c
drivers/phy/phy-exynos-mipi-video.c
drivers/phy/phy-ti-pipe3.c
drivers/phy/phy-twl4030-usb.c
drivers/pinctrl/mediatek/pinctrl-mtk-common.c
drivers/pinctrl/nomadik/pinctrl-nomadik.c
drivers/platform/x86/Kconfig
drivers/platform/x86/ideapad-laptop.c
drivers/platform/x86/thinkpad_acpi.c
drivers/ptp/ptp_chardev.c
drivers/pwm/core.c
drivers/pwm/pwm-atmel-hlcdc.c
drivers/pwm/sysfs.c
drivers/regulator/qcom_smd-regulator.c
drivers/regulator/tps51632-regulator.c
drivers/scsi/53c700.c
drivers/scsi/aacraid/aacraid.h
drivers/scsi/aacraid/linit.c
drivers/scsi/mpt3sas/mpt3sas_scsih.c
drivers/scsi/scsi_devinfo.c
drivers/scsi/scsi_error.c
drivers/scsi/scsi_lib.c
drivers/scsi/sd.c
drivers/scsi/sd.h
drivers/spi/spi-sun4i.c
drivers/spi/spi-sun6i.c
drivers/spi/spi-ti-qspi.c
drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c
drivers/staging/rtl8188eu/core/rtw_efuse.c
drivers/staging/rtl8188eu/hal/usb_halinit.c
drivers/thermal/cpu_cooling.c
drivers/thermal/int340x_thermal/int3406_thermal.c
drivers/tty/Kconfig
drivers/tty/pty.c
drivers/usb/core/quirks.c
drivers/usb/dwc2/core.h
drivers/usb/dwc2/gadget.c
drivers/usb/dwc3/core.h
drivers/usb/dwc3/dwc3-exynos.c
drivers/usb/dwc3/dwc3-st.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/composite.c
drivers/usb/gadget/configfs.c
drivers/usb/gadget/function/f_fs.c
drivers/usb/gadget/function/f_printer.c
drivers/usb/gadget/function/f_tcm.c
drivers/usb/gadget/function/f_uac2.c
drivers/usb/gadget/function/storage_common.c
drivers/usb/gadget/legacy/inode.c
drivers/usb/gadget/udc/udc-core.c
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-hub.c
drivers/usb/host/ehci-msm.c
drivers/usb/host/ehci-tegra.c
drivers/usb/host/ohci-q.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-plat.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_core.h
drivers/usb/musb/musb_gadget.c
drivers/usb/musb/musb_host.c
drivers/usb/musb/omap2430.c
drivers/usb/musb/sunxi.c
drivers/usb/phy/phy-twl6030-usb.c
drivers/usb/serial/mos7720.c
drivers/usb/storage/uas.c
drivers/usb/usbip/vhci_hcd.c
drivers/vfio/pci/vfio_pci_config.c
drivers/vfio/pci/vfio_pci_intrs.c
drivers/vfio/vfio_iommu_type1.c
drivers/video/fbdev/omap2/omapfb/dss/hdmi5_core.c
drivers/watchdog/Kconfig
drivers/xen/balloon.c
drivers/xen/xen-pciback/conf_space.c
drivers/xen/xen-pciback/conf_space_header.c
fs/autofs4/autofs_i.h
fs/autofs4/expire.c
fs/autofs4/root.c
fs/autofs4/waitq.c
fs/binfmt_elf.c
fs/binfmt_elf_fdpic.c
fs/btrfs/check-integrity.c
fs/btrfs/ctree.c
fs/btrfs/ctree.h
fs/btrfs/delayed-inode.c
fs/btrfs/delayed-inode.h
fs/btrfs/disk-io.c
fs/btrfs/disk-io.h
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/extent_io.h
fs/btrfs/file.c
fs/btrfs/free-space-cache.c
fs/btrfs/hash.c
fs/btrfs/hash.h
fs/btrfs/inode.c
fs/btrfs/ordered-data.c
fs/btrfs/ordered-data.h
fs/btrfs/reada.c
fs/btrfs/scrub.c
fs/btrfs/super.c
fs/btrfs/tests/btrfs-tests.c
fs/btrfs/tests/btrfs-tests.h
fs/btrfs/tests/extent-buffer-tests.c
fs/btrfs/tests/extent-io-tests.c
fs/btrfs/tests/free-space-tests.c
fs/btrfs/tests/free-space-tree-tests.c
fs/btrfs/tests/inode-tests.c
fs/btrfs/tests/qgroup-tests.c
fs/btrfs/transaction.c
fs/btrfs/transaction.h
fs/btrfs/tree-log.c
fs/btrfs/volumes.c
fs/cachefiles/interface.c
fs/ceph/addr.c
fs/ceph/cache.c
fs/ceph/cache.h
fs/ceph/caps.c
fs/ceph/file.c
fs/ceph/super.h
fs/coredump.c
fs/dcache.c
fs/debugfs/file.c
fs/devpts/inode.c
fs/ecryptfs/kthread.c
fs/fscache/page.c
fs/internal.h
fs/jbd2/journal.c
fs/libfs.c
fs/namei.c
fs/namespace.c
fs/nfsd/blocklayout.c
fs/nfsd/nfs2acl.c
fs/nfsd/nfs3acl.c
fs/nfsd/nfs4acl.c
fs/nfsd/nfs4callback.c
fs/nfsd/nfs4state.c
fs/nfsd/state.h
fs/nilfs2/the_nilfs.c
fs/ocfs2/Makefile
fs/ocfs2/buffer_head_io.c
fs/overlayfs/dir.c
fs/overlayfs/inode.c
fs/posix_acl.c
fs/proc/root.c
fs/reiserfs/super.c
fs/ubifs/file.c
fs/udf/partition.c
fs/udf/super.c
fs/udf/udf_sb.h
include/acpi/video.h
include/asm-generic/qspinlock.h
include/linux/binfmts.h
include/linux/ceph/osd_client.h
include/linux/ceph/osdmap.h
include/linux/clk-provider.h
include/linux/cpuidle.h
include/linux/dcache.h
include/linux/devpts_fs.h
include/linux/dma-buf.h
include/linux/efi.h
include/linux/fence.h
include/linux/fscache-cache.h
include/linux/iio/common/st_sensors.h
include/linux/init_task.h
include/linux/irqchip/arm-gic-v3.h
include/linux/isa.h
include/linux/jump_label.h
include/linux/kasan.h
include/linux/leds.h
include/linux/mlx5/device.h
include/linux/mlx5/mlx5_ifc.h
include/linux/mlx5/qp.h
include/linux/mlx5/vport.h
include/linux/mm.h
include/linux/namei.h
include/linux/of.h
include/linux/of_pci.h
include/linux/of_reserved_mem.h
include/linux/page_idle.h
include/linux/pwm.h
include/linux/reservation.h
include/linux/sched.h
include/linux/sctp.h
include/linux/seqlock.h
include/linux/sunrpc/clnt.h
include/linux/sunrpc/svc_xprt.h
include/linux/sunrpc/xprt.h
include/linux/thermal.h
include/linux/timekeeping.h
include/linux/usb/gadget.h
include/linux/usb/musb.h
include/media/v4l2-mc.h
include/net/compat.h
include/net/ip6_tunnel.h
include/net/ip_vs.h
include/net/netfilter/nf_queue.h
include/net/netns/netfilter.h
include/net/pkt_cls.h
include/net/pkt_sched.h
include/net/sch_generic.h
include/rdma/ib_verbs.h
include/rdma/rdma_vt.h
include/uapi/linux/btrfs.h
include/uapi/linux/ethtool.h
include/uapi/linux/gtp.h
include/uapi/linux/pkt_cls.h
include/uapi/sound/Kbuild
init/main.c
kernel/bpf/inode.c
kernel/events/core.c
kernel/fork.c
kernel/futex.c
kernel/irq/ipi.c
kernel/jump_label.c
kernel/kcov.c
kernel/locking/mutex-debug.c
kernel/locking/mutex-debug.h
kernel/locking/mutex.c
kernel/locking/mutex.h
kernel/locking/qspinlock.c
kernel/power/process.c
kernel/relay.c
kernel/sched/core.c
kernel/sched/debug.c
kernel/sched/fair.c
kernel/sched/idle.c
kernel/sched/sched.h
kernel/sched/stats.h
kernel/time/hrtimer.c
kernel/trace/bpf_trace.c
kernel/trace/trace_printk.c
lib/Kconfig.debug
lib/Makefile
lib/test_uuid.c [new file with mode: 0644]
lib/uuid.c
mm/compaction.c
mm/fadvise.c
mm/filemap.c
mm/hugetlb.c
mm/internal.h
mm/kasan/kasan.c
mm/kmemleak.c
mm/memcontrol.c
mm/memory.c
mm/mempool.c
mm/migrate.c
mm/oom_kill.c
mm/page-writeback.c
mm/page_alloc.c
mm/page_owner.c
mm/page_poison.c
mm/percpu.c
mm/shmem.c
mm/swap.c
mm/swap_state.c
mm/vmalloc.c
mm/vmstat.c
mm/z3fold.c
net/8021q/vlan.c
net/8021q/vlan.h
net/8021q/vlan_dev.c
net/atm/signaling.c
net/atm/svc.c
net/bridge/br_fdb.c
net/ceph/osd_client.c
net/ceph/osdmap.c
net/compat.c
net/core/gen_stats.c
net/core/hwbm.c
net/core/net-sysfs.c
net/core/pktgen.c
net/ieee802154/nl802154.c
net/ipv4/af_inet.c
net/ipv4/sysctl_net_ipv4.c
net/ipv4/udp.c
net/ipv6/Kconfig
net/ipv6/Makefile
net/ipv6/fou6.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_output.c
net/ipv6/netfilter/nf_dup_ipv6.c
net/ipv6/tcp_ipv6.c
net/ipv6/udp.c
net/l2tp/l2tp_core.c
net/l2tp/l2tp_ip6.c
net/lapb/lapb_in.c
net/lapb/lapb_out.c
net/lapb/lapb_subr.c
net/mac80211/mesh.c
net/mac80211/sta_info.h
net/netfilter/ipvs/ip_vs_conn.c
net/netfilter/ipvs/ip_vs_core.c
net/netfilter/nf_conntrack_ftp.c
net/netfilter/nf_conntrack_helper.c
net/netfilter/nf_conntrack_irc.c
net/netfilter/nf_conntrack_sane.c
net/netfilter/nf_conntrack_sip.c
net/netfilter/nf_conntrack_standalone.c
net/netfilter/nf_conntrack_tftp.c
net/netfilter/nf_queue.c
net/netfilter/nf_tables_api.c
net/netfilter/nfnetlink_queue.c
net/netfilter/x_tables.c
net/openvswitch/actions.c
net/packet/af_packet.c
net/rds/rds.h
net/rds/recv.c
net/rds/send.c
net/rds/tcp.c
net/rds/tcp.h
net/rds/tcp_connect.c
net/rds/tcp_listen.c
net/rds/threads.c
net/rxrpc/rxkad.c
net/sched/act_police.c
net/sched/cls_flower.c
net/sched/cls_u32.c
net/sched/sch_api.c
net/sched/sch_drr.c
net/sched/sch_fq_codel.c
net/sched/sch_generic.c
net/sched/sch_hfsc.c
net/sched/sch_htb.c
net/sched/sch_ingress.c
net/sched/sch_prio.c
net/sched/sch_qfq.c
net/sched/sch_red.c
net/sched/sch_tbf.c
net/sctp/sctp_diag.c
net/sctp/socket.c
net/sunrpc/clnt.c
net/sunrpc/svc_xprt.c
net/sunrpc/xprtsock.c
net/tipc/netlink_compat.c
net/unix/af_unix.c
net/wireless/core.c
net/wireless/wext-core.c
scripts/checkpatch.pl
scripts/mod/file2alias.c
security/keys/compat.c
security/keys/dh.c
security/keys/internal.h
security/keys/key.c
security/keys/keyctl.c
sound/drivers/dummy.c
sound/hda/hdac_regmap.c
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_tegra.c
sound/pci/hda/patch_realtek.c
tools/perf/util/data-convert-bt.c
tools/perf/util/event.c
tools/perf/util/symbol.c
tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-mod.tc
tools/testing/selftests/ftrace/test.d/trigger/trigger-hist.tc
tools/testing/selftests/ftrace/test.d/trigger/trigger-multihist.tc
tools/testing/selftests/net/reuseport_bpf.c
tools/testing/selftests/vm/compaction_test.c
tools/virtio/ringtest/Makefile
tools/virtio/ringtest/README
tools/virtio/ringtest/noring.c [new file with mode: 0644]
tools/virtio/ringtest/run-on-all.sh
tools/vm/slabinfo.c
virt/kvm/arm/hyp/vgic-v2-sr.c
virt/kvm/arm/vgic/vgic-mmio.c
virt/kvm/arm/vgic/vgic-v2.c
virt/kvm/arm/vgic/vgic-v3.c
virt/kvm/irqchip.c
virt/kvm/kvm_main.c

index 08b8042..52489f5 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -21,6 +21,7 @@ Andrey Ryabinin <ryabinin.a.a@gmail.com> <a.ryabinin@samsung.com>
 Andrew Morton <akpm@linux-foundation.org>
 Andrew Vasquez <andrew.vasquez@qlogic.com>
 Andy Adamson <andros@citi.umich.edu>
+Antoine Tenart <antoine.tenart@free-electrons.com>
 Antonio Ospite <ao2@ao2.it> <ao2@amarulasolutions.com>
 Archit Taneja <archit@ti.com>
 Arnaud Patard <arnaud.patard@rtp-net.org>
@@ -30,6 +31,9 @@ Axel Lin <axel.lin@gmail.com>
 Ben Gardner <bgardner@wabtec.com>
 Ben M Cahill <ben.m.cahill@intel.com>
 Björn Steinbrink <B.Steinbrink@gmx.de>
+Boris Brezillon <boris.brezillon@free-electrons.com>
+Boris Brezillon <boris.brezillon@free-electrons.com> <b.brezillon.dev@gmail.com>
+Boris Brezillon <boris.brezillon@free-electrons.com> <b.brezillon@overkiz.com>
 Brian Avery <b.avery@hp.com>
 Brian King <brking@us.ibm.com>
 Christoph Hellwig <hch@lst.de>
@@ -89,6 +93,7 @@ Leonid I Ananiev <leonid.i.ananiev@intel.com>
 Linas Vepstas <linas@austin.ibm.com>
 Mark Brown <broonie@sirena.org.uk>
 Matthieu CASTET <castet.matthieu@free.fr>
+Mauro Carvalho Chehab <mchehab@kernel.org> <maurochehab@gmail.com> <mchehab@infradead.org> <mchehab@redhat.com> <m.chehab@samsung.com> <mchehab@osg.samsung.com> <mchehab@s-opensource.com>
 Mayuresh Janorkar <mayur@ti.com>
 Michael Buesch <m@bues.ch>
 Michel Dänzer <michel@tungstengraphics.com>
@@ -122,6 +127,7 @@ Santosh Shilimkar <santosh.shilimkar@oracle.org>
 Sascha Hauer <s.hauer@pengutronix.de>
 S.ÇaÄŸlar Onur <caglar@pardus.org.tr>
 Shiraz Hashim <shiraz.linux.kernel@gmail.com> <shiraz.hashim@st.com>
+Shuah Khan <shuah@kernel.org> <shuahkhan@gmail.com> <shuah.khan@hp.com> <shuahkh@osg.samsung.com> <shuah.kh@samsung.com>
 Simon Kelley <simon@thekelleys.org.uk>
 Stéphane Witzmann <stephane.witzmann@ubpmes.univ-bpclermont.fr>
 Stephen Hemminger <shemminger@osdl.org>
diff --git a/CREDITS b/CREDITS
index 0f0bf22..2a3fbcd 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -649,6 +649,7 @@ D: Configure, Menuconfig, xconfig
 
 N: Mauro Carvalho Chehab
 E: m.chehab@samsung.org
+E: mchehab@osg.samsung.com
 E: mchehab@infradead.org
 D: Media subsystem (V4L/DVB) drivers and core
 D: EDAC drivers and EDAC 3.0 core rework
index 2f4a005..1ba0d0f 100644 (file)
@@ -1,6 +1,6 @@
 What:          /config/usb-gadget/gadget/functions/uvc.name
 Date:          Dec 2014
-KernelVersion: 3.20
+KernelVersion: 4.0
 Description:   UVC function directory
 
                streaming_maxburst      - 0..15 (ss only)
@@ -9,37 +9,37 @@ Description:  UVC function directory
 
 What:          /config/usb-gadget/gadget/functions/uvc.name/control
 Date:          Dec 2014
-KernelVersion: 3.20
+KernelVersion: 4.0
 Description:   Control descriptors
 
 What:          /config/usb-gadget/gadget/functions/uvc.name/control/class
 Date:          Dec 2014
-KernelVersion: 3.20
+KernelVersion: 4.0
 Description:   Class descriptors
 
 What:          /config/usb-gadget/gadget/functions/uvc.name/control/class/ss
 Date:          Dec 2014
-KernelVersion: 3.20
+KernelVersion: 4.0
 Description:   Super speed control class descriptors
 
 What:          /config/usb-gadget/gadget/functions/uvc.name/control/class/fs
 Date:          Dec 2014
-KernelVersion: 3.20
+KernelVersion: 4.0
 Description:   Full speed control class descriptors
 
 What:          /config/usb-gadget/gadget/functions/uvc.name/control/terminal
 Date:          Dec 2014
-KernelVersion: 3.20
+KernelVersion: 4.0
 Description:   Terminal descriptors
 
 What:          /config/usb-gadget/gadget/functions/uvc.name/control/terminal/output
 Date:          Dec 2014
-KernelVersion: 3.20
+KernelVersion: 4.0
 Description:   Output terminal descriptors
 
 What:          /config/usb-gadget/gadget/functions/uvc.name/control/terminal/output/default
 Date:          Dec 2014
-KernelVersion: 3.20
+KernelVersion: 4.0
 Description:   Default output terminal descriptors
 
                All attributes read only:
@@ -53,12 +53,12 @@ Description:        Default output terminal descriptors
 
 What:          /config/usb-gadget/gadget/functions/uvc.name/control/terminal/camera
 Date:          Dec 2014
-KernelVersion: 3.20
+KernelVersion: 4.0
 Description:   Camera terminal descriptors
 
 What:          /config/usb-gadget/gadget/functions/uvc.name/control/terminal/camera/default
 Date:          Dec 2014
-KernelVersion: 3.20
+KernelVersion: 4.0
 Description:   Default camera terminal descriptors
 
                All attributes read only:
@@ -75,12 +75,12 @@ Description:        Default camera terminal descriptors
 
 What:          /config/usb-gadget/gadget/functions/uvc.name/control/processing
 Date:          Dec 2014
-KernelVersion: 3.20
+KernelVersion: 4.0
 Description:   Processing unit descriptors
 
 What:          /config/usb-gadget/gadget/functions/uvc.name/control/processing/default
 Date:          Dec 2014
-KernelVersion: 3.20
+KernelVersion: 4.0
 Description:   Default processing unit descriptors
 
                All attributes read only:
@@ -94,49 +94,49 @@ Description:        Default processing unit descriptors
 
 What:          /config/usb-gadget/gadget/functions/uvc.name/control/header
 Date:          Dec 2014
-KernelVersion: 3.20
+KernelVersion: 4.0
 Description:   Control header descriptors
 
 What:          /config/usb-gadget/gadget/functions/uvc.name/control/header/name
 Date:          Dec 2014
-KernelVersion: 3.20
+KernelVersion: 4.0
 Description:   Specific control header descriptors
 
 dwClockFrequency
 bcdUVC
 What:          /config/usb-gadget/gadget/functions/uvc.name/streaming
 Date:          Dec 2014
-KernelVersion: 3.20
+KernelVersion: 4.0
 Description:   Streaming descriptors
 
 What:          /config/usb-gadget/gadget/functions/uvc.name/streaming/class
 Date:          Dec 2014
-KernelVersion: 3.20
+KernelVersion: 4.0
 Description:   Streaming class descriptors
 
 What:          /config/usb-gadget/gadget/functions/uvc.name/streaming/class/ss
 Date:          Dec 2014
-KernelVersion: 3.20
+KernelVersion: 4.0
 Description:   Super speed streaming class descriptors
 
 What:          /config/usb-gadget/gadget/functions/uvc.name/streaming/class/hs
 Date:          Dec 2014
-KernelVersion: 3.20
+KernelVersion: 4.0
 Description:   High speed streaming class descriptors
 
 What:          /config/usb-gadget/gadget/functions/uvc.name/streaming/class/fs
 Date:          Dec 2014
-KernelVersion: 3.20
+KernelVersion: 4.0
 Description:   Full speed streaming class descriptors
 
 What:          /config/usb-gadget/gadget/functions/uvc.name/streaming/color_matching
 Date:          Dec 2014
-KernelVersion: 3.20
+KernelVersion: 4.0
 Description:   Color matching descriptors
 
 What:          /config/usb-gadget/gadget/functions/uvc.name/streaming/color_matching/default
 Date:          Dec 2014
-KernelVersion: 3.20
+KernelVersion: 4.0
 Description:   Default color matching descriptors
 
                All attributes read only:
@@ -150,12 +150,12 @@ Description:      Default color matching descriptors
 
 What:          /config/usb-gadget/gadget/functions/uvc.name/streaming/mjpeg
 Date:          Dec 2014
-KernelVersion: 3.20
+KernelVersion: 4.0
 Description:   MJPEG format descriptors
 
 What:          /config/usb-gadget/gadget/functions/uvc.name/streaming/mjpeg/name
 Date:          Dec 2014
-KernelVersion: 3.20
+KernelVersion: 4.0
 Description:   Specific MJPEG format descriptors
 
                All attributes read only,
@@ -174,7 +174,7 @@ Description:        Specific MJPEG format descriptors
 
 What:          /config/usb-gadget/gadget/functions/uvc.name/streaming/mjpeg/name/name
 Date:          Dec 2014
-KernelVersion: 3.20
+KernelVersion: 4.0
 Description:   Specific MJPEG frame descriptors
 
                dwFrameInterval         - indicates how frame interval can be
@@ -196,12 +196,12 @@ Description:      Specific MJPEG frame descriptors
 
 What:          /config/usb-gadget/gadget/functions/uvc.name/streaming/uncompressed
 Date:          Dec 2014
-KernelVersion: 3.20
+KernelVersion: 4.0
 Description:   Uncompressed format descriptors
 
 What:          /config/usb-gadget/gadget/functions/uvc.name/streaming/uncompressed/name
 Date:          Dec 2014
-KernelVersion: 3.20
+KernelVersion: 4.0
 Description:   Specific uncompressed format descriptors
 
                bmaControls             - this format's data for bmaControls in
@@ -221,7 +221,7 @@ Description:        Specific uncompressed format descriptors
 
 What:          /config/usb-gadget/gadget/functions/uvc.name/streaming/uncompressed/name/name
 Date:          Dec 2014
-KernelVersion: 3.20
+KernelVersion: 4.0
 Description:   Specific uncompressed frame descriptors
 
                dwFrameInterval         - indicates how frame interval can be
@@ -243,12 +243,12 @@ Description:      Specific uncompressed frame descriptors
 
 What:          /config/usb-gadget/gadget/functions/uvc.name/streaming/header
 Date:          Dec 2014
-KernelVersion: 3.20
+KernelVersion: 4.0
 Description:   Streaming header descriptors
 
 What:          /config/usb-gadget/gadget/functions/uvc.name/streaming/header/name
 Date:          Dec 2014
-KernelVersion: 3.20
+KernelVersion: 4.0
 Description:   Specific streaming header descriptors
 
                All attributes read only:
index 6708c5e..33e96f7 100644 (file)
@@ -1,4 +1,4 @@
-What           /sys/bus/iio/devices/iio:deviceX/in_proximity_raw
+What           /sys/bus/iio/devices/iio:deviceX/in_proximity_input
 Date:          March 2014
 KernelVersion: 3.15
 Contact:       Matt Ranostay <mranostay@gmail.com>
index de79efd..8c68768 100644 (file)
@@ -128,16 +128,44 @@ X!Edrivers/base/interface.c
 !Edrivers/base/platform.c
 !Edrivers/base/bus.c
      </sect1>
-     <sect1><title>Device Drivers DMA Management</title>
+     <sect1>
+       <title>Buffer Sharing and Synchronization</title>
+       <para>
+         The dma-buf subsystem provides the framework for sharing buffers
+         for hardware (DMA) access across multiple device drivers and
+         subsystems, and for synchronizing asynchronous hardware access.
+       </para>
+       <para>
+         This is used, for example, by drm "prime" multi-GPU support, but
+         is of course not limited to GPU use cases.
+       </para>
+       <para>
+         The three main components of this are: (1) dma-buf, representing
+         a sg_table and exposed to userspace as a file descriptor to allow
+         passing between devices, (2) fence, which provides a mechanism
+         to signal when one device as finished access, and (3) reservation,
+         which manages the shared or exclusive fence(s) associated with
+         the buffer.
+       </para>
+       <sect2><title>dma-buf</title>
 !Edrivers/dma-buf/dma-buf.c
+!Iinclude/linux/dma-buf.h
+       </sect2>
+       <sect2><title>reservation</title>
+!Pdrivers/dma-buf/reservation.c Reservation Object Overview
+!Edrivers/dma-buf/reservation.c
+!Iinclude/linux/reservation.h
+       </sect2>
+       <sect2><title>fence</title>
 !Edrivers/dma-buf/fence.c
-!Edrivers/dma-buf/seqno-fence.c
 !Iinclude/linux/fence.h
+!Edrivers/dma-buf/seqno-fence.c
 !Iinclude/linux/seqno-fence.h
-!Edrivers/dma-buf/reservation.c
-!Iinclude/linux/reservation.h
 !Edrivers/dma-buf/sync_file.c
 !Iinclude/linux/sync_file.h
+       </sect2>
+     </sect1>
+     <sect1><title>Device Drivers DMA Management</title>
 !Edrivers/base/dma-coherent.c
 !Edrivers/base/dma-mapping.c
      </sect1>
index c6938e5..4da60b4 100644 (file)
@@ -56,6 +56,7 @@ stable kernels.
 | ARM            | MMU-500         | #841119,#826419 | N/A                     |
 |                |                 |                 |                         |
 | Cavium         | ThunderX ITS    | #22375, #24313  | CAVIUM_ERRATUM_22375    |
+| Cavium         | ThunderX ITS    | #23144          | CAVIUM_ERRATUM_23144    |
 | Cavium         | ThunderX GICv3  | #23154          | CAVIUM_ERRATUM_23154    |
 | Cavium         | ThunderX Core   | #27456          | CAVIUM_ERRATUM_27456    |
 | Cavium         | ThunderX SMMUv2 | #27704          | N/A                    |
index 0a175d9..a407462 100644 (file)
@@ -62,6 +62,7 @@ Required properties:
    display-timings are used instead.
 
 Optional properties (required if display-timings are used):
+ - ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
  - display-timings : A node that describes the display timings as defined in
    Documentation/devicetree/bindings/display/display-timing.txt.
  - fsl,data-mapping : should be "spwg" or "jeida"
index 9bcd5e8..02af0d9 100644 (file)
@@ -7,6 +7,7 @@ Required properties:
        - "ti,ina220" for ina220
        - "ti,ina226" for ina226
        - "ti,ina230" for ina230
+       - "ti,ina231" for ina231
 - reg: I2C address
 
 Optional properties:
index bfeabb8..71191ff 100644 (file)
@@ -44,8 +44,8 @@ Required properties:
 - our-claim-gpio: The GPIO that we use to claim the bus.
 - their-claim-gpios: The GPIOs that the other sides use to claim the bus.
   Note that some implementations may only support a single other master.
-- Standard I2C mux properties. See mux.txt in this directory.
-- Single I2C child bus node at reg 0. See mux.txt in this directory.
+- Standard I2C mux properties. See i2c-mux.txt in this directory.
+- Single I2C child bus node at reg 0. See i2c-mux.txt in this directory.
 
 Optional properties:
 - slew-delay-us: microseconds to wait for a GPIO to go high. Default is 10 us.
index 6078aef..7ce23ac 100644 (file)
@@ -27,7 +27,8 @@ Required properties:
 - i2c-bus-name: The name of this bus. Also needed as pinctrl-name for the I2C
                parents.
 
-Furthermore, I2C mux properties and child nodes. See mux.txt in this directory.
+Furthermore, I2C mux properties and child nodes. See i2c-mux.txt in this
+directory.
 
 Example:
 
index 66709a8..21da3ec 100644 (file)
@@ -22,8 +22,8 @@ Required properties:
 - i2c-parent: The phandle of the I2C bus that this multiplexer's master-side
   port is connected to.
 - mux-gpios: list of gpios used to control the muxer
-* Standard I2C mux properties. See mux.txt in this directory.
-* I2C child bus nodes. See mux.txt in this directory.
+* Standard I2C mux properties. See i2c-mux.txt in this directory.
+* I2C child bus nodes. See i2c-mux.txt in this directory.
 
 Optional properties:
 - idle-state: value to set the muxer to when idle. When no value is
@@ -33,7 +33,7 @@ For each i2c child node, an I2C child bus will be created. They will
 be numbered based on their order in the device tree.
 
 Whenever an access is made to a device on a child bus, the value set
-in the revelant node's reg property will be output using the list of
+in the relevant node's reg property will be output using the list of
 GPIOs, the first in the list holding the least-significant value.
 
 If an idle state is defined, using the idle-state (optional) property,
index ae8af16..33119a9 100644 (file)
@@ -28,9 +28,9 @@ Also required are:
 * Standard pinctrl properties that specify the pin mux state for each child
   bus. See ../pinctrl/pinctrl-bindings.txt.
 
-* Standard I2C mux properties. See mux.txt in this directory.
+* Standard I2C mux properties. See i2c-mux.txt in this directory.
 
-* I2C child bus nodes. See mux.txt in this directory.
+* I2C child bus nodes. See i2c-mux.txt in this directory.
 
 For each named state defined in the pinctrl-names property, an I2C child bus
 will be created. I2C child bus numbers are assigned based on the index into
index 688783f..de00d7f 100644 (file)
@@ -7,8 +7,8 @@ Required properties:
 - compatible: i2c-mux-reg
 - i2c-parent: The phandle of the I2C bus that this multiplexer's master-side
   port is connected to.
-* Standard I2C mux properties. See mux.txt in this directory.
-* I2C child bus nodes. See mux.txt in this directory.
+* Standard I2C mux properties. See i2c-mux.txt in this directory.
+* I2C child bus nodes. See i2c-mux.txt in this directory.
 
 Optional properties:
 - reg: this pair of <offset size> specifies the register to control the mux.
@@ -24,7 +24,7 @@ Optional properties:
   given, it defaults to the last value used.
 
 Whenever an access is made to a device on a child bus, the value set
-in the revelant node's reg property will be output to the register.
+in the relevant node's reg property will be output to the register.
 
 If an idle state is defined, using the idle-state (optional) property,
 whenever an access is not being made to a device on a child bus, the
index 14aa6cf..6a9a63c 100644 (file)
@@ -13,10 +13,10 @@ Optional properties:
                      initialization. This is an array of 28 values(u8).
 
   - marvell,wakeup-pin: It represents wakeup pin number of the bluetooth chip.
-                       firmware will use the pin to wakeup host system.
+                       firmware will use the pin to wakeup host system (u16).
   - marvell,wakeup-gap-ms: wakeup gap represents wakeup latency of the host
                      platform. The value will be configured to firmware. This
-                     is needed to work chip's sleep feature as expected.
+                     is needed to work chip's sleep feature as expected (u16).
   - interrupt-parent: phandle of the parent interrupt controller
   - interrupts : interrupt pin number to the cpu. Driver will request an irq based
                 on this interrupt number. During system suspend, the irq will be
@@ -50,7 +50,7 @@ calibration data is also available in below example.
                        0x37 0x01 0x1c 0x00 0xff 0xff 0xff 0xff 0x01 0x7f 0x04 0x02
                        0x00 0x00 0xba 0xce 0xc0 0xc6 0x2d 0x00 0x00 0x00 0x00 0x00
                        0x00 0x00 0xf0 0x00>;
-               marvell,wakeup-pin = <0x0d>;
-               marvell,wakeup-gap-ms = <0x64>;
+               marvell,wakeup-pin = /bits/ 16 <0x0d>;
+               marvell,wakeup-gap-ms = /bits/ 16 <0x64>;
        };
 };
index a7440bc..2c2500d 100644 (file)
@@ -255,6 +255,7 @@ synology    Synology, Inc.
 SUNW   Sun Microsystems, Inc
 tbs    TBS Technologies
 tcl    Toby Churchill Ltd.
+technexion     TechNexion
 technologic    Technologic Systems
 thine  THine Electronics, Inc.
 ti     Texas Instruments
@@ -269,6 +270,7 @@ tronsmart   Tronsmart
 truly  Truly Semiconductors Limited
 tyan   Tyan Computer Corporation
 upisemi        uPI Semiconductor Corp.
+uniwest        United Western Technologies Corp (UniWest)
 urt    United Radiant Technology Corporation
 usi    Universal Scientific Industrial Co., Ltd.
 v3     V3 Semiconductor
index 30d2fcb..9f94fe2 100644 (file)
+Each mount of the devpts filesystem is now distinct such that ptys
+and their indicies allocated in one mount are independent from ptys
+and their indicies in all other mounts.
 
-To support containers, we now allow multiple instances of devpts filesystem,
-such that indices of ptys allocated in one instance are independent of indices
-allocated in other instances of devpts.
+All mounts of the devpts filesystem now create a /dev/pts/ptmx node
+with permissions 0000.
 
-To preserve backward compatibility, this support for multiple instances is
-enabled only if:
+To retain backwards compatibility the a ptmx device node (aka any node
+created with "mknod name c 5 2") when opened will look for an instance
+of devpts under the name "pts" in the same directory as the ptmx device
+node.
 
-       - CONFIG_DEVPTS_MULTIPLE_INSTANCES=y, and
-       - '-o newinstance' mount option is specified while mounting devpts
-
-IOW, devpts now supports both single-instance and multi-instance semantics.
-
-If CONFIG_DEVPTS_MULTIPLE_INSTANCES=n, there is no change in behavior and
-this referred to as the "legacy" mode. In this mode, the new mount options
-(-o newinstance and -o ptmxmode) will be ignored with a 'bogus option' message
-on console.
-
-If CONFIG_DEVPTS_MULTIPLE_INSTANCES=y and devpts is mounted without the
-'newinstance' option (as in current start-up scripts) the new mount binds
-to the initial kernel mount of devpts. This mode is referred to as the
-'single-instance' mode and the current, single-instance semantics are
-preserved, i.e PTYs are common across the system.
-
-The only difference between this single-instance mode and the legacy mode
-is the presence of new, '/dev/pts/ptmx' node with permissions 0000, which
-can safely be ignored.
-
-If CONFIG_DEVPTS_MULTIPLE_INSTANCES=y and 'newinstance' option is specified,
-the mount is considered to be in the multi-instance mode and a new instance
-of the devpts fs is created. Any ptys created in this instance are independent
-of ptys in other instances of devpts. Like in the single-instance mode, the
-/dev/pts/ptmx node is present. To effectively use the multi-instance mode,
-open of /dev/ptmx must be a redirected to '/dev/pts/ptmx' using a symlink or
-bind-mount.
-
-Eg: A container startup script could do the following:
-
-       $ chmod 0666 /dev/pts/ptmx
-       $ rm /dev/ptmx
-       $ ln -s pts/ptmx /dev/ptmx
-       $ ns_exec -cm /bin/bash
-
-       # We are now in new container
-
-       $ umount /dev/pts
-       $ mount -t devpts -o newinstance lxcpts /dev/pts
-       $ sshd -p 1234
-
-where 'ns_exec -cm /bin/bash' calls clone() with CLONE_NEWNS flag and execs
-/bin/bash in the child process.  A pty created by the sshd is not visible in
-the original mount of /dev/pts.
+As an option instead of placing a /dev/ptmx device node at /dev/ptmx
+it is possible to place a symlink to /dev/pts/ptmx at /dev/ptmx or
+to bind mount /dev/ptx/ptmx to /dev/ptmx.  If you opt for using
+the devpts filesystem in this manner devpts should be mounted with
+the ptmxmode=0666, or chmod 0666 /dev/pts/ptmx should be called.
 
 Total count of pty pairs in all instances is limited by sysctls:
 kernel.pty.max = 4096          - global limit
-kernel.pty.reserve = 1024      - reserve for initial instance
+kernel.pty.reserve = 1024      - reserved for filesystems mounted from the initial mount namespace
 kernel.pty.nr                  - current count of ptys
 
 Per-instance limit could be set by adding mount option "max=<count>".
 This feature was added in kernel 3.4 together with sysctl kernel.pty.reserve.
 In kernels older than 3.4 sysctl kernel.pty.max works as per-instance limit.
-
-User-space changes
-------------------
-
-In multi-instance mode (i.e '-o newinstance' mount option is specified at least
-once), following user-space issues should be noted.
-
-1. If -o newinstance mount option is never used, /dev/pts/ptmx can be ignored
-   and no change is needed to system-startup scripts.
-
-2. To effectively use multi-instance mode (i.e -o newinstance is specified)
-   administrators or startup scripts should "redirect" open of /dev/ptmx to
-   /dev/pts/ptmx using either a bind mount or symlink.
-
-       $ mount -t devpts -o newinstance devpts /dev/pts
-
-   followed by either
-
-       $ rm /dev/ptmx
-       $ ln -s pts/ptmx /dev/ptmx
-       $ chmod 666 /dev/pts/ptmx
-   or
-       $ mount -o bind /dev/pts/ptmx /dev/ptmx
-
-3. The '/dev/ptmx -> pts/ptmx' symlink is the preferred method since it
-   enables better error-reporting and treats both single-instance and
-   multi-instance mounts similarly.
-
-   But this method requires that system-startup scripts set the mode of
-   /dev/pts/ptmx correctly (default mode is 0000). The scripts can set the
-   mode by, either
-
-       - adding ptmxmode mount option to devpts entry in /etc/fstab, or
-       - using 'chmod 0666 /dev/pts/ptmx'
-
-4. If multi-instance mode mount is needed for containers, but the system
-   startup scripts have not yet been updated, container-startup scripts
-   should bind mount /dev/ptmx to /dev/pts/ptmx to avoid breaking single-
-   instance mounts.
-
-   Or, in general, container-startup scripts should use:
-
-       mount -t devpts -o newinstance -o ptmxmode=0666 devpts /dev/pts
-       if [ ! -L /dev/ptmx ]; then
-               mount -o bind /dev/pts/ptmx /dev/ptmx
-       fi
-
-   When all devpts mounts are multi-instance, /dev/ptmx can permanently be
-   a symlink to pts/ptmx and the bind mount can be ignored.
-
-5. A multi-instance mount that is not accompanied by the /dev/ptmx to
-   /dev/pts/ptmx redirection would result in an unusable/unreachable pty.
-
-       mount -t devpts -o newinstance lxcpts /dev/pts
-
-   immediately followed by:
-
-       open("/dev/ptmx")
-
-    would create a pty, say /dev/pts/7, in the initial kernel mount.
-    But /dev/pts/7 would be invisible in the new mount.
-
-6. The permissions for /dev/pts/ptmx node should be specified when mounting
-   /dev/pts, using the '-o ptmxmode=%o' mount option (default is 0000).
-
-       mount -t devpts -o newinstance -o ptmxmode=0644 devpts /dev/pts
-
-   The permissions can be later be changed as usual with 'chmod'.
-
-       chmod 666 /dev/pts/ptmx
-
-7. A mount of devpts without the 'newinstance' option results in binding to
-   initial kernel mount.  This behavior while preserving legacy semantics,
-   does not provide strict isolation in a container environment. i.e by
-   mounting devpts without the 'newinstance' option, a container could
-   get visibility into the 'host' or root container's devpts.
-   
-   To workaround this and have strict isolation, all mounts of devpts,
-   including the mount in the root container, should use the newinstance
-   option.
index 35f6a98..220d0a8 100644 (file)
@@ -170,21 +170,92 @@ document trapinfo
        address the kernel panicked.
 end
 
+define dump_log_idx
+       set $idx = $arg0
+       if ($argc > 1)
+               set $prev_flags = $arg1
+       else
+               set $prev_flags = 0
+       end
+       set $msg = ((struct printk_log *) (log_buf + $idx))
+       set $prefix = 1
+       set $newline = 1
+       set $log = log_buf + $idx + sizeof(*$msg)
 
-define dmesg
-       set $i = 0
-       set $end_idx = (log_end - 1) & (log_buf_len - 1)
+       # prev & LOG_CONT && !(msg->flags & LOG_PREIX)
+       if (($prev_flags & 8) && !($msg->flags & 4))
+               set $prefix = 0
+       end
+
+       # msg->flags & LOG_CONT
+       if ($msg->flags & 8)
+               # (prev & LOG_CONT && !(prev & LOG_NEWLINE))
+               if (($prev_flags & 8) && !($prev_flags & 2))
+                       set $prefix = 0
+               end
+               # (!(msg->flags & LOG_NEWLINE))
+               if (!($msg->flags & 2))
+                       set $newline = 0
+               end
+       end
+
+       if ($prefix)
+               printf "[%5lu.%06lu] ", $msg->ts_nsec / 1000000000, $msg->ts_nsec % 1000000000
+       end
+       if ($msg->text_len != 0)
+               eval "printf \"%%%d.%ds\", $log", $msg->text_len, $msg->text_len
+       end
+       if ($newline)
+               printf "\n"
+       end
+       if ($msg->dict_len > 0)
+               set $dict = $log + $msg->text_len
+               set $idx = 0
+               set $line = 1
+               while ($idx < $msg->dict_len)
+                       if ($line)
+                               printf " "
+                               set $line = 0
+                       end
+                       set $c = $dict[$idx]
+                       if ($c == '\0')
+                               printf "\n"
+                               set $line = 1
+                       else
+                               if ($c < ' ' || $c >= 127 || $c == '\\')
+                                       printf "\\x%02x", $c
+                               else
+                                       printf "%c", $c
+                               end
+                       end
+                       set $idx = $idx + 1
+               end
+               printf "\n"
+       end
+end
+document dump_log_idx
+       Dump a single log given its index in the log buffer.  The first
+       parameter is the index into log_buf, the second is optional and
+       specified the previous log buffer's flags, used for properly
+       formatting continued lines.
+end
 
-       while ($i < logged_chars)
-               set $idx = (log_end - 1 - logged_chars + $i) & (log_buf_len - 1)
+define dmesg
+       set $i = log_first_idx
+       set $end_idx = log_first_idx
+       set $prev_flags = 0
 
-               if ($idx + 100 <= $end_idx) || \
-                  ($end_idx <= $idx && $idx + 100 < log_buf_len)
-                       printf "%.100s", &log_buf[$idx]
-                       set $i = $i + 100
+       while (1)
+               set $msg = ((struct printk_log *) (log_buf + $i))
+               if ($msg->len == 0)
+                       set $i = 0
                else
-                       printf "%c", log_buf[$idx]
-                       set $i = $i + 1
+                       dump_log_idx $i $prev_flags
+                       set $i = $i + $msg->len
+                       set $prev_flags = $msg->flags
+               end
+               if ($i == $end_idx)
+                       loop_break
                end
        end
 end
index d406d98..44f5e6b 100644 (file)
@@ -74,8 +74,8 @@ blink_set() function (see <linux/leds.h>). To set an LED to blinking,
 however, it is better to use the API function led_blink_set(), as it
 will check and implement software fallback if necessary.
 
-To turn off blinking again, use the API function led_brightness_set()
-as that will not just set the LED brightness but also stop any software
+To turn off blinking, use the API function led_brightness_set()
+with brightness value LED_OFF, which should stop any software
 timers that may have been required for blinking.
 
 The blink_set() function should choose a user friendly blinking value
index 631b0f7..9d05ed7 100644 (file)
@@ -369,8 +369,6 @@ does not allocate any driver private context space.
 Switch configuration
 --------------------
 
-- priv_size: additional size needed by the switch driver for its private context
-
 - tag_protocol: this is to indicate what kind of tagging protocol is supported,
   should be a valid value from the dsa_tag_protocol enum
 
@@ -416,11 +414,6 @@ PHY devices and link management
   to the switch port MDIO registers. If unavailable return a negative error
   code.
 
-- poll_link: Function invoked by DSA to query the link state of the switch
-  builtin Ethernet PHYs, per port. This function is responsible for calling
-  netif_carrier_{on,off} when appropriate, and can be used to poll all ports in a
-  single call. Executes from workqueue context.
-
 - adjust_link: Function invoked by the PHY library when a slave network device
   is attached to a PHY device. This function is responsible for appropriately
   configuring the switch port link parameters: speed, duplex, pause based on
@@ -542,6 +535,16 @@ Bridge layer
 Bridge VLAN filtering
 ---------------------
 
+- port_vlan_filtering: bridge layer function invoked when the bridge gets
+  configured for turning on or off VLAN filtering. If nothing specific needs to
+  be done at the hardware level, this callback does not need to be implemented.
+  When VLAN filtering is turned on, the hardware must be programmed with
+  rejecting 802.1Q frames which have VLAN IDs outside of the programmed allowed
+  VLAN ID map/rules.  If there is no PVID programmed into the switch port,
+  untagged frames must be rejected as well. When turned off the switch must
+  accept any 802.1Q frames irrespective of their VLAN ID, and untagged frames are
+  allowed.
+
 - port_vlan_prepare: bridge layer function invoked when the bridge prepares the
   configuration of a VLAN on the given port. If the operation is not supported
   by the hardware, this function should return -EOPNOTSUPP to inform the bridge
index 6c7f365..9ae9293 100644 (file)
@@ -1036,15 +1036,17 @@ proxy_arp_pvlan - BOOLEAN
 
 shared_media - BOOLEAN
        Send(router) or accept(host) RFC1620 shared media redirects.
-       Overrides ip_secure_redirects.
+       Overrides secure_redirects.
        shared_media for the interface will be enabled if at least one of
        conf/{all,interface}/shared_media is set to TRUE,
        it will be disabled otherwise
        default TRUE
 
 secure_redirects - BOOLEAN
-       Accept ICMP redirect messages only for gateways,
-       listed in default gateway list.
+       Accept ICMP redirect messages only to gateways listed in the
+       interface's current gateway list. Even if disabled, RFC1122 redirect
+       rules still apply.
+       Overridden by shared_media.
        secure_redirects for the interface will be enabled if at least one of
        conf/{all,interface}/secure_redirects is set to TRUE,
        it will be disabled otherwise
index 8638f61..37eca00 100644 (file)
@@ -263,19 +263,23 @@ scmd->allowed.
 
  3. scmd recovered
     ACTION: scsi_eh_finish_cmd() is invoked to EH-finish scmd
-       - shost->host_failed--
        - clear scmd->eh_eflags
        - scsi_setup_cmd_retry()
        - move from local eh_work_q to local eh_done_q
     LOCKING: none
+    CONCURRENCY: at most one thread per separate eh_work_q to
+                keep queue manipulation lockless
 
  4. EH completes
     ACTION: scsi_eh_flush_done_q() retries scmds or notifies upper
-           layer of failure.
+           layer of failure. May be called concurrently but must have
+           a no more than one thread per separate eh_work_q to
+           manipulate the queue locklessly
        - scmd is removed from eh_done_q and scmd->eh_entry is cleared
        - if retry is necessary, scmd is requeued using
           scsi_queue_insert()
        - otherwise, scsi_finish_command() is invoked for scmd
+       - zero shost->host_failed
     LOCKING: queue or finish function performs appropriate locking
 
 
index 20d0571..3849814 100644 (file)
@@ -826,7 +826,8 @@ The keyctl syscall functions are:
  (*) Compute a Diffie-Hellman shared secret or public key
 
        long keyctl(KEYCTL_DH_COMPUTE, struct keyctl_dh_params *params,
-                  char *buffer, size_t buflen);
+                  char *buffer, size_t buflen,
+                  void *reserved);
 
      The params struct contains serial numbers for three keys:
 
@@ -843,6 +844,8 @@ The keyctl syscall functions are:
      public key.  If the base is the remote public key, the result is
      the shared secret.
 
+     The reserved argument must be set to NULL.
+
      The buffer length must be at least the length of the prime, or zero.
 
      If the buffer length is nonzero, the length of the result is
index 7304d2e..952fd2a 100644 (file)
@@ -1159,6 +1159,7 @@ F:        arch/arm/mach-footbridge/
 ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
 M:     Shawn Guo <shawnguo@kernel.org>
 M:     Sascha Hauer <kernel@pengutronix.de>
+R:     Fabio Estevam <fabio.estevam@nxp.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git
@@ -2242,7 +2243,8 @@ F:        include/net/ax25.h
 F:     net/ax25/
 
 AZ6007 DVB DRIVER
-M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@s-opensource.com>
+M:     Mauro Carvalho Chehab <mchehab@kernel.org>
 L:     linux-media@vger.kernel.org
 W:     https://linuxtv.org
 T:     git git://linuxtv.org/media_tree.git
@@ -2709,7 +2711,8 @@ F:        Documentation/filesystems/btrfs.txt
 F:     fs/btrfs/
 
 BTTV VIDEO4LINUX DRIVER
-M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@s-opensource.com>
+M:     Mauro Carvalho Chehab <mchehab@kernel.org>
 L:     linux-media@vger.kernel.org
 W:     https://linuxtv.org
 T:     git git://linuxtv.org/media_tree.git
@@ -2773,9 +2776,9 @@ F:        include/net/caif/
 F:     net/caif/
 
 CALGARY x86-64 IOMMU
-M:     Muli Ben-Yehuda <muli@il.ibm.com>
-M:     "Jon D. Mason" <jdmason@kudzu.us>
-L:     discuss@x86-64.org
+M:     Muli Ben-Yehuda <mulix@mulix.org>
+M:     Jon Mason <jdmason@kudzu.us>
+L:     iommu@lists.linux-foundation.org
 S:     Maintained
 F:     arch/x86/kernel/pci-calgary_64.c
 F:     arch/x86/kernel/tce_64.c
@@ -3086,6 +3089,7 @@ M:        Stephen Boyd <sboyd@codeaurora.org>
 L:     linux-clk@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git
 S:     Maintained
+F:     Documentation/devicetree/bindings/clock/
 F:     drivers/clk/
 X:     drivers/clk/clkdev.c
 F:     include/linux/clk-pr*
@@ -3343,7 +3347,8 @@ S:        Maintained
 F:     drivers/media/dvb-frontends/cx24120*
 
 CX88 VIDEO4LINUX DRIVER
-M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@s-opensource.com>
+M:     Mauro Carvalho Chehab <mchehab@kernel.org>
 L:     linux-media@vger.kernel.org
 W:     https://linuxtv.org
 T:     git git://linuxtv.org/media_tree.git
@@ -3773,6 +3778,7 @@ Q:        https://patchwork.kernel.org/project/linux-dmaengine/list/
 S:     Maintained
 F:     drivers/dma/
 F:     include/linux/dmaengine.h
+F:     Documentation/devicetree/bindings/dma/
 F:     Documentation/dmaengine/
 T:     git git://git.infradead.org/users/vkoul/slave-dma.git
 
@@ -4290,7 +4296,8 @@ F:        fs/ecryptfs/
 EDAC-CORE
 M:     Doug Thompson <dougthompson@xmission.com>
 M:     Borislav Petkov <bp@alien8.de>
-M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@s-opensource.com>
+M:     Mauro Carvalho Chehab <mchehab@kernel.org>
 L:     linux-edac@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp.git for-next
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-edac.git linux_next
@@ -4335,7 +4342,8 @@ S:        Maintained
 F:     drivers/edac/e7xxx_edac.c
 
 EDAC-GHES
-M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@s-opensource.com>
+M:     Mauro Carvalho Chehab <mchehab@kernel.org>
 L:     linux-edac@vger.kernel.org
 S:     Maintained
 F:     drivers/edac/ghes_edac.c
@@ -4359,19 +4367,22 @@ S:      Maintained
 F:     drivers/edac/i5000_edac.c
 
 EDAC-I5400
-M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@s-opensource.com>
+M:     Mauro Carvalho Chehab <mchehab@kernel.org>
 L:     linux-edac@vger.kernel.org
 S:     Maintained
 F:     drivers/edac/i5400_edac.c
 
 EDAC-I7300
-M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@s-opensource.com>
+M:     Mauro Carvalho Chehab <mchehab@kernel.org>
 L:     linux-edac@vger.kernel.org
 S:     Maintained
 F:     drivers/edac/i7300_edac.c
 
 EDAC-I7CORE
-M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@s-opensource.com>
+M:     Mauro Carvalho Chehab <mchehab@kernel.org>
 L:     linux-edac@vger.kernel.org
 S:     Maintained
 F:     drivers/edac/i7core_edac.c
@@ -4408,7 +4419,8 @@ S:        Maintained
 F:     drivers/edac/r82600_edac.c
 
 EDAC-SBRIDGE
-M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@s-opensource.com>
+M:     Mauro Carvalho Chehab <mchehab@kernel.org>
 L:     linux-edac@vger.kernel.org
 S:     Maintained
 F:     drivers/edac/sb_edac.c
@@ -4467,7 +4479,8 @@ S:        Maintained
 F:     drivers/net/ethernet/ibm/ehea/
 
 EM28XX VIDEO4LINUX DRIVER
-M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@s-opensource.com>
+M:     Mauro Carvalho Chehab <mchehab@kernel.org>
 L:     linux-media@vger.kernel.org
 W:     https://linuxtv.org
 T:     git git://linuxtv.org/media_tree.git
@@ -6486,6 +6499,7 @@ F:        include/uapi/linux/sunrpc/
 
 KERNEL SELFTEST FRAMEWORK
 M:     Shuah Khan <shuahkh@osg.samsung.com>
+M:     Shuah Khan <shuah@kernel.org>
 L:     linux-kselftest@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/shuah/linux-kselftest
 S:     Maintained
@@ -7357,7 +7371,8 @@ S:        Supported
 F:     drivers/media/pci/netup_unidvb/*
 
 MEDIA INPUT INFRASTRUCTURE (V4L/DVB)
-M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@s-opensource.com>
+M:     Mauro Carvalho Chehab <mchehab@kernel.org>
 P:     LinuxTV.org Project
 L:     linux-media@vger.kernel.org
 W:     https://linuxtv.org
@@ -7989,6 +8004,7 @@ Q:        http://patchwork.ozlabs.org/project/netdev/list/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git
 S:     Odd Fixes
+F:     Documentation/devicetree/bindings/net/
 F:     drivers/net/
 F:     include/linux/if_*
 F:     include/linux/netdevice.h
@@ -8007,6 +8023,7 @@ Q:        http://patchwork.kernel.org/project/linux-wireless/list/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers.git
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next.git
 S:     Maintained
+F:     Documentation/devicetree/bindings/net/wireless/
 F:     drivers/net/wireless/
 
 NETXEN (1/10) GbE SUPPORT
@@ -8404,10 +8421,9 @@ F:       drivers/i2c/busses/i2c-ocores.c
 OPEN FIRMWARE AND FLATTENED DEVICE TREE
 M:     Rob Herring <robh+dt@kernel.org>
 M:     Frank Rowand <frowand.list@gmail.com>
-M:     Grant Likely <grant.likely@linaro.org>
 L:     devicetree@vger.kernel.org
 W:     http://www.devicetree.org/
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/glikely/linux.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git
 S:     Maintained
 F:     drivers/of/
 F:     include/linux/of*.h
@@ -8415,12 +8431,10 @@ F:      scripts/dtc/
 
 OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS
 M:     Rob Herring <robh+dt@kernel.org>
-M:     Pawel Moll <pawel.moll@arm.com>
 M:     Mark Rutland <mark.rutland@arm.com>
-M:     Ian Campbell <ijc+devicetree@hellion.org.uk>
-M:     Kumar Gala <galak@codeaurora.org>
 L:     devicetree@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git
+Q:     http://patchwork.ozlabs.org/project/devicetree-bindings/list/
 S:     Maintained
 F:     Documentation/devicetree/
 F:     arch/*/boot/dts/
@@ -8944,6 +8958,7 @@ M:        Linus Walleij <linus.walleij@linaro.org>
 L:     linux-gpio@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git
 S:     Maintained
+F:     Documentation/devicetree/bindings/pinctrl/
 F:     drivers/pinctrl/
 F:     include/linux/pinctrl/
 
@@ -9851,7 +9866,8 @@ S:        Odd Fixes
 F:     drivers/media/i2c/saa6588*
 
 SAA7134 VIDEO4LINUX DRIVER
-M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@s-opensource.com>
+M:     Mauro Carvalho Chehab <mchehab@kernel.org>
 L:     linux-media@vger.kernel.org
 W:     https://linuxtv.org
 T:     git git://linuxtv.org/media_tree.git
@@ -10370,7 +10386,8 @@ S:      Maintained
 F:     drivers/media/radio/si4713/radio-usb-si4713.c
 
 SIANO DVB DRIVER
-M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@s-opensource.com>
+M:     Mauro Carvalho Chehab <mchehab@kernel.org>
 L:     linux-media@vger.kernel.org
 W:     https://linuxtv.org
 T:     git git://linuxtv.org/media_tree.git
@@ -11136,7 +11153,8 @@ S:      Maintained
 F:     drivers/media/i2c/tda9840*
 
 TEA5761 TUNER DRIVER
-M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@s-opensource.com>
+M:     Mauro Carvalho Chehab <mchehab@kernel.org>
 L:     linux-media@vger.kernel.org
 W:     https://linuxtv.org
 T:     git git://linuxtv.org/media_tree.git
@@ -11144,7 +11162,8 @@ S:      Odd fixes
 F:     drivers/media/tuners/tea5761.*
 
 TEA5767 TUNER DRIVER
-M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@s-opensource.com>
+M:     Mauro Carvalho Chehab <mchehab@kernel.org>
 L:     linux-media@vger.kernel.org
 W:     https://linuxtv.org
 T:     git git://linuxtv.org/media_tree.git
@@ -11531,7 +11550,8 @@ F:      include/linux/shmem_fs.h
 F:     mm/shmem.c
 
 TM6000 VIDEO4LINUX DRIVER
-M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@s-opensource.com>
+M:     Mauro Carvalho Chehab <mchehab@kernel.org>
 L:     linux-media@vger.kernel.org
 W:     https://linuxtv.org
 T:     git git://linuxtv.org/media_tree.git
@@ -11885,7 +11905,8 @@ F:      drivers/usb/common/usb-otg-fsm.c
 
 USB OVER IP DRIVER
 M:     Valentina Manea <valentina.manea.m@gmail.com>
-M:     Shuah Khan <shuah.kh@samsung.com>
+M:     Shuah Khan <shuahkh@osg.samsung.com>
+M:     Shuah Khan <shuah@kernel.org>
 L:     linux-usb@vger.kernel.org
 S:     Maintained
 F:     Documentation/usb/usbip_protocol.txt
@@ -11956,6 +11977,7 @@ L:      linux-usb@vger.kernel.org
 W:     http://www.linux-usb.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git
 S:     Supported
+F:     Documentation/devicetree/bindings/usb/
 F:     Documentation/usb/
 F:     drivers/usb/
 F:     include/linux/usb.h
@@ -12129,6 +12151,7 @@ VIRTIO CORE, NET AND BLOCK DRIVERS
 M:     "Michael S. Tsirkin" <mst@redhat.com>
 L:     virtualization@lists.linux-foundation.org
 S:     Maintained
+F:     Documentation/devicetree/bindings/virtio/
 F:     drivers/virtio/
 F:     tools/virtio/
 F:     drivers/net/virtio_net.c
@@ -12517,7 +12540,8 @@ S:      Maintained
 F:     arch/x86/entry/vdso/
 
 XC2028/3028 TUNER DRIVER
-M:     Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M:     Mauro Carvalho Chehab <mchehab@s-opensource.com>
+M:     Mauro Carvalho Chehab <mchehab@kernel.org>
 L:     linux-media@vger.kernel.org
 W:     https://linuxtv.org
 T:     git git://linuxtv.org/media_tree.git
index 0f70de6..6471f20 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 4
 PATCHLEVEL = 7
 SUBLEVEL = 0
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc5
 NAME = Psychotic Stoned Sheep
 
 # *DOCUMENTATION*
index d794384..1599629 100644 (file)
@@ -226,8 +226,8 @@ config ARCH_INIT_TASK
 config ARCH_TASK_STRUCT_ALLOCATOR
        bool
 
-# Select if arch has its private alloc_thread_info() function
-config ARCH_THREAD_INFO_ALLOCATOR
+# Select if arch has its private alloc_thread_stack() function
+config ARCH_THREAD_STACK_ALLOCATOR
        bool
 
 # Select if arch wants to size task_struct dynamically via arch_task_struct_size:
@@ -606,6 +606,9 @@ config HAVE_ARCH_HASH
          file which provides platform-specific implementations of some
          functions in <linux/hash.h> or fs/namei.c.
 
+config ISA_BUS_API
+       def_bool ISA
+
 #
 # ABI hall of shame
 #
index aab14a0..c2ebb6f 100644 (file)
@@ -40,7 +40,7 @@ pgd_free(struct mm_struct *mm, pgd_t *pgd)
 static inline pmd_t *
 pmd_alloc_one(struct mm_struct *mm, unsigned long address)
 {
-       pmd_t *ret = (pmd_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
+       pmd_t *ret = (pmd_t *)__get_free_page(GFP_KERNEL|__GFP_ZERO);
        return ret;
 }
 
@@ -53,7 +53,7 @@ pmd_free(struct mm_struct *mm, pmd_t *pmd)
 static inline pte_t *
 pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
 {
-       pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
+       pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_ZERO);
        return pte;
 }
 
index 0dcbacf..0d3e59f 100644 (file)
@@ -61,7 +61,7 @@ config RWSEM_GENERIC_SPINLOCK
        def_bool y
 
 config ARCH_DISCONTIGMEM_ENABLE
-       def_bool y
+       def_bool n
 
 config ARCH_FLATMEM_ENABLE
        def_bool y
@@ -186,9 +186,6 @@ if SMP
 config ARC_HAS_COH_CACHES
        def_bool n
 
-config ARC_HAS_REENTRANT_IRQ_LV2
-       def_bool n
-
 config ARC_MCIP
        bool "ARConnect Multicore IP (MCIP) Support "
        depends on ISA_ARCV2
@@ -366,25 +363,10 @@ config NODES_SHIFT
 if ISA_ARCOMPACT
 
 config ARC_COMPACT_IRQ_LEVELS
-       bool "ARCompact IRQ Priorities: High(2)/Low(1)"
+       bool "Setup Timer IRQ as high Priority"
        default n
-       # Timer HAS to be high priority, for any other high priority config
-       select ARC_IRQ3_LV2
        # if SMP, LV2 enabled ONLY if ARC implementation has LV2 re-entrancy
-       depends on !SMP || ARC_HAS_REENTRANT_IRQ_LV2
-
-if ARC_COMPACT_IRQ_LEVELS
-
-config ARC_IRQ3_LV2
-       bool
-
-config ARC_IRQ5_LV2
-       bool
-
-config ARC_IRQ6_LV2
-       bool
-
-endif  #ARC_COMPACT_IRQ_LEVELS
+       depends on !SMP
 
 config ARC_FPU_SAVE_RESTORE
        bool "Enable FPU state persistence across context switch"
@@ -407,11 +389,6 @@ config ARC_HAS_LLSC
        default y
        depends on !ARC_CANT_LLSC
 
-config ARC_STAR_9000923308
-       bool "Workaround for llock/scond livelock"
-       default n
-       depends on ISA_ARCV2 && SMP && ARC_HAS_LLSC
-
 config ARC_HAS_SWAPE
        bool "Insn: SWAPE (endian-swap)"
        default y
@@ -471,7 +448,7 @@ config LINUX_LINK_BASE
 
 config HIGHMEM
        bool "High Memory Support"
-       select DISCONTIGMEM
+       select ARCH_DISCONTIGMEM_ENABLE
        help
          With ARC 2G:2G address split, only upper 2G is directly addressable by
          kernel. Enable this to potentially allow access to rest of 2G and PAE
index 02fabef..d4df6be 100644 (file)
@@ -127,7 +127,7 @@ libs-y              += arch/arc/lib/ $(LIBGCC)
 
 boot           := arch/arc/boot
 
-#default target for make without any arguements.
+#default target for make without any arguments.
 KBUILD_IMAGE   := bootpImage
 
 all:   $(KBUILD_IMAGE)
index 3942634..02410b2 100644 (file)
@@ -23,8 +23,6 @@
 
 
 / {
-       clock-frequency         = <500000000>;  /* 500 MHZ */
-
        soc100 {
                bus-frequency   = <166666666>;
 
index b046722..f9e7686 100644 (file)
@@ -23,8 +23,6 @@
 
 
 / {
-       clock-frequency         = <500000000>;  /* 500 MHZ */
-
        soc100 {
                bus-frequency   = <166666666>;
 
index 3e02f15..6ae2c47 100644 (file)
@@ -15,7 +15,6 @@
 
 / {
        compatible = "snps,arc";
-       clock-frequency = <750000000>;  /* 750 MHZ */
        #address-cells = <1>;
        #size-cells = <1>;
 
index 378e455..14df46f 100644 (file)
@@ -14,7 +14,6 @@
 
 / {
        compatible = "snps,arc";
-       clock-frequency = <90000000>;
        #address-cells = <1>;
        #size-cells = <1>;
 
index 64c94b2..3d6cfa3 100644 (file)
@@ -14,7 +14,6 @@
 
 / {
        compatible = "snps,arc";
-       clock-frequency = <90000000>;
        #address-cells = <1>;
        #size-cells = <1>;
 
index b89f6c3..1e0d225 100644 (file)
@@ -18,7 +18,6 @@
 
 / {
        compatible = "ezchip,arc-nps";
-       clock-frequency = <83333333>;   /* 83.333333 MHZ */
        #address-cells = <1>;
        #size-cells = <1>;
        interrupt-parent = <&intc>;
index 5d5e373..6397051 100644 (file)
@@ -11,7 +11,6 @@
 
 / {
        compatible = "snps,nsim";
-       clock-frequency = <80000000>;   /* 80 MHZ */
        #address-cells = <1>;
        #size-cells = <1>;
        interrupt-parent = <&core_intc>;
index b5b060a..763d66c 100644 (file)
@@ -11,7 +11,6 @@
 
 / {
        compatible = "snps,nsimosci";
-       clock-frequency = <20000000>;   /* 20 MHZ */
        #address-cells = <1>;
        #size-cells = <1>;
        interrupt-parent = <&core_intc>;
index 325e730..4eb97c5 100644 (file)
@@ -11,7 +11,6 @@
 
 / {
        compatible = "snps,nsimosci_hs";
-       clock-frequency = <20000000>;   /* 20 MHZ */
        #address-cells = <1>;
        #size-cells = <1>;
        interrupt-parent = <&core_intc>;
index ee03d71..853f897 100644 (file)
@@ -11,7 +11,6 @@
 
 / {
        compatible = "snps,nsimosci_hs";
-       clock-frequency = <5000000>;    /* 5 MHZ */
        #address-cells = <1>;
        #size-cells = <1>;
        interrupt-parent = <&core_intc>;
index 3a10cc6..65808fe 100644 (file)
@@ -13,7 +13,6 @@
 
 / {
        compatible = "snps,arc";
-       clock-frequency = <80000000>;   /* 80 MHZ */
        #address-cells = <1>;
        #size-cells = <1>;
        chosen { };
index 71fd308..2dfe803 100644 (file)
@@ -8,7 +8,6 @@
 
 / {
        compatible = "snps,arc";
-       clock-frequency = <80000000>;   /* 80 MHZ */
        #address-cells = <1>;
        #size-cells = <1>;
        chosen { };
index d1cb25a..4c11079 100644 (file)
@@ -8,7 +8,6 @@
 
 / {
        compatible = "snps,arc";
-       clock-frequency = <80000000>;   /* 80 MHZ */
        #address-cells = <1>;
        #size-cells = <1>;
        chosen { };
index ad4ee43..0fd6ba9 100644 (file)
@@ -14,7 +14,6 @@
 
 / {
        compatible = "snps,arc";
-       clock-frequency = <50000000>;
        #address-cells = <1>;
        #size-cells = <1>;
 
index a3cb626..82214cd 100644 (file)
@@ -15,7 +15,6 @@
 
 / {
        compatible = "snps,arc";
-       clock-frequency = <50000000>;
        #address-cells = <1>;
        #size-cells = <1>;
 
index 5f3dcbb..dd68399 100644 (file)
 
 #define atomic_set(v, i) WRITE_ONCE(((v)->counter), (i))
 
-#ifdef CONFIG_ARC_STAR_9000923308
-
-#define SCOND_FAIL_RETRY_VAR_DEF                                               \
-       unsigned int delay = 1, tmp;                                            \
-
-#define SCOND_FAIL_RETRY_ASM                                                   \
-       "       bz      4f                      \n"                             \
-       "   ; --- scond fail delay ---          \n"                             \
-       "       mov     %[tmp], %[delay]        \n"     /* tmp = delay */       \
-       "2:     brne.d  %[tmp], 0, 2b           \n"     /* while (tmp != 0) */  \
-       "       sub     %[tmp], %[tmp], 1       \n"     /* tmp-- */             \
-       "       rol     %[delay], %[delay]      \n"     /* delay *= 2 */        \
-       "       b       1b                      \n"     /* start over */        \
-       "4: ; --- success ---                   \n"                             \
-
-#define SCOND_FAIL_RETRY_VARS                                                  \
-         ,[delay] "+&r" (delay),[tmp] "=&r"    (tmp)                           \
-
-#else  /* !CONFIG_ARC_STAR_9000923308 */
-
-#define SCOND_FAIL_RETRY_VAR_DEF
-
-#define SCOND_FAIL_RETRY_ASM                                                   \
-       "       bnz     1b                      \n"                             \
-
-#define SCOND_FAIL_RETRY_VARS
-
-#endif
-
 #define ATOMIC_OP(op, c_op, asm_op)                                    \
 static inline void atomic_##op(int i, atomic_t *v)                     \
 {                                                                      \
-       unsigned int val;                                               \
-       SCOND_FAIL_RETRY_VAR_DEF                                        \
+       unsigned int val;                                               \
                                                                        \
        __asm__ __volatile__(                                           \
        "1:     llock   %[val], [%[ctr]]                \n"             \
        "       " #asm_op " %[val], %[val], %[i]        \n"             \
        "       scond   %[val], [%[ctr]]                \n"             \
-       "                                               \n"             \
-       SCOND_FAIL_RETRY_ASM                                            \
-                                                                       \
+       "       bnz     1b                              \n"             \
        : [val] "=&r"   (val) /* Early clobber to prevent reg reuse */  \
-         SCOND_FAIL_RETRY_VARS                                         \
        : [ctr] "r"     (&v->counter), /* Not "m": llock only supports reg direct addr mode */  \
          [i]   "ir"    (i)                                             \
        : "cc");                                                        \
@@ -77,8 +44,7 @@ static inline void atomic_##op(int i, atomic_t *v)                    \
 #define ATOMIC_OP_RETURN(op, c_op, asm_op)                             \
 static inline int atomic_##op##_return(int i, atomic_t *v)             \
 {                                                                      \
-       unsigned int val;                                               \
-       SCOND_FAIL_RETRY_VAR_DEF                                        \
+       unsigned int val;                                               \
                                                                        \
        /*                                                              \
         * Explicit full memory barrier needed before/after as          \
@@ -90,11 +56,8 @@ static inline int atomic_##op##_return(int i, atomic_t *v)           \
        "1:     llock   %[val], [%[ctr]]                \n"             \
        "       " #asm_op " %[val], %[val], %[i]        \n"             \
        "       scond   %[val], [%[ctr]]                \n"             \
-       "                                               \n"             \
-       SCOND_FAIL_RETRY_ASM                                            \
-                                                                       \
+       "       bnz     1b                              \n"             \
        : [val] "=&r"   (val)                                           \
-         SCOND_FAIL_RETRY_VARS                                         \
        : [ctr] "r"     (&v->counter),                                  \
          [i]   "ir"    (i)                                             \
        : "cc");                                                        \
index e0e1faf..14c310f 100644 (file)
@@ -76,8 +76,8 @@
         * We need to be a bit more cautious here. What if a kernel bug in
         * L1 ISR, caused SP to go whaco (some small value which looks like
         * USER stk) and then we take L2 ISR.
-        * Above brlo alone would treat it as a valid L1-L2 sceanrio
-        * instead of shouting alound
+        * Above brlo alone would treat it as a valid L1-L2 scenario
+        * instead of shouting around
         * The only feasible way is to make sure this L2 happened in
         * L1 prelogue ONLY i.e. ilink2 is less than a pre-set marker in
         * L1 ISR before it switches stack
index 1fd467e..b0b87f2 100644 (file)
@@ -83,7 +83,7 @@ static inline void get_new_mmu_context(struct mm_struct *mm)
                local_flush_tlb_all();
 
                /*
-                * Above checke for rollover of 8 bit ASID in 32 bit container.
+                * Above check for rollover of 8 bit ASID in 32 bit container.
                 * If the container itself wrapped around, set it to a non zero
                 * "generation" to distinguish from no context
                 */
index 86ed671..3749234 100644 (file)
@@ -95,7 +95,7 @@ static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
 {
        pte_t *pte;
 
-       pte = (pte_t *) __get_free_pages(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO,
+       pte = (pte_t *) __get_free_pages(GFP_KERNEL | __GFP_ZERO,
                                         __get_order_pte());
 
        return pte;
@@ -107,7 +107,7 @@ pte_alloc_one(struct mm_struct *mm, unsigned long address)
        pgtable_t pte_pg;
        struct page *page;
 
-       pte_pg = (pgtable_t)__get_free_pages(GFP_KERNEL | __GFP_REPEAT, __get_order_pte());
+       pte_pg = (pgtable_t)__get_free_pages(GFP_KERNEL, __get_order_pte());
        if (!pte_pg)
                return 0;
        memzero((void *)pte_pg, PTRS_PER_PTE * sizeof(pte_t));
index 034bbdc..858f98e 100644 (file)
@@ -47,7 +47,7 @@
  * Page Tables are purely for Linux VM's consumption and the bits below are
  * suited to that (uniqueness). Hence some are not implemented in the TLB and
  * some have different value in TLB.
- * e.g. MMU v2: K_READ bit is 8 and so is GLOBAL (possible becoz they live in
+ * e.g. MMU v2: K_READ bit is 8 and so is GLOBAL (possible because they live in
  *      seperate PD0 and PD1, which combined forms a translation entry)
  *      while for PTE perspective, they are 8 and 9 respectively
  * with MMU v3: Most bits (except SHARED) represent the exact hardware pos
index f904899..16b630f 100644 (file)
@@ -78,7 +78,7 @@ struct task_struct;
 #define KSTK_ESP(tsk)   (task_pt_regs(tsk)->sp)
 
 /*
- * Where abouts of Task's sp, fp, blink when it was last seen in kernel mode.
+ * Where about of Task's sp, fp, blink when it was last seen in kernel mode.
  * Look in process.c for details of kernel stack layout
  */
 #define TSK_K_ESP(tsk)         (tsk->thread.ksp)
index 9913804..89fdd1b 100644 (file)
@@ -86,7 +86,7 @@ static inline const char *arc_platform_smp_cpuinfo(void)
  * (1) These insn were introduced only in 4.10 release. So for older released
  *     support needed.
  *
- * (2) In a SMP setup, the LLOCK/SCOND atomiticity across CPUs needs to be
+ * (2) In a SMP setup, the LLOCK/SCOND atomicity across CPUs needs to be
  *     gaurantted by the platform (not something which core handles).
  *     Assuming a platform won't, SMP Linux needs to use spinlocks + local IRQ
  *     disabling for atomicity.
index 800e7c4..cded4a9 100644 (file)
 
 #ifdef CONFIG_ARC_HAS_LLSC
 
-/*
- * A normal LLOCK/SCOND based system, w/o need for livelock workaround
- */
-#ifndef CONFIG_ARC_STAR_9000923308
-
 static inline void arch_spin_lock(arch_spinlock_t *lock)
 {
        unsigned int val;
@@ -238,293 +233,6 @@ static inline void arch_write_unlock(arch_rwlock_t *rw)
        smp_mb();
 }
 
-#else  /* CONFIG_ARC_STAR_9000923308 */
-
-/*
- * HS38x4 could get into a LLOCK/SCOND livelock in case of multiple overlapping
- * coherency transactions in the SCU. The exclusive line state keeps rotating
- * among contenting cores leading to a never ending cycle. So break the cycle
- * by deferring the retry of failed exclusive access (SCOND). The actual delay
- * needed is function of number of contending cores as well as the unrelated
- * coherency traffic from other cores. To keep the code simple, start off with
- * small delay of 1 which would suffice most cases and in case of contention
- * double the delay. Eventually the delay is sufficient such that the coherency
- * pipeline is drained, thus a subsequent exclusive access would succeed.
- */
-
-#define SCOND_FAIL_RETRY_VAR_DEF                                               \
-       unsigned int delay, tmp;                                                \
-
-#define SCOND_FAIL_RETRY_ASM                                                   \
-       "   ; --- scond fail delay ---          \n"                             \
-       "       mov     %[tmp], %[delay]        \n"     /* tmp = delay */       \
-       "2:     brne.d  %[tmp], 0, 2b           \n"     /* while (tmp != 0) */  \
-       "       sub     %[tmp], %[tmp], 1       \n"     /* tmp-- */             \
-       "       rol     %[delay], %[delay]      \n"     /* delay *= 2 */        \
-       "       b       1b                      \n"     /* start over */        \
-       "                                       \n"                             \
-       "4: ; --- done ---                      \n"                             \
-
-#define SCOND_FAIL_RETRY_VARS                                                  \
-         ,[delay] "=&r" (delay), [tmp] "=&r"   (tmp)                           \
-
-static inline void arch_spin_lock(arch_spinlock_t *lock)
-{
-       unsigned int val;
-       SCOND_FAIL_RETRY_VAR_DEF;
-
-       smp_mb();
-
-       __asm__ __volatile__(
-       "0:     mov     %[delay], 1             \n"
-       "1:     llock   %[val], [%[slock]]      \n"
-       "       breq    %[val], %[LOCKED], 0b   \n"     /* spin while LOCKED */
-       "       scond   %[LOCKED], [%[slock]]   \n"     /* acquire */
-       "       bz      4f                      \n"     /* done */
-       "                                       \n"
-       SCOND_FAIL_RETRY_ASM
-
-       : [val]         "=&r"   (val)
-         SCOND_FAIL_RETRY_VARS
-       : [slock]       "r"     (&(lock->slock)),
-         [LOCKED]      "r"     (__ARCH_SPIN_LOCK_LOCKED__)
-       : "memory", "cc");
-
-       smp_mb();
-}
-
-/* 1 - lock taken successfully */
-static inline int arch_spin_trylock(arch_spinlock_t *lock)
-{
-       unsigned int val, got_it = 0;
-       SCOND_FAIL_RETRY_VAR_DEF;
-
-       smp_mb();
-
-       __asm__ __volatile__(
-       "0:     mov     %[delay], 1             \n"
-       "1:     llock   %[val], [%[slock]]      \n"
-       "       breq    %[val], %[LOCKED], 4f   \n"     /* already LOCKED, just bail */
-       "       scond   %[LOCKED], [%[slock]]   \n"     /* acquire */
-       "       bz.d    4f                      \n"
-       "       mov.z   %[got_it], 1            \n"     /* got it */
-       "                                       \n"
-       SCOND_FAIL_RETRY_ASM
-
-       : [val]         "=&r"   (val),
-         [got_it]      "+&r"   (got_it)
-         SCOND_FAIL_RETRY_VARS
-       : [slock]       "r"     (&(lock->slock)),
-         [LOCKED]      "r"     (__ARCH_SPIN_LOCK_LOCKED__)
-       : "memory", "cc");
-
-       smp_mb();
-
-       return got_it;
-}
-
-static inline void arch_spin_unlock(arch_spinlock_t *lock)
-{
-       smp_mb();
-
-       lock->slock = __ARCH_SPIN_LOCK_UNLOCKED__;
-
-       smp_mb();
-}
-
-/*
- * Read-write spinlocks, allowing multiple readers but only one writer.
- * Unfair locking as Writers could be starved indefinitely by Reader(s)
- */
-
-static inline void arch_read_lock(arch_rwlock_t *rw)
-{
-       unsigned int val;
-       SCOND_FAIL_RETRY_VAR_DEF;
-
-       smp_mb();
-
-       /*
-        * zero means writer holds the lock exclusively, deny Reader.
-        * Otherwise grant lock to first/subseq reader
-        *
-        *      if (rw->counter > 0) {
-        *              rw->counter--;
-        *              ret = 1;
-        *      }
-        */
-
-       __asm__ __volatile__(
-       "0:     mov     %[delay], 1             \n"
-       "1:     llock   %[val], [%[rwlock]]     \n"
-       "       brls    %[val], %[WR_LOCKED], 0b\n"     /* <= 0: spin while write locked */
-       "       sub     %[val], %[val], 1       \n"     /* reader lock */
-       "       scond   %[val], [%[rwlock]]     \n"
-       "       bz      4f                      \n"     /* done */
-       "                                       \n"
-       SCOND_FAIL_RETRY_ASM
-
-       : [val]         "=&r"   (val)
-         SCOND_FAIL_RETRY_VARS
-       : [rwlock]      "r"     (&(rw->counter)),
-         [WR_LOCKED]   "ir"    (0)
-       : "memory", "cc");
-
-       smp_mb();
-}
-
-/* 1 - lock taken successfully */
-static inline int arch_read_trylock(arch_rwlock_t *rw)
-{
-       unsigned int val, got_it = 0;
-       SCOND_FAIL_RETRY_VAR_DEF;
-
-       smp_mb();
-
-       __asm__ __volatile__(
-       "0:     mov     %[delay], 1             \n"
-       "1:     llock   %[val], [%[rwlock]]     \n"
-       "       brls    %[val], %[WR_LOCKED], 4f\n"     /* <= 0: already write locked, bail */
-       "       sub     %[val], %[val], 1       \n"     /* counter-- */
-       "       scond   %[val], [%[rwlock]]     \n"
-       "       bz.d    4f                      \n"
-       "       mov.z   %[got_it], 1            \n"     /* got it */
-       "                                       \n"
-       SCOND_FAIL_RETRY_ASM
-
-       : [val]         "=&r"   (val),
-         [got_it]      "+&r"   (got_it)
-         SCOND_FAIL_RETRY_VARS
-       : [rwlock]      "r"     (&(rw->counter)),
-         [WR_LOCKED]   "ir"    (0)
-       : "memory", "cc");
-
-       smp_mb();
-
-       return got_it;
-}
-
-static inline void arch_write_lock(arch_rwlock_t *rw)
-{
-       unsigned int val;
-       SCOND_FAIL_RETRY_VAR_DEF;
-
-       smp_mb();
-
-       /*
-        * If reader(s) hold lock (lock < __ARCH_RW_LOCK_UNLOCKED__),
-        * deny writer. Otherwise if unlocked grant to writer
-        * Hence the claim that Linux rwlocks are unfair to writers.
-        * (can be starved for an indefinite time by readers).
-        *
-        *      if (rw->counter == __ARCH_RW_LOCK_UNLOCKED__) {
-        *              rw->counter = 0;
-        *              ret = 1;
-        *      }
-        */
-
-       __asm__ __volatile__(
-       "0:     mov     %[delay], 1             \n"
-       "1:     llock   %[val], [%[rwlock]]     \n"
-       "       brne    %[val], %[UNLOCKED], 0b \n"     /* while !UNLOCKED spin */
-       "       mov     %[val], %[WR_LOCKED]    \n"
-       "       scond   %[val], [%[rwlock]]     \n"
-       "       bz      4f                      \n"
-       "                                       \n"
-       SCOND_FAIL_RETRY_ASM
-
-       : [val]         "=&r"   (val)
-         SCOND_FAIL_RETRY_VARS
-       : [rwlock]      "r"     (&(rw->counter)),
-         [UNLOCKED]    "ir"    (__ARCH_RW_LOCK_UNLOCKED__),
-         [WR_LOCKED]   "ir"    (0)
-       : "memory", "cc");
-
-       smp_mb();
-}
-
-/* 1 - lock taken successfully */
-static inline int arch_write_trylock(arch_rwlock_t *rw)
-{
-       unsigned int val, got_it = 0;
-       SCOND_FAIL_RETRY_VAR_DEF;
-
-       smp_mb();
-
-       __asm__ __volatile__(
-       "0:     mov     %[delay], 1             \n"
-       "1:     llock   %[val], [%[rwlock]]     \n"
-       "       brne    %[val], %[UNLOCKED], 4f \n"     /* !UNLOCKED, bail */
-       "       mov     %[val], %[WR_LOCKED]    \n"
-       "       scond   %[val], [%[rwlock]]     \n"
-       "       bz.d    4f                      \n"
-       "       mov.z   %[got_it], 1            \n"     /* got it */
-       "                                       \n"
-       SCOND_FAIL_RETRY_ASM
-
-       : [val]         "=&r"   (val),
-         [got_it]      "+&r"   (got_it)
-         SCOND_FAIL_RETRY_VARS
-       : [rwlock]      "r"     (&(rw->counter)),
-         [UNLOCKED]    "ir"    (__ARCH_RW_LOCK_UNLOCKED__),
-         [WR_LOCKED]   "ir"    (0)
-       : "memory", "cc");
-
-       smp_mb();
-
-       return got_it;
-}
-
-static inline void arch_read_unlock(arch_rwlock_t *rw)
-{
-       unsigned int val;
-
-       smp_mb();
-
-       /*
-        * rw->counter++;
-        */
-       __asm__ __volatile__(
-       "1:     llock   %[val], [%[rwlock]]     \n"
-       "       add     %[val], %[val], 1       \n"
-       "       scond   %[val], [%[rwlock]]     \n"
-       "       bnz     1b                      \n"
-       "                                       \n"
-       : [val]         "=&r"   (val)
-       : [rwlock]      "r"     (&(rw->counter))
-       : "memory", "cc");
-
-       smp_mb();
-}
-
-static inline void arch_write_unlock(arch_rwlock_t *rw)
-{
-       unsigned int val;
-
-       smp_mb();
-
-       /*
-        * rw->counter = __ARCH_RW_LOCK_UNLOCKED__;
-        */
-       __asm__ __volatile__(
-       "1:     llock   %[val], [%[rwlock]]     \n"
-       "       scond   %[UNLOCKED], [%[rwlock]]\n"
-       "       bnz     1b                      \n"
-       "                                       \n"
-       : [val]         "=&r"   (val)
-       : [rwlock]      "r"     (&(rw->counter)),
-         [UNLOCKED]    "r"     (__ARCH_RW_LOCK_UNLOCKED__)
-       : "memory", "cc");
-
-       smp_mb();
-}
-
-#undef SCOND_FAIL_RETRY_VAR_DEF
-#undef SCOND_FAIL_RETRY_ASM
-#undef SCOND_FAIL_RETRY_VARS
-
-#endif /* CONFIG_ARC_STAR_9000923308 */
-
 #else  /* !CONFIG_ARC_HAS_LLSC */
 
 static inline void arch_spin_lock(arch_spinlock_t *lock)
index 3af6745..2d79e52 100644 (file)
@@ -103,7 +103,7 @@ static inline __attribute_const__ struct thread_info *current_thread_info(void)
 
 /*
  * _TIF_ALLWORK_MASK includes SYSCALL_TRACE, but we don't need it.
- * SYSCALL_TRACE is anways seperately/unconditionally tested right after a
+ * SYSCALL_TRACE is anyway seperately/unconditionally tested right after a
  * syscall, so all that reamins to be tested is _TIF_WORK_MASK
  */
 
index d1da603..a78d567 100644 (file)
@@ -32,7 +32,7 @@
 #define __kernel_ok            (segment_eq(get_fs(), KERNEL_DS))
 
 /*
- * Algorthmically, for __user_ok() we want do:
+ * Algorithmically, for __user_ok() we want do:
  *     (start < TASK_SIZE) && (start+len < TASK_SIZE)
  * where TASK_SIZE could either be retrieved from thread_info->addr_limit or
  * emitted directly in code.
index 095599a..71f3918 100644 (file)
@@ -74,7 +74,7 @@
        __tmp ^ __in;                                           \
 })
 
-#elif (ARC_BSWAP_TYPE == 2)    /* Custom single cycle bwap instruction */
+#elif (ARC_BSWAP_TYPE == 2)    /* Custom single cycle bswap instruction */
 
 #define __arch_swab32(x)                                               \
 ({                                                                     \
index 0cb0aba..98812c1 100644 (file)
@@ -91,27 +91,13 @@ VECTOR   mem_service             ; 0x8, Mem exception   (0x1)
 VECTOR   instr_service           ; 0x10, Instrn Error   (0x2)
 
 ; ******************** Device ISRs **********************
-#ifdef CONFIG_ARC_IRQ3_LV2
-VECTOR   handle_interrupt_level2
-#else
-VECTOR   handle_interrupt_level1
-#endif
-
-VECTOR   handle_interrupt_level1
-
-#ifdef CONFIG_ARC_IRQ5_LV2
-VECTOR   handle_interrupt_level2
-#else
-VECTOR   handle_interrupt_level1
-#endif
-
-#ifdef CONFIG_ARC_IRQ6_LV2
+#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
 VECTOR   handle_interrupt_level2
 #else
 VECTOR   handle_interrupt_level1
 #endif
 
-.rept   25
+.rept   28
 VECTOR   handle_interrupt_level1 ; Other devices
 .endr
 
index c5cceca..ce9deb9 100644 (file)
@@ -28,10 +28,8 @@ void arc_init_IRQ(void)
 {
        int level_mask = 0;
 
-       /* setup any high priority Interrupts (Level2 in ARCompact jargon) */
-       level_mask |= IS_ENABLED(CONFIG_ARC_IRQ3_LV2) << 3;
-       level_mask |= IS_ENABLED(CONFIG_ARC_IRQ5_LV2) << 5;
-       level_mask |= IS_ENABLED(CONFIG_ARC_IRQ6_LV2) << 6;
+       /* Is timer high priority Interrupt (Level2 in ARCompact jargon) */
+       level_mask |= IS_ENABLED(CONFIG_ARC_COMPACT_IRQ_LEVELS) << TIMER0_IRQ;
 
        /*
         * Write to register, even if no LV2 IRQs configured to reset it
index 6fd4802..08f03d9 100644 (file)
@@ -108,7 +108,7 @@ static void arc_perf_event_update(struct perf_event *event,
        int64_t delta = new_raw_count - prev_raw_count;
 
        /*
-        * We don't afaraid of hwc->prev_count changing beneath our feet
+        * We aren't afraid of hwc->prev_count changing beneath our feet
         * because there's no way for us to re-enter this function anytime.
         */
        local64_set(&hwc->prev_count, new_raw_count);
index f63b8bf..2ee7a4d 100644 (file)
@@ -392,7 +392,7 @@ void __init setup_arch(char **cmdline_p)
                /*
                 * If we are here, it is established that @uboot_arg didn't
                 * point to DT blob. Instead if u-boot says it is cmdline,
-                * Appent to embedded DT cmdline.
+                * append to embedded DT cmdline.
                 * setup_machine_fdt() would have populated @boot_command_line
                 */
                if (uboot_tag == 1) {
index 004b7f0..6cb3736 100644 (file)
@@ -34,7 +34,7 @@
  *  -ViXS were still seeing crashes when using insmod to load drivers.
  *   It turned out that the code to change Execute permssions for TLB entries
  *   of user was not guarded for interrupts (mod_tlb_permission)
- *   This was cauing TLB entries to be overwritten on unrelated indexes
+ *   This was causing TLB entries to be overwritten on unrelated indexes
  *
  * Vineetg: July 15th 2008: Bug #94183
  *  -Exception happens in Delay slot of a JMP, and before user space resumes,
index a6f91e8..934150e 100644 (file)
@@ -276,7 +276,7 @@ static int tlb_stats_open(struct inode *inode, struct file *file)
        return 0;
 }
 
-/* called on user read(): display the couters */
+/* called on user read(): display the counters */
 static ssize_t tlb_stats_output(struct file *file,     /* file descriptor */
                                char __user *user_buf,  /* user buffer */
                                size_t len,             /* length of buffer */
index 9e5eddb..5a294b2 100644 (file)
@@ -215,7 +215,7 @@ slc_chk:
  * ------------------
  * This ver of MMU supports variable page sizes (1k-16k): although Linux will
  * only support 8k (default), 16k and 4k.
- * However from hardware perspective, smaller page sizes aggrevate aliasing
+ * However from hardware perspective, smaller page sizes aggravate aliasing
  * meaning more vaddr bits needed to disambiguate the cache-line-op ;
  * the existing scheme of piggybacking won't work for certain configurations.
  * Two new registers IC_PTAG and DC_PTAG inttoduced.
@@ -302,7 +302,7 @@ void __cache_line_loop_v3(phys_addr_t paddr, unsigned long vaddr,
 
        /*
         * This is technically for MMU v4, using the MMU v3 programming model
-        * Special work for HS38 aliasing I-cache configuratino with PAE40
+        * Special work for HS38 aliasing I-cache configuration with PAE40
         *   - upper 8 bits of paddr need to be written into PTAG_HI
         *   - (and needs to be written before the lower 32 bits)
         * Note that PTAG_HI is hoisted outside the line loop
@@ -936,7 +936,7 @@ void arc_cache_init(void)
                              ic->ver, CONFIG_ARC_MMU_VER);
 
                /*
-                * In MMU v4 (HS38x) the alising icache config uses IVIL/PTAG
+                * In MMU v4 (HS38x) the aliasing icache config uses IVIL/PTAG
                 * pair to provide vaddr/paddr respectively, just as in MMU v3
                 */
                if (is_isa_arcv2() && ic->alias)
index 8c8e36f..73d7e4c 100644 (file)
@@ -10,7 +10,7 @@
  * DMA Coherent API Notes
  *
  * I/O is inherently non-coherent on ARC. So a coherent DMA buffer is
- * implemented by accessintg it using a kernel virtual address, with
+ * implemented by accessing it using a kernel virtual address, with
  * Cache bit off in the TLB entry.
  *
  * The default DMA address == Phy address which is 0x8000_0000 based.
index 06b6c2d..414b427 100644 (file)
@@ -741,6 +741,7 @@ dtb-$(CONFIG_MACH_SUN7I) += \
        sun7i-a20-olimex-som-evb.dtb \
        sun7i-a20-olinuxino-lime.dtb \
        sun7i-a20-olinuxino-lime2.dtb \
+       sun7i-a20-olinuxino-lime2-emmc.dtb \
        sun7i-a20-olinuxino-micro.dtb \
        sun7i-a20-orangepi.dtb \
        sun7i-a20-orangepi-mini.dtb \
index d82dd6e..5687d6b 100644 (file)
        status = "okay";
        pinctrl-names = "default";
        pinctrl-0 = <&i2c0_pins>;
-       clock-frequency = <400000>;
+       clock-frequency = <100000>;
 
        tps@24 {
                compatible = "ti,tps65218";
index b01a594..0e63b9d 100644 (file)
 
                tps659038_pmic {
                        compatible = "ti,tps659038-pmic";
+
+                       smps12-in-supply = <&vmain>;
+                       smps3-in-supply = <&vmain>;
+                       smps45-in-supply = <&vmain>;
+                       smps6-in-supply = <&vmain>;
+                       smps7-in-supply = <&vmain>;
+                       smps8-in-supply = <&vmain>;
+                       smps9-in-supply = <&vmain>;
+                       ldo1-in-supply = <&vmain>;
+                       ldo2-in-supply = <&vmain>;
+                       ldo3-in-supply = <&vmain>;
+                       ldo4-in-supply = <&vmain>;
+                       ldo9-in-supply = <&vmain>;
+                       ldoln-in-supply = <&vmain>;
+                       ldousb-in-supply = <&vmain>;
+                       ldortc-in-supply = <&vmain>;
+
                        regulators {
                                smps12_reg: smps12 {
                                        /* VDD_MPU */
-                                       vin-supply = <&vmain>;
                                        regulator-name = "smps12";
                                        regulator-min-microvolt = <850000>;
                                        regulator-max-microvolt = <1250000>;
@@ -73,7 +89,6 @@
 
                                smps3_reg: smps3 {
                                        /* VDD_DDR EMIF1 EMIF2 */
-                                       vin-supply = <&vmain>;
                                        regulator-name = "smps3";
                                        regulator-min-microvolt = <1350000>;
                                        regulator-max-microvolt = <1350000>;
@@ -84,7 +99,6 @@
                                smps45_reg: smps45 {
                                        /* VDD_DSPEVE on AM572 */
                                        /* VDD_IVA + VDD_DSP on AM571 */
-                                       vin-supply = <&vmain>;
                                        regulator-name = "smps45";
                                        regulator-min-microvolt = <850000>;
                                        regulator-max-microvolt = <1250000>;
 
                                smps6_reg: smps6 {
                                        /* VDD_GPU */
-                                       vin-supply = <&vmain>;
                                        regulator-name = "smps6";
                                        regulator-min-microvolt = <850000>;
                                        regulator-max-microvolt = <1250000>;
 
                                smps7_reg: smps7 {
                                        /* VDD_CORE */
-                                       vin-supply = <&vmain>;
                                        regulator-name = "smps7";
                                        regulator-min-microvolt = <850000>;
                                        regulator-max-microvolt = <1150000>;
                                smps8_reg: smps8 {
                                        /* 5728 - VDD_IVAHD */
                                        /* 5718 - N.C. test point */
-                                       vin-supply = <&vmain>;
                                        regulator-name = "smps8";
                                };
 
                                smps9_reg: smps9 {
                                        /* VDD_3_3D */
-                                       vin-supply = <&vmain>;
                                        regulator-name = "smps9";
                                        regulator-min-microvolt = <3300000>;
                                        regulator-max-microvolt = <3300000>;
                                ldo1_reg: ldo1 {
                                        /* VDDSHV8 - VSDMMC  */
                                        /* NOTE: on rev 1.3a, data supply */
-                                       vin-supply = <&vmain>;
                                        regulator-name = "ldo1";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <3300000>;
 
                                ldo2_reg: ldo2 {
                                        /* VDDSH18V */
-                                       vin-supply = <&vmain>;
                                        regulator-name = "ldo2";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <1800000>;
 
                                ldo3_reg: ldo3 {
                                        /* R1.3a 572x V1_8PHY_LDO3: USB, SATA */
-                                       vin-supply = <&vmain>;
                                        regulator-name = "ldo3";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <1800000>;
 
                                ldo4_reg: ldo4 {
                                        /* R1.3a 572x V1_8PHY_LDO4: PCIE, HDMI*/
-                                       vin-supply = <&vmain>;
                                        regulator-name = "ldo4";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <1800000>;
 
                                ldo9_reg: ldo9 {
                                        /* VDD_RTC  */
-                                       vin-supply = <&vmain>;
                                        regulator-name = "ldo9";
                                        regulator-min-microvolt = <840000>;
                                        regulator-max-microvolt = <1160000>;
 
                                ldoln_reg: ldoln {
                                        /* VDDA_1V8_PLL */
-                                       vin-supply = <&vmain>;
                                        regulator-name = "ldoln";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <1800000>;
 
                                ldousb_reg: ldousb {
                                        /* VDDA_3V_USB: VDDA_USBHS33 */
-                                       vin-supply = <&vmain>;
                                        regulator-name = "ldousb";
                                        regulator-min-microvolt = <3300000>;
                                        regulator-max-microvolt = <3300000>;
 
                                ldortc_reg: ldortc {
                                        /* VDDA_RTC  */
-                                       vin-supply = <&vmain>;
                                        regulator-name = "ldortc";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <1800000>;
index cbc17b0..4128fa9 100644 (file)
        };
 };
 
+&mmc1 {
+        status = "disabled";
+};
+
 &mmc2 {
        pinctrl-names = "default";
        pinctrl-0 = <&sd1_pins>;
        cd-gpios = <&gpio2 6 GPIO_ACTIVE_LOW>;
 };
 
+&mmc3 {
+        status = "disabled";
+};
+
 &pincntl {
        sd1_pins: pinmux_sd1_pins {
                pinctrl-single,pins = <
index 5d4313f..3f18486 100644 (file)
        phy-mode = "rgmii";
 };
 
+&mmc1 {
+       status = "disabled";
+};
+
+&mmc2 {
+       status = "disabled";
+};
+
 &mmc3 {
        pinctrl-names = "default";
        pinctrl-0 = <&sd2_pins>;
@@ -53,6 +61,7 @@
        dmas = <&edma_xbar 8 0 1        /* use SDTXEVT1 instead of MCASP0TX */
                &edma_xbar 9 0 2>;      /* use SDRXEVT1 instead of MCASP0RX */
        dma-names = "tx", "rx";
+       non-removable;
 };
 
 &pincntl {
index e007401..3a8f397 100644 (file)
                        ti,hwmods = "gpmc";
                        reg = <0x50000000 0x37c>;      /* device IO registers */
                        interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+                       dmas = <&edma_xbar 4 0>;
+                       dma-names = "rxtx";
                        gpmc,num-cs = <8>;
                        gpmc,num-waitpins = <2>;
                        #address-cells = <2>;
index 4220eef..5e06020 100644 (file)
        reg = <0x58000000 0x80>,
              <0x58004054 0x4>,
              <0x58004300 0x20>,
-             <0x58005054 0x4>,
-             <0x58005300 0x20>;
+             <0x58009054 0x4>,
+             <0x58009300 0x20>;
        reg-names = "dss", "pll1_clkctrl", "pll1",
                    "pll2_clkctrl", "pll2";
 
index ddfe1f5..fa14f77 100644 (file)
        hpd-gpios = <&gpx0 7 GPIO_ACTIVE_HIGH>;
 
        ports {
-               port0 {
+               port {
                        dp_out: endpoint {
                                remote-endpoint = <&bridge_in>;
                        };
                edid-emulation = <5>;
 
                ports {
-                       port0 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       port@0 {
+                               reg = <0>;
+
                                bridge_out: endpoint {
                                        remote-endpoint = <&panel_in>;
                                };
                        };
 
-                       port1 {
+                       port@1 {
+                               reg = <1>;
+
                                bridge_in: endpoint {
                                        remote-endpoint = <&dp_out>;
                                };
index f9d2e4f..1de972d 100644 (file)
        hpd-gpios = <&gpx2 6 GPIO_ACTIVE_HIGH>;
 
        ports {
-               port0 {
+               port {
                        dp_out: endpoint {
                                remote-endpoint = <&bridge_in>;
                        };
                use-external-pwm;
 
                ports {
-                       port0 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       port@0 {
+                               reg = <0>;
+
                                bridge_out: endpoint {
                                        remote-endpoint = <&panel_in>;
                                };
                        };
 
-                       port1 {
+                       port@1 {
+                               reg = <1>;
+
                                bridge_in: endpoint {
                                        remote-endpoint = <&dp_out>;
                                };
index 76056ba..ed44982 100644 (file)
@@ -85,7 +85,7 @@
                        OMAP3_CORE1_IOPAD(0x2158, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_clk.sdmmc2_clk */
                        OMAP3_CORE1_IOPAD(0x215a, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_cmd.sdmmc2_cmd */
                        OMAP3_CORE1_IOPAD(0x215c, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat0.sdmmc2_dat0 */
-                       OMAP3_CORE1_IOPAD(0x215e, WAKEUP_EN | PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat1.sdmmc2_dat1 */
+                       OMAP3_CORE1_IOPAD(0x215e, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat1.sdmmc2_dat1 */
                        OMAP3_CORE1_IOPAD(0x2160, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat2.sdmmc2_dat2 */
                        OMAP3_CORE1_IOPAD(0x2162, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat3.sdmmc2_dat3 */
                >;
index 41f5d38..f4f2ce4 100644 (file)
        vmmc-supply = <&vmmc1>;
        vmmc_aux-supply = <&vsim>;
        bus-width = <4>;
+       cd-gpios = <&twl_gpio 0 GPIO_ACTIVE_LOW>;
 };
 
 &mmc3 {
index d6f839c..b697106 100644 (file)
                        OMAP3630_CORE2_IOPAD(0x25f8, PIN_OUTPUT | MUX_MODE4) /* etk_d14.gpio_28 */
                >;
        };
+
+       mmc1_wp_pins: pinmux_mmc1_cd_pins {
+               pinctrl-single,pins = <
+                       OMAP3630_CORE2_IOPAD(0x25fa, PIN_INPUT | MUX_MODE4)   /* etk_d15.gpio_29 */
+               >;
+       };
 };
 
 &i2c3 {
                };
        };
 };
+
+&mmc1 {
+       pinctrl-0 = <&mmc1_pins &mmc1_wp_pins>;
+       wp-gpios = <&gpio1 29 GPIO_ACTIVE_LOW>; /* gpio_29 */
+};
index d9e2d9c..2b74a81 100644 (file)
                pinctrl-single,pins = <
                        OMAP3_CORE1_IOPAD(0x2180, PIN_INPUT_PULLUP | MUX_MODE1) /* ssi1_rdy_tx */
                        OMAP3_CORE1_IOPAD(0x217e, PIN_OUTPUT | MUX_MODE1)               /* ssi1_flag_tx */
-                       OMAP3_CORE1_IOPAD(0x2182, PIN_INPUT | WAKEUP_EN | MUX_MODE4) /* ssi1_wake_tx (cawake) */
+                       OMAP3_CORE1_IOPAD(0x2182, PIN_INPUT | MUX_MODE4)                /* ssi1_wake_tx (cawake) */
                        OMAP3_CORE1_IOPAD(0x217c, PIN_OUTPUT | MUX_MODE1)               /* ssi1_dat_tx */
                        OMAP3_CORE1_IOPAD(0x2184, PIN_INPUT | MUX_MODE1)                /* ssi1_dat_rx */
                        OMAP3_CORE1_IOPAD(0x2186, PIN_INPUT | MUX_MODE1)                /* ssi1_flag_rx */
        modem_pins: pinmux_modem {
                pinctrl-single,pins = <
                        OMAP3_CORE1_IOPAD(0x20dc, PIN_OUTPUT | MUX_MODE4)               /* gpio 70 => cmt_apeslpx */
-                       OMAP3_CORE1_IOPAD(0x20e0, PIN_INPUT | WAKEUP_EN | MUX_MODE4) /* gpio 72 => ape_rst_rq */
+                       OMAP3_CORE1_IOPAD(0x20e0, PIN_INPUT | MUX_MODE4)                /* gpio 72 => ape_rst_rq */
                        OMAP3_CORE1_IOPAD(0x20e2, PIN_OUTPUT | MUX_MODE4)               /* gpio 73 => cmt_rst_rq */
                        OMAP3_CORE1_IOPAD(0x20e4, PIN_OUTPUT | MUX_MODE4)               /* gpio 74 => cmt_en */
                        OMAP3_CORE1_IOPAD(0x20e6, PIN_OUTPUT | MUX_MODE4)               /* gpio 75 => cmt_rst */
index a00ca76..927b17f 100644 (file)
@@ -97,7 +97,7 @@
                        OMAP3_CORE1_IOPAD(0x217c, PIN_OUTPUT | MUX_MODE1)            /* ssi1_dat_tx */
                        OMAP3_CORE1_IOPAD(0x217e, PIN_OUTPUT | MUX_MODE1)            /* ssi1_flag_tx */
                        OMAP3_CORE1_IOPAD(0x2180, PIN_INPUT_PULLUP | MUX_MODE1)      /* ssi1_rdy_tx */
-                       OMAP3_CORE1_IOPAD(0x2182, PIN_INPUT | WAKEUP_EN | MUX_MODE4) /* ssi1_wake_tx (cawake) */
+                       OMAP3_CORE1_IOPAD(0x2182, PIN_INPUT | MUX_MODE4)        /* ssi1_wake_tx (cawake) */
                        OMAP3_CORE1_IOPAD(0x2184, PIN_INPUT | MUX_MODE1)             /* ssi1_dat_rx */
                        OMAP3_CORE1_IOPAD(0x2186, PIN_INPUT | MUX_MODE1)             /* ssi1_flag_rx */
                        OMAP3_CORE1_IOPAD(0x2188, PIN_OUTPUT | MUX_MODE1)            /* ssi1_rdy_rx */
                        OMAP3_CORE1_IOPAD(0x217c, PIN_OUTPUT | MUX_MODE7)            /* ssi1_dat_tx */
                        OMAP3_CORE1_IOPAD(0x217e, PIN_OUTPUT | MUX_MODE7)            /* ssi1_flag_tx */
                        OMAP3_CORE1_IOPAD(0x2180, PIN_INPUT_PULLDOWN | MUX_MODE7)    /* ssi1_rdy_tx */
-                       OMAP3_CORE1_IOPAD(0x2182, PIN_INPUT | WAKEUP_EN | MUX_MODE4) /* ssi1_wake_tx (cawake) */
+                       OMAP3_CORE1_IOPAD(0x2182, PIN_INPUT | MUX_MODE4)        /* ssi1_wake_tx (cawake) */
                        OMAP3_CORE1_IOPAD(0x2184, PIN_INPUT | MUX_MODE7)             /* ssi1_dat_rx */
                        OMAP3_CORE1_IOPAD(0x2186, PIN_INPUT | MUX_MODE7)             /* ssi1_flag_rx */
                        OMAP3_CORE1_IOPAD(0x2188, PIN_OUTPUT | MUX_MODE4)            /* ssi1_rdy_rx */
 
        modem_pins1: pinmux_modem_core1_pins {
                pinctrl-single,pins = <
-                       OMAP3_CORE1_IOPAD(0x207a, PIN_INPUT | WAKEUP_EN | MUX_MODE4) /* gpio_34 (ape_rst_rq) */
+                       OMAP3_CORE1_IOPAD(0x207a, PIN_INPUT | MUX_MODE4)        /* gpio_34 (ape_rst_rq) */
                        OMAP3_CORE1_IOPAD(0x2100, PIN_OUTPUT | MUX_MODE4)            /* gpio_88 (cmt_rst_rq) */
                        OMAP3_CORE1_IOPAD(0x210a, PIN_OUTPUT | MUX_MODE4)            /* gpio_93 (cmt_apeslpx) */
                >;
index f19170b..c29b41d 100644 (file)
@@ -98,7 +98,7 @@
                pinctrl-single,pins = <
                         OMAP3_CORE1_IOPAD(0x2174, PIN_INPUT_PULLUP | MUX_MODE0)        /* uart2_cts.uart2_cts */
                         OMAP3_CORE1_IOPAD(0x2176, PIN_OUTPUT | MUX_MODE0)              /* uart2_rts.uart2_rts */
-                        OMAP3_CORE1_IOPAD(0x217a, WAKEUP_EN | PIN_INPUT | MUX_MODE0) /* uart2_rx.uart2_rx */
+                        OMAP3_CORE1_IOPAD(0x217a, PIN_INPUT | MUX_MODE0)               /* uart2_rx.uart2_rx */
                         OMAP3_CORE1_IOPAD(0x2178, PIN_OUTPUT | MUX_MODE0)              /* uart2_tx.uart2_tx */
                >;
        };
                pinctrl-single,pins = <
                         OMAP3_CORE1_IOPAD(0x219a, PIN_INPUT_PULLDOWN | MUX_MODE0)      /* uart3_cts_rctx.uart3_cts_rctx */
                         OMAP3_CORE1_IOPAD(0x219c, PIN_OUTPUT | MUX_MODE0)              /* uart3_rts_sd.uart3_rts_sd */
-                        OMAP3_CORE1_IOPAD(0x219e, WAKEUP_EN | PIN_INPUT | MUX_MODE0) /* uart3_rx_irrx.uart3_rx_irrx */
+                        OMAP3_CORE1_IOPAD(0x219e, PIN_INPUT | MUX_MODE0)               /* uart3_rx_irrx.uart3_rx_irrx */
                         OMAP3_CORE1_IOPAD(0x21a0, PIN_OUTPUT | MUX_MODE0)              /* uart3_tx_irtx.uart3_tx_irtx */
                >;
        };
                pinctrl-single,pins = <
                        OMAP3630_CORE2_IOPAD(0x25d8, PIN_INPUT_PULLUP | MUX_MODE2)      /* etk_clk.sdmmc3_clk */
                        OMAP3630_CORE2_IOPAD(0x25e4, PIN_INPUT_PULLUP | MUX_MODE2)      /* etk_d4.sdmmc3_dat0 */
-                       OMAP3630_CORE2_IOPAD(0x25e6, WAKEUP_EN | PIN_INPUT_PULLUP | MUX_MODE2) /* etk_d5.sdmmc3_dat1 */
+                       OMAP3630_CORE2_IOPAD(0x25e6, PIN_INPUT_PULLUP | MUX_MODE2)      /* etk_d5.sdmmc3_dat1 */
                        OMAP3630_CORE2_IOPAD(0x25e8, PIN_INPUT_PULLUP | MUX_MODE2)      /* etk_d6.sdmmc3_dat2 */
                        OMAP3630_CORE2_IOPAD(0x25e2, PIN_INPUT_PULLUP | MUX_MODE2)      /* etk_d3.sdmmc3_dat3 */
                >;
index dc759a3..5d5b620 100644 (file)
                display0 = &hdmi0;
        };
 
+       vmain: fixedregulator-vmain {
+               compatible = "regulator-fixed";
+               regulator-name = "vmain";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+       };
+
+       vsys_cobra: fixedregulator-vsys_cobra {
+               compatible = "regulator-fixed";
+               regulator-name = "vsys_cobra";
+               vin-supply = <&vmain>;
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+       };
+
+       vdds_1v8_main: fixedregulator-vdds_1v8_main {
+               compatible = "regulator-fixed";
+               regulator-name = "vdds_1v8_main";
+               vin-supply = <&smps7_reg>;
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+       };
+
        vmmcsd_fixed: fixedregulator-mmcsd {
                compatible = "regulator-fixed";
                regulator-name = "vmmcsd_fixed";
 
        wlcore_irq_pin: pinmux_wlcore_irq_pin {
                pinctrl-single,pins = <
-                       OMAP5_IOPAD(0x40, WAKEUP_EN | PIN_INPUT_PULLUP | MUX_MODE6)     /* llia_wakereqin.gpio1_wk14 */
+                       OMAP5_IOPAD(0x40, PIN_INPUT_PULLUP | MUX_MODE6) /* llia_wakereqin.gpio1_wk14 */
                >;
        };
 };
 
                        ti,ldo6-vibrator;
 
+                       smps123-in-supply = <&vsys_cobra>;
+                       smps45-in-supply = <&vsys_cobra>;
+                       smps6-in-supply = <&vsys_cobra>;
+                       smps7-in-supply = <&vsys_cobra>;
+                       smps8-in-supply = <&vsys_cobra>;
+                       smps9-in-supply = <&vsys_cobra>;
+                       smps10_out2-in-supply = <&vsys_cobra>;
+                       smps10_out1-in-supply = <&vsys_cobra>;
+                       ldo1-in-supply = <&vsys_cobra>;
+                       ldo2-in-supply = <&vsys_cobra>;
+                       ldo3-in-supply = <&vdds_1v8_main>;
+                       ldo4-in-supply = <&vdds_1v8_main>;
+                       ldo5-in-supply = <&vsys_cobra>;
+                       ldo6-in-supply = <&vdds_1v8_main>;
+                       ldo7-in-supply = <&vsys_cobra>;
+                       ldo8-in-supply = <&vsys_cobra>;
+                       ldo9-in-supply = <&vmmcsd_fixed>;
+                       ldoln-in-supply = <&vsys_cobra>;
+                       ldousb-in-supply = <&vsys_cobra>;
+
                        regulators {
                                smps123_reg: smps123 {
                                        /* VDD_OPP_MPU */
                pinctrl-0 = <&twl6040_pins>;
 
                interrupts = <GIC_SPI 119 IRQ_TYPE_NONE>; /* IRQ_SYS_2N cascaded to gic */
-               ti,audpwron-gpio = <&gpio5 13 GPIO_ACTIVE_HIGH>;  /* gpio line 141 */
+
+               /* audpwron gpio defined in the board specific dts */
 
                vio-supply = <&smps7_reg>;
                v2v1-supply = <&smps9_reg>;
index 46ecb1d..f75ce02 100644 (file)
        };
 };
 
+/* LDO4 is VPP1 - ball AD9 */
+&ldo4_reg {
+       regulator-min-microvolt = <2000000>;
+       regulator-max-microvolt = <2000000>;
+};
+
+/*
+ * LDO7 is used for HDMI: VDDA_DSIPORTA - ball AA33, VDDA_DSIPORTC - ball AE33,
+ * VDDA_HDMI - ball AN25
+ */
+&ldo7_reg {
+       status = "okay";
+       regulator-min-microvolt = <1800000>;
+       regulator-max-microvolt = <1800000>;
+};
+
 &omap5_pmx_core {
        i2c4_pins: pinmux_i2c4_pins {
                pinctrl-single,pins = <
                <&gpio7 3 0>;           /* 195, SDA */
 };
 
+&twl6040 {
+       ti,audpwron-gpio = <&gpio5 16 GPIO_ACTIVE_HIGH>;  /* gpio line 144 */
+};
+
+&twl6040_pins {
+       pinctrl-single,pins = <
+               OMAP5_IOPAD(0x1c4, PIN_OUTPUT | MUX_MODE6)      /* mcspi1_somi.gpio5_144 */
+               OMAP5_IOPAD(0x1ca, PIN_OUTPUT | MUX_MODE6)      /* perslimbus2_clock.gpio5_145 */
+       >;
+};
index 60b3fbb..a51e605 100644 (file)
                <&gpio9 1 GPIO_ACTIVE_HIGH>,    /* TCA6424A P00, LS OE */
                <&gpio7 1 GPIO_ACTIVE_HIGH>;    /* GPIO 193, HPD */
 };
+
+&twl6040 {
+       ti,audpwron-gpio = <&gpio5 13 GPIO_ACTIVE_HIGH>;  /* gpio line 141 */
+};
+
+&twl6040_pins {
+       pinctrl-single,pins = <
+               OMAP5_IOPAD(0x1be, PIN_OUTPUT | MUX_MODE6)      /* mcspi1_somi.gpio5_141 */
+       >;
+};
index a3601e4..b844473 100644 (file)
 &gmac1 {
        status = "okay";
        phy-mode = "rgmii";
+       phy-handle = <&phy1>;
 
        snps,reset-gpio = <&porta 0 GPIO_ACTIVE_LOW>;
        snps,reset-active-low;
index ad8ba10..d294e82 100644 (file)
                        compatible = "shared-dma-pool";
                        reg = <0x40000000 0x01000000>;
                        no-map;
+                       status = "disabled";
                };
 
                gp1_reserved: rproc@41000000 {
                        compatible = "shared-dma-pool";
                        reg = <0x41000000 0x01000000>;
                        no-map;
+                       status = "disabled";
                };
 
                audio_reserved: rproc@42000000 {
                        compatible = "shared-dma-pool";
                        reg = <0x42000000 0x01000000>;
                        no-map;
+                       status = "disabled";
                };
 
                dmu_reserved: rproc@43000000 {
index 68b479b..73c133f 100644 (file)
 };
 
 &reg_dc1sw {
-       regulator-min-microvolt = <3000000>;
-       regulator-max-microvolt = <3000000>;
        regulator-name = "vcc-lcd";
 };
 
index 360adfb..d6ad619 100644 (file)
 
 &reg_dc1sw {
        regulator-name = "vcc-lcd-usb2";
-       regulator-min-microvolt = <3000000>;
-       regulator-max-microvolt = <3000000>;
 };
 
 &reg_dc5ldo {
index 10f49ab..47195e8 100644 (file)
@@ -82,6 +82,7 @@ CONFIG_TOUCHSCREEN_MMS114=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_MAX77693_HAPTIC=y
 CONFIG_INPUT_MAX8997_HAPTIC=y
+CONFIG_KEYBOARD_SAMSUNG=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_SAMSUNG=y
 CONFIG_SERIAL_SAMSUNG_CONSOLE=y
index 8f85756..8a5fff1 100644 (file)
@@ -264,6 +264,7 @@ CONFIG_KEYBOARD_TEGRA=y
 CONFIG_KEYBOARD_SPEAR=y
 CONFIG_KEYBOARD_ST_KEYSCAN=y
 CONFIG_KEYBOARD_CROS_EC=m
+CONFIG_KEYBOARD_SAMSUNG=m
 CONFIG_MOUSE_PS2_ELANTECH=y
 CONFIG_MOUSE_CYAPA=m
 CONFIG_MOUSE_ELAN_I2C=y
index 19cfab5..20febb3 100644 (file)
@@ -29,7 +29,7 @@
 
 static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
 {
-       return (pmd_t *)get_zeroed_page(GFP_KERNEL | __GFP_REPEAT);
+       return (pmd_t *)get_zeroed_page(GFP_KERNEL);
 }
 
 static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
index aeddd28..92fd2c8 100644 (file)
@@ -193,6 +193,7 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
 
 #define pmd_large(pmd)         (pmd_val(pmd) & 2)
 #define pmd_bad(pmd)           (pmd_val(pmd) & 2)
+#define pmd_present(pmd)       (pmd_val(pmd))
 
 #define copy_pmd(pmdpd,pmdps)          \
        do {                            \
index fa70db7..2a029bc 100644 (file)
@@ -211,6 +211,7 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
                                                : !!(pmd_val(pmd) & (val)))
 #define pmd_isclear(pmd, val)  (!(pmd_val(pmd) & (val)))
 
+#define pmd_present(pmd)       (pmd_isset((pmd), L_PMD_SECT_VALID))
 #define pmd_young(pmd)         (pmd_isset((pmd), PMD_SECT_AF))
 #define pte_special(pte)       (pte_isset((pte), L_PTE_SPECIAL))
 static inline pte_t pte_mkspecial(pte_t pte)
@@ -249,10 +250,10 @@ PMD_BIT_FUNC(mkyoung,   |= PMD_SECT_AF);
 #define pfn_pmd(pfn,prot)      (__pmd(((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot)))
 #define mk_pmd(page,prot)      pfn_pmd(page_to_pfn(page),prot)
 
-/* represent a notpresent pmd by zero, this is used by pmdp_invalidate */
+/* represent a notpresent pmd by faulting entry, this is used by pmdp_invalidate */
 static inline pmd_t pmd_mknotpresent(pmd_t pmd)
 {
-       return __pmd(0);
+       return __pmd(pmd_val(pmd) & ~L_PMD_SECT_VALID);
 }
 
 static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
index 348caab..d622040 100644 (file)
@@ -182,7 +182,6 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
 #define pgd_offset_k(addr)     pgd_offset(&init_mm, addr)
 
 #define pmd_none(pmd)          (!pmd_val(pmd))
-#define pmd_present(pmd)       (pmd_val(pmd))
 
 static inline pte_t *pmd_page_vaddr(pmd_t pmd)
 {
index ef9119f..4d93758 100644 (file)
@@ -733,8 +733,8 @@ static int vfp_set(struct task_struct *target,
        if (ret)
                return ret;
 
-       vfp_flush_hwstate(thread);
        thread->vfpstate.hard = new_vfp;
+       vfp_flush_hwstate(thread);
 
        return 0;
 }
index df90bc5..8615216 100644 (file)
@@ -486,7 +486,7 @@ static const char *ipi_types[NR_IPI] __tracepoint_string = {
 
 static void smp_cross_call(const struct cpumask *target, unsigned int ipinr)
 {
-       trace_ipi_raise(target, ipi_types[ipinr]);
+       trace_ipi_raise_rcuidle(target, ipi_types[ipinr]);
        __smp_cross_call(target, ipinr);
 }
 
index e65aa7d..20dcf6e 100644 (file)
@@ -61,7 +61,6 @@ config ARCH_EXYNOS4
        select CLKSRC_SAMSUNG_PWM if CPU_EXYNOS4210
        select CPU_EXYNOS4210
        select GIC_NON_BANKED
-       select KEYBOARD_SAMSUNG if INPUT_KEYBOARD
        select MIGHT_HAVE_CACHE_L2X0
        help
          Samsung EXYNOS4 (Cortex-A9) SoC based systems
index a38b16b..b56de4b 100644 (file)
@@ -46,7 +46,7 @@ static int ksz8081_phy_fixup(struct phy_device *dev)
 static void __init imx6ul_enet_phy_init(void)
 {
        if (IS_BUILTIN(CONFIG_PHYLIB))
-               phy_register_fixup_for_uid(PHY_ID_KSZ8081, 0xffffffff,
+               phy_register_fixup_for_uid(PHY_ID_KSZ8081, MICREL_PHY_ID_MASK,
                                           ksz8081_phy_fixup);
 }
 
index 5d7fb59..bf60844 100644 (file)
@@ -43,8 +43,8 @@
 #define OTHERS_MASK                    (MODEM_IRQ_MASK | HOOK_SWITCH_MASK)
 
 /* IRQ handler register bitmasks */
-#define DEFERRED_FIQ_MASK              (0x1 << (INT_DEFERRED_FIQ % IH2_BASE))
-#define GPIO_BANK1_MASK                (0x1 << INT_GPIO_BANK1)
+#define DEFERRED_FIQ_MASK              OMAP_IRQ_BIT(INT_DEFERRED_FIQ)
+#define GPIO_BANK1_MASK                OMAP_IRQ_BIT(INT_GPIO_BANK1)
 
 /* Driver buffer byte offsets */
 #define BUF_MASK                       (FIQ_MASK * 4)
@@ -110,7 +110,7 @@ ENTRY(qwerty_fiqin_start)
        mov r8, #2                              @ reset FIQ agreement
        str r8, [r12, #IRQ_CONTROL_REG_OFFSET]
 
-       cmp r10, #INT_GPIO_BANK1                @ is it GPIO bank interrupt?
+       cmp r10, #(INT_GPIO_BANK1 - NR_IRQS_LEGACY)     @ is it GPIO interrupt?
        beq gpio                                @ yes - process it
 
        mov r8, #1
index d1f1209..ec760ae 100644 (file)
@@ -109,7 +109,8 @@ void __init ams_delta_init_fiq(void)
         * Since no set_type() method is provided by OMAP irq chip,
         * switch to edge triggered interrupt type manually.
         */
-       offset = IRQ_ILR0_REG_OFFSET + INT_DEFERRED_FIQ * 0x4;
+       offset = IRQ_ILR0_REG_OFFSET +
+                       ((INT_DEFERRED_FIQ - NR_IRQS_LEGACY) & 0x1f) * 0x4;
        val = omap_readl(DEFERRED_FIQ_IH_BASE + offset) & ~(1 << 1);
        omap_writel(val, DEFERRED_FIQ_IH_BASE + offset);
 
@@ -149,7 +150,7 @@ void __init ams_delta_init_fiq(void)
        /*
         * Redirect GPIO interrupts to FIQ
         */
-       offset = IRQ_ILR0_REG_OFFSET + INT_GPIO_BANK1 * 0x4;
+       offset = IRQ_ILR0_REG_OFFSET + (INT_GPIO_BANK1 - NR_IRQS_LEGACY) * 0x4;
        val = omap_readl(OMAP_IH1_BASE + offset) | 1;
        omap_writel(val, OMAP_IH1_BASE + offset);
 }
index adb5e76..6dfc3e1 100644 (file)
@@ -14,6 +14,8 @@
 #ifndef __AMS_DELTA_FIQ_H
 #define __AMS_DELTA_FIQ_H
 
+#include <mach/irqs.h>
+
 /*
  * Interrupt number used for passing control from FIQ to IRQ.
  * IRQ12, described as reserved, has been selected.
index 0517f0c..1a648e9 100644 (file)
@@ -17,6 +17,7 @@ config ARCH_OMAP3
        select PM_OPP if PM
        select PM if CPU_IDLE
        select SOC_HAS_OMAP2_SDRC
+       select ARM_ERRATA_430973
 
 config ARCH_OMAP4
        bool "TI OMAP4"
@@ -36,6 +37,7 @@ config ARCH_OMAP4
        select PM if CPU_IDLE
        select ARM_ERRATA_754322
        select ARM_ERRATA_775420
+       select OMAP_INTERCONNECT
 
 config SOC_OMAP5
        bool "TI OMAP5"
@@ -67,6 +69,8 @@ config SOC_AM43XX
        select HAVE_ARM_SCU
        select GENERIC_CLOCKEVENTS_BROADCAST
        select HAVE_ARM_TWD
+       select ARM_ERRATA_754322
+       select ARM_ERRATA_775420
 
 config SOC_DRA7XX
        bool "TI DRA7XX"
@@ -240,4 +244,12 @@ endmenu
 
 endif
 
+config OMAP5_ERRATA_801819
+       bool "Errata 801819: An eviction from L1 data cache might stall indefinitely"
+       depends on SOC_OMAP5 || SOC_DRA7XX
+       help
+         A livelock can occur in the L2 cache arbitration that might prevent
+         a snoop from completing. Under certain conditions this can cause the
+         system to deadlock.
+
 endmenu
index af2851f..bae263f 100644 (file)
@@ -46,6 +46,7 @@
 
 #define OMAP5_DRA7_MON_SET_CNTFRQ_INDEX        0x109
 #define OMAP5_MON_AMBA_IF_INDEX                0x108
+#define OMAP5_DRA7_MON_SET_ACR_INDEX   0x107
 
 /* Secure PPA(Primary Protected Application) APIs */
 #define OMAP4_PPA_L2_POR_INDEX         0x23
index c625cc1..8cd1de9 100644 (file)
@@ -50,6 +50,39 @@ void __iomem *omap4_get_scu_base(void)
        return scu_base;
 }
 
+#ifdef CONFIG_OMAP5_ERRATA_801819
+void omap5_erratum_workaround_801819(void)
+{
+       u32 acr, revidr;
+       u32 acr_mask;
+
+       /* REVIDR[3] indicates erratum fix available on silicon */
+       asm volatile ("mrc p15, 0, %0, c0, c0, 6" : "=r" (revidr));
+       if (revidr & (0x1 << 3))
+               return;
+
+       asm volatile ("mrc p15, 0, %0, c1, c0, 1" : "=r" (acr));
+       /*
+        * BIT(27) - Disables streaming. All write-allocate lines allocate in
+        * the L1 or L2 cache.
+        * BIT(25) - Disables streaming. All write-allocate lines allocate in
+        * the L1 cache.
+        */
+       acr_mask = (0x3 << 25) | (0x3 << 27);
+       /* do we already have it done.. if yes, skip expensive smc */
+       if ((acr & acr_mask) == acr_mask)
+               return;
+
+       acr |= acr_mask;
+       omap_smc1(OMAP5_DRA7_MON_SET_ACR_INDEX, acr);
+
+       pr_debug("%s: ARM erratum workaround 801819 applied on CPU%d\n",
+                __func__, smp_processor_id());
+}
+#else
+static inline void omap5_erratum_workaround_801819(void) { }
+#endif
+
 static void omap4_secondary_init(unsigned int cpu)
 {
        /*
@@ -64,12 +97,15 @@ static void omap4_secondary_init(unsigned int cpu)
                omap_secure_dispatcher(OMAP4_PPA_CPU_ACTRL_SMP_INDEX,
                                                        4, 0, 0, 0, 0, 0);
 
-       /*
-        * Configure the CNTFRQ register for the secondary cpu's which
-        * indicates the frequency of the cpu local timers.
-        */
-       if (soc_is_omap54xx() || soc_is_dra7xx())
+       if (soc_is_omap54xx() || soc_is_dra7xx()) {
+               /*
+                * Configure the CNTFRQ register for the secondary cpu's which
+                * indicates the frequency of the cpu local timers.
+                */
                set_cntfreq();
+               /* Configure ACR to disable streaming WA for 801819 */
+               omap5_erratum_workaround_801819();
+       }
 
        /*
         * Synchronise with the boot thread.
@@ -218,6 +254,8 @@ static void __init omap4_smp_prepare_cpus(unsigned int max_cpus)
 
        if (cpu_is_omap446x())
                startup_addr = omap4460_secondary_startup;
+       if (soc_is_dra74x() || soc_is_omap54xx())
+               omap5_erratum_workaround_801819();
 
        /*
         * Write the address of secondary startup routine into the
index 78af6d8..daf2753 100644 (file)
@@ -186,8 +186,9 @@ static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
                        trace_state = (PWRDM_TRACE_STATES_FLAG |
                                       ((next & OMAP_POWERSTATE_MASK) << 8) |
                                       ((prev & OMAP_POWERSTATE_MASK) << 0));
-                       trace_power_domain_target(pwrdm->name, trace_state,
-                                                 smp_processor_id());
+                       trace_power_domain_target_rcuidle(pwrdm->name,
+                                                         trace_state,
+                                                         smp_processor_id());
                }
                break;
        default:
@@ -523,8 +524,8 @@ int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
 
        if (arch_pwrdm && arch_pwrdm->pwrdm_set_next_pwrst) {
                /* Trace the pwrdm desired target state */
-               trace_power_domain_target(pwrdm->name, pwrst,
-                                         smp_processor_id());
+               trace_power_domain_target_rcuidle(pwrdm->name, pwrst,
+                                                 smp_processor_id());
                /* Program the pwrdm desired target state */
                ret = arch_pwrdm->pwrdm_set_next_pwrst(pwrdm, pwrst);
        }
index 0ec2d00..eb350a6 100644 (file)
@@ -36,14 +36,7 @@ static struct powerdomain iva_7xx_pwrdm = {
        .prcm_offs        = DRA7XX_PRM_IVA_INST,
        .prcm_partition   = DRA7XX_PRM_PARTITION,
        .pwrsts           = PWRSTS_OFF_ON,
-       .pwrsts_logic_ret = PWRSTS_OFF,
        .banks            = 4,
-       .pwrsts_mem_ret = {
-               [0] = PWRSTS_OFF_RET,   /* hwa_mem */
-               [1] = PWRSTS_OFF_RET,   /* sl2_mem */
-               [2] = PWRSTS_OFF_RET,   /* tcm1_mem */
-               [3] = PWRSTS_OFF_RET,   /* tcm2_mem */
-       },
        .pwrsts_mem_on  = {
                [0] = PWRSTS_ON,        /* hwa_mem */
                [1] = PWRSTS_ON,        /* sl2_mem */
@@ -76,12 +69,7 @@ static struct powerdomain ipu_7xx_pwrdm = {
        .prcm_offs        = DRA7XX_PRM_IPU_INST,
        .prcm_partition   = DRA7XX_PRM_PARTITION,
        .pwrsts           = PWRSTS_OFF_ON,
-       .pwrsts_logic_ret = PWRSTS_OFF,
        .banks            = 2,
-       .pwrsts_mem_ret = {
-               [0] = PWRSTS_OFF_RET,   /* aessmem */
-               [1] = PWRSTS_OFF_RET,   /* periphmem */
-       },
        .pwrsts_mem_on  = {
                [0] = PWRSTS_ON,        /* aessmem */
                [1] = PWRSTS_ON,        /* periphmem */
@@ -95,11 +83,7 @@ static struct powerdomain dss_7xx_pwrdm = {
        .prcm_offs        = DRA7XX_PRM_DSS_INST,
        .prcm_partition   = DRA7XX_PRM_PARTITION,
        .pwrsts           = PWRSTS_OFF_ON,
-       .pwrsts_logic_ret = PWRSTS_OFF,
        .banks            = 1,
-       .pwrsts_mem_ret = {
-               [0] = PWRSTS_OFF_RET,   /* dss_mem */
-       },
        .pwrsts_mem_on  = {
                [0] = PWRSTS_ON,        /* dss_mem */
        },
@@ -111,13 +95,8 @@ static struct powerdomain l4per_7xx_pwrdm = {
        .name             = "l4per_pwrdm",
        .prcm_offs        = DRA7XX_PRM_L4PER_INST,
        .prcm_partition   = DRA7XX_PRM_PARTITION,
-       .pwrsts           = PWRSTS_RET_ON,
-       .pwrsts_logic_ret = PWRSTS_RET,
+       .pwrsts           = PWRSTS_ON,
        .banks            = 2,
-       .pwrsts_mem_ret = {
-               [0] = PWRSTS_OFF_RET,   /* nonretained_bank */
-               [1] = PWRSTS_OFF_RET,   /* retained_bank */
-       },
        .pwrsts_mem_on  = {
                [0] = PWRSTS_ON,        /* nonretained_bank */
                [1] = PWRSTS_ON,        /* retained_bank */
@@ -132,9 +111,6 @@ static struct powerdomain gpu_7xx_pwrdm = {
        .prcm_partition   = DRA7XX_PRM_PARTITION,
        .pwrsts           = PWRSTS_OFF_ON,
        .banks            = 1,
-       .pwrsts_mem_ret = {
-               [0] = PWRSTS_OFF_RET,   /* gpu_mem */
-       },
        .pwrsts_mem_on  = {
                [0] = PWRSTS_ON,        /* gpu_mem */
        },
@@ -148,8 +124,6 @@ static struct powerdomain wkupaon_7xx_pwrdm = {
        .prcm_partition   = DRA7XX_PRM_PARTITION,
        .pwrsts           = PWRSTS_ON,
        .banks            = 1,
-       .pwrsts_mem_ret = {
-       },
        .pwrsts_mem_on  = {
                [0] = PWRSTS_ON,        /* wkup_bank */
        },
@@ -161,15 +135,7 @@ static struct powerdomain core_7xx_pwrdm = {
        .prcm_offs        = DRA7XX_PRM_CORE_INST,
        .prcm_partition   = DRA7XX_PRM_PARTITION,
        .pwrsts           = PWRSTS_ON,
-       .pwrsts_logic_ret = PWRSTS_RET,
        .banks            = 5,
-       .pwrsts_mem_ret = {
-               [0] = PWRSTS_OFF_RET,   /* core_nret_bank */
-               [1] = PWRSTS_OFF_RET,   /* core_ocmram */
-               [2] = PWRSTS_OFF_RET,   /* core_other_bank */
-               [3] = PWRSTS_OFF_RET,   /* ipu_l2ram */
-               [4] = PWRSTS_OFF_RET,   /* ipu_unicache */
-       },
        .pwrsts_mem_on  = {
                [0] = PWRSTS_ON,        /* core_nret_bank */
                [1] = PWRSTS_ON,        /* core_ocmram */
@@ -226,11 +192,7 @@ static struct powerdomain vpe_7xx_pwrdm = {
        .prcm_offs        = DRA7XX_PRM_VPE_INST,
        .prcm_partition   = DRA7XX_PRM_PARTITION,
        .pwrsts           = PWRSTS_OFF_ON,
-       .pwrsts_logic_ret = PWRSTS_OFF,
        .banks            = 1,
-       .pwrsts_mem_ret = {
-               [0] = PWRSTS_OFF_RET,   /* vpe_bank */
-       },
        .pwrsts_mem_on  = {
                [0] = PWRSTS_ON,        /* vpe_bank */
        },
@@ -260,14 +222,8 @@ static struct powerdomain l3init_7xx_pwrdm = {
        .name             = "l3init_pwrdm",
        .prcm_offs        = DRA7XX_PRM_L3INIT_INST,
        .prcm_partition   = DRA7XX_PRM_PARTITION,
-       .pwrsts           = PWRSTS_RET_ON,
-       .pwrsts_logic_ret = PWRSTS_RET,
+       .pwrsts           = PWRSTS_ON,
        .banks            = 3,
-       .pwrsts_mem_ret = {
-               [0] = PWRSTS_OFF_RET,   /* gmac_bank */
-               [1] = PWRSTS_OFF_RET,   /* l3init_bank1 */
-               [2] = PWRSTS_OFF_RET,   /* l3init_bank2 */
-       },
        .pwrsts_mem_on  = {
                [0] = PWRSTS_ON,        /* gmac_bank */
                [1] = PWRSTS_ON,        /* l3init_bank1 */
@@ -283,9 +239,6 @@ static struct powerdomain eve3_7xx_pwrdm = {
        .prcm_partition   = DRA7XX_PRM_PARTITION,
        .pwrsts           = PWRSTS_OFF_ON,
        .banks            = 1,
-       .pwrsts_mem_ret = {
-               [0] = PWRSTS_OFF_RET,   /* eve3_bank */
-       },
        .pwrsts_mem_on  = {
                [0] = PWRSTS_ON,        /* eve3_bank */
        },
@@ -299,9 +252,6 @@ static struct powerdomain emu_7xx_pwrdm = {
        .prcm_partition   = DRA7XX_PRM_PARTITION,
        .pwrsts           = PWRSTS_OFF_ON,
        .banks            = 1,
-       .pwrsts_mem_ret = {
-               [0] = PWRSTS_OFF_RET,   /* emu_bank */
-       },
        .pwrsts_mem_on  = {
                [0] = PWRSTS_ON,        /* emu_bank */
        },
@@ -314,11 +264,6 @@ static struct powerdomain dsp2_7xx_pwrdm = {
        .prcm_partition   = DRA7XX_PRM_PARTITION,
        .pwrsts           = PWRSTS_OFF_ON,
        .banks            = 3,
-       .pwrsts_mem_ret = {
-               [0] = PWRSTS_OFF_RET,   /* dsp2_edma */
-               [1] = PWRSTS_OFF_RET,   /* dsp2_l1 */
-               [2] = PWRSTS_OFF_RET,   /* dsp2_l2 */
-       },
        .pwrsts_mem_on  = {
                [0] = PWRSTS_ON,        /* dsp2_edma */
                [1] = PWRSTS_ON,        /* dsp2_l1 */
@@ -334,11 +279,6 @@ static struct powerdomain dsp1_7xx_pwrdm = {
        .prcm_partition   = DRA7XX_PRM_PARTITION,
        .pwrsts           = PWRSTS_OFF_ON,
        .banks            = 3,
-       .pwrsts_mem_ret = {
-               [0] = PWRSTS_OFF_RET,   /* dsp1_edma */
-               [1] = PWRSTS_OFF_RET,   /* dsp1_l1 */
-               [2] = PWRSTS_OFF_RET,   /* dsp1_l2 */
-       },
        .pwrsts_mem_on  = {
                [0] = PWRSTS_ON,        /* dsp1_edma */
                [1] = PWRSTS_ON,        /* dsp1_l1 */
@@ -354,9 +294,6 @@ static struct powerdomain cam_7xx_pwrdm = {
        .prcm_partition   = DRA7XX_PRM_PARTITION,
        .pwrsts           = PWRSTS_OFF_ON,
        .banks            = 1,
-       .pwrsts_mem_ret = {
-               [0] = PWRSTS_OFF_RET,   /* vip_bank */
-       },
        .pwrsts_mem_on  = {
                [0] = PWRSTS_ON,        /* vip_bank */
        },
@@ -370,9 +307,6 @@ static struct powerdomain eve4_7xx_pwrdm = {
        .prcm_partition   = DRA7XX_PRM_PARTITION,
        .pwrsts           = PWRSTS_OFF_ON,
        .banks            = 1,
-       .pwrsts_mem_ret = {
-               [0] = PWRSTS_OFF_RET,   /* eve4_bank */
-       },
        .pwrsts_mem_on  = {
                [0] = PWRSTS_ON,        /* eve4_bank */
        },
@@ -386,9 +320,6 @@ static struct powerdomain eve2_7xx_pwrdm = {
        .prcm_partition   = DRA7XX_PRM_PARTITION,
        .pwrsts           = PWRSTS_OFF_ON,
        .banks            = 1,
-       .pwrsts_mem_ret = {
-               [0] = PWRSTS_OFF_RET,   /* eve2_bank */
-       },
        .pwrsts_mem_on  = {
                [0] = PWRSTS_ON,        /* eve2_bank */
        },
@@ -402,9 +333,6 @@ static struct powerdomain eve1_7xx_pwrdm = {
        .prcm_partition   = DRA7XX_PRM_PARTITION,
        .pwrsts           = PWRSTS_OFF_ON,
        .banks            = 1,
-       .pwrsts_mem_ret = {
-               [0] = PWRSTS_OFF_RET,   /* eve1_bank */
-       },
        .pwrsts_mem_on  = {
                [0] = PWRSTS_ON,        /* eve1_bank */
        },
index 5b385bb..cb9497a 100644 (file)
@@ -496,8 +496,7 @@ void __init omap_init_time(void)
        __omap_sync32k_timer_init(1, "timer_32k_ck", "ti,timer-alwon",
                        2, "timer_sys_ck", NULL, false);
 
-       if (of_have_populated_dt())
-               clocksource_probe();
+       clocksource_probe();
 }
 
 #if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_AM43XX)
@@ -505,6 +504,8 @@ void __init omap3_secure_sync32k_timer_init(void)
 {
        __omap_sync32k_timer_init(12, "secure_32k_fck", "ti,timer-secure",
                        2, "timer_sys_ck", NULL, false);
+
+       clocksource_probe();
 }
 #endif /* CONFIG_ARCH_OMAP3 */
 
@@ -513,6 +514,8 @@ void __init omap3_gptimer_timer_init(void)
 {
        __omap_sync32k_timer_init(2, "timer_sys_ck", NULL,
                        1, "timer_sys_ck", "ti,timer-alwon", true);
+
+       clocksource_probe();
 }
 #endif
 
index 5766ce2..8409cab 100644 (file)
@@ -547,7 +547,7 @@ static struct clk *ve_spc_clk_register(struct device *cpu_dev)
 
        init.name = dev_name(cpu_dev);
        init.ops = &clk_spc_ops;
-       init.flags = CLK_IS_ROOT | CLK_GET_RATE_NOCACHE;
+       init.flags = CLK_GET_RATE_NOCACHE;
        init.num_parents = 0;
 
        return devm_clk_register(cpu_dev, &spc->hw);
index 84baa16..e93aa67 100644 (file)
@@ -68,7 +68,7 @@
 #include <linux/platform_data/asoc-s3c.h>
 #include <linux/platform_data/spi-s3c64xx.h>
 
-static u64 samsung_device_dma_mask = DMA_BIT_MASK(32);
+#define samsung_device_dma_mask (*((u64[]) { DMA_BIT_MASK(32) }))
 
 /* AC97 */
 #ifdef CONFIG_CPU_S3C2440
index 76747d9..5a0a691 100644 (file)
@@ -113,6 +113,18 @@ config ARCH_PHYS_ADDR_T_64BIT
 config MMU
        def_bool y
 
+config ARM64_PAGE_SHIFT
+       int
+       default 16 if ARM64_64K_PAGES
+       default 14 if ARM64_16K_PAGES
+       default 12
+
+config ARM64_CONT_SHIFT
+       int
+       default 5 if ARM64_64K_PAGES
+       default 7 if ARM64_16K_PAGES
+       default 4
+
 config ARCH_MMAP_RND_BITS_MIN
        default 14 if ARM64_64K_PAGES
        default 16 if ARM64_16K_PAGES
@@ -426,6 +438,15 @@ config CAVIUM_ERRATUM_22375
 
          If unsure, say Y.
 
+config CAVIUM_ERRATUM_23144
+       bool "Cavium erratum 23144: ITS SYNC hang on dual socket system"
+       depends on NUMA
+       default y
+       help
+         ITS SYNC command hang for cross node io and collections/cpu mapping.
+
+         If unsure, say Y.
+
 config CAVIUM_ERRATUM_23154
        bool "Cavium erratum 23154: Access to ICC_IAR1_EL1 is not sync'ed"
        default y
index 710fde4..0cc758c 100644 (file)
@@ -12,7 +12,8 @@ config ARM64_PTDUMP
          who are working in architecture specific areas of the kernel.
          It is probably not a good idea to enable this feature in a production
          kernel.
-         If in doubt, say "N"
+
+         If in doubt, say N.
 
 config PID_IN_CONTEXTIDR
        bool "Write the current PID to the CONTEXTIDR register"
@@ -38,15 +39,15 @@ config ARM64_RANDOMIZE_TEXT_OFFSET
          value.
 
 config DEBUG_SET_MODULE_RONX
-        bool "Set loadable kernel module data as NX and text as RO"
-        depends on MODULES
-        help
-          This option helps catch unintended modifications to loadable
-          kernel module's text and read-only data. It also prevents execution
-          of module data. Such protection may interfere with run-time code
-          patching and dynamic kernel tracing - and they might also protect
-          against certain classes of kernel exploits.
-          If in doubt, say "N".
+       bool "Set loadable kernel module data as NX and text as RO"
+       depends on MODULES
+       default y
+       help
+         Is this is set, kernel module text and rodata will be made read-only.
+         This is to help catch accidental or malicious attempts to change the
+         kernel's executable code.
+
+         If in doubt, say Y.
 
 config DEBUG_RODATA
        bool "Make kernel text and rodata read-only"
@@ -56,7 +57,7 @@ config DEBUG_RODATA
          is to help catch accidental or malicious attempts to change the
          kernel's executable code.
 
-         If in doubt, say Y
+         If in doubt, say Y.
 
 config DEBUG_ALIGN_RODATA
        depends on DEBUG_RODATA
@@ -69,7 +70,7 @@ config DEBUG_ALIGN_RODATA
          alignment and potentially wasted space. Turn on this option if
          performance is more important than memory pressure.
 
-         If in doubt, say N
+         If in doubt, say N.
 
 source "drivers/hwtracing/coresight/Kconfig"
 
index 354d754..648a32c 100644 (file)
@@ -60,7 +60,9 @@ head-y                := arch/arm64/kernel/head.o
 
 # The byte offset of the kernel image in RAM from the start of RAM.
 ifeq ($(CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET), y)
-TEXT_OFFSET := $(shell awk 'BEGIN {srand(); printf "0x%03x000\n", int(512 * rand())}')
+TEXT_OFFSET := $(shell awk "BEGIN {srand(); printf \"0x%06x\n\", \
+                int(2 * 1024 * 1024 / (2 ^ $(CONFIG_ARM64_PAGE_SHIFT)) * \
+                rand()) * (2 ^ $(CONFIG_ARM64_PAGE_SHIFT))}")
 else
 TEXT_OFFSET := 0x00080000
 endif
@@ -93,7 +95,7 @@ boot := arch/arm64/boot
 Image: vmlinux
        $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 
-Image.%: vmlinux
+Image.%: Image
        $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 
 zinstall install:
index 3a4e9a2..fbafa24 100644 (file)
                #size-cells = <1>;
                #interrupts-cells = <3>;
 
-               compatible = "arm,amba-bus";
+               compatible = "simple-bus";
                interrupt-parent = <&gic>;
                ranges;
 
index 46f325a..d7f8e06 100644 (file)
        };
 
        amba {
-               compatible = "arm,amba-bus";
+               compatible = "simple-bus";
                #address-cells = <2>;
                #size-cells = <2>;
                ranges;
index 7a09c48..579b6e6 100644 (file)
@@ -160,14 +160,14 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm,
 #define STACK_RND_MASK                 (0x3ffff >> (PAGE_SHIFT - 12))
 #endif
 
-#ifdef CONFIG_COMPAT
-
 #ifdef __AARCH64EB__
 #define COMPAT_ELF_PLATFORM            ("v8b")
 #else
 #define COMPAT_ELF_PLATFORM            ("v8l")
 #endif
 
+#ifdef CONFIG_COMPAT
+
 #define COMPAT_ELF_ET_DYN_BASE         (2 * TASK_SIZE_32 / 3)
 
 /* AArch32 registers. */
index f69f69c..da84645 100644 (file)
@@ -38,25 +38,54 @@ extern int kgdb_fault_expected;
 #endif /* !__ASSEMBLY__ */
 
 /*
- * gdb is expecting the following registers layout.
+ * gdb remote procotol (well most versions of it) expects the following
+ * register layout.
  *
  * General purpose regs:
  *     r0-r30: 64 bit
  *     sp,pc : 64 bit
- *     pstate  : 64 bit
- *     Total: 34
+ *     pstate  : 32 bit
+ *     Total: 33 + 1
  * FPU regs:
  *     f0-f31: 128 bit
- *     Total: 32
- * Extra regs
  *     fpsr & fpcr: 32 bit
- *     Total: 2
+ *     Total: 32 + 2
  *
+ * To expand a little on the "most versions of it"... when the gdb remote
+ * protocol for AArch64 was developed it depended on a statement in the
+ * Architecture Reference Manual that claimed "SPSR_ELx is a 32-bit register".
+ * and, as a result, allocated only 32-bits for the PSTATE in the remote
+ * protocol. In fact this statement is still present in ARM DDI 0487A.i.
+ *
+ * Unfortunately "is a 32-bit register" has a very special meaning for
+ * system registers. It means that "the upper bits, bits[63:32], are
+ * RES0.". RES0 is heavily used in the ARM architecture documents as a
+ * way to leave space for future architecture changes. So to translate a
+ * little for people who don't spend their spare time reading ARM architecture
+ * manuals, what "is a 32-bit register" actually means in this context is
+ * "is a 64-bit register but one with no meaning allocated to any of the
+ * upper 32-bits... *yet*".
+ *
+ * Perhaps then we should not be surprised that this has led to some
+ * confusion. Specifically a patch, influenced by the above translation,
+ * that extended PSTATE to 64-bit was accepted into gdb-7.7 but the patch
+ * was reverted in gdb-7.8.1 and all later releases, when this was
+ * discovered to be an undocumented protocol change.
+ *
+ * So... it is *not* wrong for us to only allocate 32-bits to PSTATE
+ * here even though the kernel itself allocates 64-bits for the same
+ * state. That is because this bit of code tells the kernel how the gdb
+ * remote protocol (well most versions of it) describes the register state.
+ *
+ * Note that if you are using one of the versions of gdb that supports
+ * the gdb-7.7 version of the protocol you cannot use kgdb directly
+ * without providing a custom register description (gdb can load new
+ * protocol descriptions at runtime).
  */
 
-#define _GP_REGS               34
+#define _GP_REGS               33
 #define _FP_REGS               32
-#define _EXTRA_REGS            2
+#define _EXTRA_REGS            3
 /*
  * general purpose registers size in bytes.
  * pstate is only 4 bytes. subtract 4 bytes
index 72a3025..31b7322 100644 (file)
@@ -55,8 +55,9 @@
 #define VMEMMAP_SIZE (UL(1) << (VA_BITS - PAGE_SHIFT - 1 + STRUCT_PAGE_MAX_SHIFT))
 
 /*
- * PAGE_OFFSET - the virtual address of the start of the kernel image (top
+ * PAGE_OFFSET - the virtual address of the start of the linear map (top
  *              (VA_BITS - 1))
+ * KIMAGE_VADDR - the virtual address of the start of the kernel image
  * VA_BITS - the maximum number of bits for virtual addresses.
  * VA_START - the first kernel virtual address.
  * TASK_SIZE - the maximum size of a user space task.
index 17b45f7..8472c6d 100644 (file)
 
 /* PAGE_SHIFT determines the page size */
 /* CONT_SHIFT determines the number of pages which can be tracked together  */
-#ifdef CONFIG_ARM64_64K_PAGES
-#define PAGE_SHIFT             16
-#define CONT_SHIFT             5
-#elif defined(CONFIG_ARM64_16K_PAGES)
-#define PAGE_SHIFT             14
-#define CONT_SHIFT             7
-#else
-#define PAGE_SHIFT             12
-#define CONT_SHIFT             4
-#endif
+#define PAGE_SHIFT             CONFIG_ARM64_PAGE_SHIFT
+#define CONT_SHIFT             CONFIG_ARM64_CONT_SHIFT
 #define PAGE_SIZE              (_AC(1, UL) << PAGE_SHIFT)
 #define PAGE_MASK              (~(PAGE_SIZE-1))
 
index ff98585..d25f4f1 100644 (file)
@@ -26,7 +26,7 @@
 
 #define check_pgt_cache()              do { } while (0)
 
-#define PGALLOC_GFP    (GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO)
+#define PGALLOC_GFP    (GFP_KERNEL | __GFP_NOTRACK | __GFP_ZERO)
 #define PGD_SIZE       (PTRS_PER_PGD * sizeof(pgd_t))
 
 #if CONFIG_PGTABLE_LEVELS > 2
index 433e504..0226447 100644 (file)
@@ -124,6 +124,18 @@ static inline void cpu_panic_kernel(void)
        cpu_park_loop();
 }
 
+/*
+ * If a secondary CPU enters the kernel but fails to come online,
+ * (e.g. due to mismatched features), and cannot exit the kernel,
+ * we increment cpus_stuck_in_kernel and leave the CPU in a
+ * quiesecent loop within the kernel text. The memory containing
+ * this loop must not be re-used for anything else as the 'stuck'
+ * core is executing it.
+ *
+ * This function is used to inhibit features like kexec and hibernate.
+ */
+bool cpus_are_stuck_in_kernel(void);
+
 #endif /* ifndef __ASSEMBLY__ */
 
 #endif /* ifndef __ASM_SMP_H */
index fc9682b..e875a5a 100644 (file)
@@ -30,22 +30,53 @@ static inline void arch_spin_unlock_wait(arch_spinlock_t *lock)
 {
        unsigned int tmp;
        arch_spinlock_t lockval;
+       u32 owner;
+
+       /*
+        * Ensure prior spin_lock operations to other locks have completed
+        * on this CPU before we test whether "lock" is locked.
+        */
+       smp_mb();
+       owner = READ_ONCE(lock->owner) << 16;
 
        asm volatile(
 "      sevl\n"
 "1:    wfe\n"
 "2:    ldaxr   %w0, %2\n"
+       /* Is the lock free? */
 "      eor     %w1, %w0, %w0, ror #16\n"
-"      cbnz    %w1, 1b\n"
+"      cbz     %w1, 3f\n"
+       /* Lock taken -- has there been a subsequent unlock->lock transition? */
+"      eor     %w1, %w3, %w0, lsl #16\n"
+"      cbz     %w1, 1b\n"
+       /*
+        * The owner has been updated, so there was an unlock->lock
+        * transition that we missed. That means we can rely on the
+        * store-release of the unlock operation paired with the
+        * load-acquire of the lock operation to publish any of our
+        * previous stores to the new lock owner and therefore don't
+        * need to bother with the writeback below.
+        */
+"      b       4f\n"
+"3:\n"
+       /*
+        * Serialise against any concurrent lockers by writing back the
+        * unlocked lock value
+        */
        ARM64_LSE_ATOMIC_INSN(
        /* LL/SC */
 "      stxr    %w1, %w0, %2\n"
-"      cbnz    %w1, 2b\n", /* Serialise against any concurrent lockers */
-       /* LSE atomics */
 "      nop\n"
-"      nop\n")
+"      nop\n",
+       /* LSE atomics */
+"      mov     %w1, %w0\n"
+"      cas     %w0, %w0, %2\n"
+"      eor     %w1, %w1, %w0\n")
+       /* Somebody else wrote to the lock, GOTO 10 and reload the value */
+"      cbnz    %w1, 2b\n"
+"4:"
        : "=&r" (lockval), "=&r" (tmp), "+Q" (*lock)
-       :
+       : "r" (owner)
        : "memory");
 }
 
@@ -148,6 +179,7 @@ static inline int arch_spin_value_unlocked(arch_spinlock_t lock)
 
 static inline int arch_spin_is_locked(arch_spinlock_t *lock)
 {
+       smp_mb(); /* See arch_spin_unlock_wait */
        return !arch_spin_value_unlocked(READ_ONCE(*lock));
 }
 
index 0685d74..9e397a5 100644 (file)
@@ -80,19 +80,6 @@ static inline void set_fs(mm_segment_t fs)
 
 #define segment_eq(a, b)       ((a) == (b))
 
-/*
- * Return 1 if addr < current->addr_limit, 0 otherwise.
- */
-#define __addr_ok(addr)                                                        \
-({                                                                     \
-       unsigned long flag;                                             \
-       asm("cmp %1, %0; cset %0, lo"                                   \
-               : "=&r" (flag)                                          \
-               : "r" (addr), "0" (current_thread_info()->addr_limit)   \
-               : "cc");                                                \
-       flag;                                                           \
-})
-
 /*
  * Test whether a block of memory is a valid user space address.
  * Returns 1 if the range is valid, 0 otherwise.
index 41e58fe..e78ac26 100644 (file)
@@ -44,7 +44,7 @@
 #define __ARM_NR_compat_cacheflush     (__ARM_NR_COMPAT_BASE+2)
 #define __ARM_NR_compat_set_tls                (__ARM_NR_COMPAT_BASE+5)
 
-#define __NR_compat_syscalls           390
+#define __NR_compat_syscalls           394
 #endif
 
 #define __ARCH_WANT_SYS_CLONE
index 5b925b7..b7e8ef1 100644 (file)
@@ -801,6 +801,14 @@ __SYSCALL(__NR_execveat, compat_sys_execveat)
 __SYSCALL(__NR_userfaultfd, sys_userfaultfd)
 #define __NR_membarrier 389
 __SYSCALL(__NR_membarrier, sys_membarrier)
+#define __NR_mlock2 390
+__SYSCALL(__NR_mlock2, sys_mlock2)
+#define __NR_copy_file_range 391
+__SYSCALL(__NR_copy_file_range, sys_copy_file_range)
+#define __NR_preadv2 392
+__SYSCALL(__NR_preadv2, compat_sys_preadv2)
+#define __NR_pwritev2 393
+__SYSCALL(__NR_pwritev2, compat_sys_pwritev2)
 
 /*
  * Please add new compat syscalls above this comment and update
index 3808470..c173d32 100644 (file)
@@ -22,6 +22,8 @@
 
 #include <linux/bitops.h>
 #include <linux/bug.h>
+#include <linux/compat.h>
+#include <linux/elf.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/personality.h>
@@ -104,6 +106,7 @@ static const char *const compat_hwcap2_str[] = {
 static int c_show(struct seq_file *m, void *v)
 {
        int i, j;
+       bool compat = personality(current->personality) == PER_LINUX32;
 
        for_each_online_cpu(i) {
                struct cpuinfo_arm64 *cpuinfo = &per_cpu(cpu_data, i);
@@ -115,6 +118,9 @@ static int c_show(struct seq_file *m, void *v)
                 * "processor".  Give glibc what it expects.
                 */
                seq_printf(m, "processor\t: %d\n", i);
+               if (compat)
+                       seq_printf(m, "model name\t: ARMv8 Processor rev %d (%s)\n",
+                                  MIDR_REVISION(midr), COMPAT_ELF_PLATFORM);
 
                seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
                           loops_per_jiffy / (500000UL/HZ),
@@ -127,7 +133,7 @@ static int c_show(struct seq_file *m, void *v)
                 * software which does already (at least for 32-bit).
                 */
                seq_puts(m, "Features\t:");
-               if (personality(current->personality) == PER_LINUX32) {
+               if (compat) {
 #ifdef CONFIG_COMPAT
                        for (j = 0; compat_hwcap_str[j]; j++)
                                if (compat_elf_hwcap & (1 << j))
index f8df75d..21ab5df 100644 (file)
@@ -33,6 +33,7 @@
 #include <asm/pgtable.h>
 #include <asm/pgtable-hwdef.h>
 #include <asm/sections.h>
+#include <asm/smp.h>
 #include <asm/suspend.h>
 #include <asm/virt.h>
 
@@ -236,6 +237,11 @@ int swsusp_arch_suspend(void)
        unsigned long flags;
        struct sleep_stack_data state;
 
+       if (cpus_are_stuck_in_kernel()) {
+               pr_err("Can't hibernate: no mechanism to offline secondary CPUs.\n");
+               return -EBUSY;
+       }
+
        local_dbg_save(flags);
 
        if (__cpu_suspend_enter(&state)) {
index b67531a..b5f063e 100644 (file)
@@ -58,7 +58,17 @@ struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = {
        { "x30", 8, offsetof(struct pt_regs, regs[30])},
        { "sp", 8, offsetof(struct pt_regs, sp)},
        { "pc", 8, offsetof(struct pt_regs, pc)},
-       { "pstate", 8, offsetof(struct pt_regs, pstate)},
+       /*
+        * struct pt_regs thinks PSTATE is 64-bits wide but gdb remote
+        * protocol disagrees. Therefore we must extract only the lower
+        * 32-bits. Look for the big comment in asm/kgdb.h for more
+        * detail.
+        */
+       { "pstate", 4, offsetof(struct pt_regs, pstate)
+#ifdef CONFIG_CPU_BIG_ENDIAN
+                                                       + 4
+#endif
+       },
        { "v0", 16, -1 },
        { "v1", 16, -1 },
        { "v2", 16, -1 },
@@ -128,6 +138,8 @@ sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *task)
        memset((char *)gdb_regs, 0, NUMREGBYTES);
        thread_regs = task_pt_regs(task);
        memcpy((void *)gdb_regs, (void *)thread_regs->regs, GP_REG_BYTES);
+       /* Special case for PSTATE (check comments in asm/kgdb.h for details) */
+       dbg_get_reg(33, gdb_regs + GP_REG_BYTES, thread_regs);
 }
 
 void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc)
index 678e084..62ff3c0 100644 (file)
@@ -909,3 +909,21 @@ int setup_profiling_timer(unsigned int multiplier)
 {
        return -EINVAL;
 }
+
+static bool have_cpu_die(void)
+{
+#ifdef CONFIG_HOTPLUG_CPU
+       int any_cpu = raw_smp_processor_id();
+
+       if (cpu_ops[any_cpu]->cpu_die)
+               return true;
+#endif
+       return false;
+}
+
+bool cpus_are_stuck_in_kernel(void)
+{
+       bool smp_spin_tables = (num_possible_cpus() > 1 && !have_cpu_die());
+
+       return !!cpus_stuck_in_kernel || smp_spin_tables;
+}
index c539208..2a43012 100644 (file)
@@ -64,8 +64,7 @@ static void dump_mem(const char *lvl, const char *str, unsigned long bottom,
 
        /*
         * We need to switch to kernel mode so that we can use __get_user
-        * to safely read from kernel space.  Note that we now dump the
-        * code first, just in case the backtrace kills us.
+        * to safely read from kernel space.
         */
        fs = get_fs();
        set_fs(KERNEL_DS);
@@ -111,21 +110,12 @@ static void dump_backtrace_entry(unsigned long where)
        print_ip_sym(where);
 }
 
-static void dump_instr(const char *lvl, struct pt_regs *regs)
+static void __dump_instr(const char *lvl, struct pt_regs *regs)
 {
        unsigned long addr = instruction_pointer(regs);
-       mm_segment_t fs;
        char str[sizeof("00000000 ") * 5 + 2 + 1], *p = str;
        int i;
 
-       /*
-        * We need to switch to kernel mode so that we can use __get_user
-        * to safely read from kernel space.  Note that we now dump the
-        * code first, just in case the backtrace kills us.
-        */
-       fs = get_fs();
-       set_fs(KERNEL_DS);
-
        for (i = -4; i < 1; i++) {
                unsigned int val, bad;
 
@@ -139,8 +129,18 @@ static void dump_instr(const char *lvl, struct pt_regs *regs)
                }
        }
        printk("%sCode: %s\n", lvl, str);
+}
 
-       set_fs(fs);
+static void dump_instr(const char *lvl, struct pt_regs *regs)
+{
+       if (!user_mode(regs)) {
+               mm_segment_t fs = get_fs();
+               set_fs(KERNEL_DS);
+               __dump_instr(lvl, regs);
+               set_fs(fs);
+       } else {
+               __dump_instr(lvl, regs);
+       }
 }
 
 static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
@@ -477,8 +477,9 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr)
        void __user *pc = (void __user *)instruction_pointer(regs);
        console_verbose();
 
-       pr_crit("Bad mode in %s handler detected, code 0x%08x -- %s\n",
-               handler[reason], esr, esr_get_class_string(esr));
+       pr_crit("Bad mode in %s handler detected on CPU%d, code 0x%08x -- %s\n",
+               handler[reason], smp_processor_id(), esr,
+               esr_get_class_string(esr));
        __show_regs(regs);
 
        info.si_signo = SIGILL;
index fff7cd4..5f8f80b 100644 (file)
@@ -169,7 +169,8 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
         * Make sure stores to the GIC via the memory mapped interface
         * are now visible to the system register interface.
         */
-       dsb(st);
+       if (!cpu_if->vgic_sre)
+               dsb(st);
 
        cpu_if->vgic_vmcr  = read_gicreg(ICH_VMCR_EL2);
 
@@ -190,12 +191,11 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
                        if (!(vcpu->arch.vgic_cpu.live_lrs & (1UL << i)))
                                continue;
 
-                       if (cpu_if->vgic_elrsr & (1 << i)) {
+                       if (cpu_if->vgic_elrsr & (1 << i))
                                cpu_if->vgic_lr[i] &= ~ICH_LR_STATE;
-                               continue;
-                       }
+                       else
+                               cpu_if->vgic_lr[i] = __gic_v3_get_lr(i);
 
-                       cpu_if->vgic_lr[i] = __gic_v3_get_lr(i);
                        __gic_v3_set_lr(0, i);
                }
 
@@ -236,8 +236,12 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
 
        val = read_gicreg(ICC_SRE_EL2);
        write_gicreg(val | ICC_SRE_EL2_ENABLE, ICC_SRE_EL2);
-       isb(); /* Make sure ENABLE is set at EL2 before setting SRE at EL1 */
-       write_gicreg(1, ICC_SRE_EL1);
+
+       if (!cpu_if->vgic_sre) {
+               /* Make sure ENABLE is set at EL2 before setting SRE at EL1 */
+               isb();
+               write_gicreg(1, ICC_SRE_EL1);
+       }
 }
 
 void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
@@ -256,8 +260,10 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
         * been actually programmed with the value we want before
         * starting to mess with the rest of the GIC.
         */
-       write_gicreg(cpu_if->vgic_sre, ICC_SRE_EL1);
-       isb();
+       if (!cpu_if->vgic_sre) {
+               write_gicreg(0, ICC_SRE_EL1);
+               isb();
+       }
 
        val = read_gicreg(ICH_VTR_EL2);
        max_lr_idx = vtr_to_max_lr_idx(val);
@@ -306,18 +312,18 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
         * (re)distributors. This ensure the guest will read the
         * correct values from the memory-mapped interface.
         */
-       isb();
-       dsb(sy);
+       if (!cpu_if->vgic_sre) {
+               isb();
+               dsb(sy);
+       }
        vcpu->arch.vgic_cpu.live_lrs = live_lrs;
 
        /*
         * Prevent the guest from touching the GIC system registers if
         * SRE isn't enabled for GICv3 emulation.
         */
-       if (!cpu_if->vgic_sre) {
-               write_gicreg(read_gicreg(ICC_SRE_EL2) & ~ICC_SRE_EL2_ENABLE,
-                            ICC_SRE_EL2);
-       }
+       write_gicreg(read_gicreg(ICC_SRE_EL2) & ~ICC_SRE_EL2_ENABLE,
+                    ICC_SRE_EL2);
 }
 
 void __hyp_text __vgic_v3_init_lrs(void)
index 7bbe3ff..a57d650 100644 (file)
@@ -134,6 +134,17 @@ static bool access_gic_sgi(struct kvm_vcpu *vcpu,
        return true;
 }
 
+static bool access_gic_sre(struct kvm_vcpu *vcpu,
+                          struct sys_reg_params *p,
+                          const struct sys_reg_desc *r)
+{
+       if (p->is_write)
+               return ignore_write(vcpu, p);
+
+       p->regval = vcpu->arch.vgic_cpu.vgic_v3.vgic_sre;
+       return true;
+}
+
 static bool trap_raz_wi(struct kvm_vcpu *vcpu,
                        struct sys_reg_params *p,
                        const struct sys_reg_desc *r)
@@ -958,7 +969,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
          access_gic_sgi },
        /* ICC_SRE_EL1 */
        { Op0(0b11), Op1(0b000), CRn(0b1100), CRm(0b1100), Op2(0b101),
-         trap_raz_wi },
+         access_gic_sre },
 
        /* CONTEXTIDR_EL1 */
        { Op0(0b11), Op1(0b000), CRn(0b1101), CRm(0b0000), Op2(0b001),
index b7b3978..efcf1f7 100644 (file)
@@ -179,7 +179,7 @@ static u64 new_context(struct mm_struct *mm, unsigned int cpu)
                                                 &asid_generation);
        flush_context(cpu);
 
-       /* We have at least 1 ASID per CPU, so this will always succeed */
+       /* We have more ASIDs than CPUs, so this will always succeed */
        asid = find_next_zero_bit(asid_map, NUM_USER_ASIDS, 1);
 
 set_asid:
@@ -227,8 +227,11 @@ switch_mm_fastpath:
 static int asids_init(void)
 {
        asid_bits = get_cpu_asid_bits();
-       /* If we end up with more CPUs than ASIDs, expect things to crash */
-       WARN_ON(NUM_USER_ASIDS < num_possible_cpus());
+       /*
+        * Expect allocation after rollover to fail if we don't have at least
+        * one more ASID than CPUs. ASID #0 is reserved for init_mm.
+        */
+       WARN_ON(NUM_USER_ASIDS - 1 <= num_possible_cpus());
        atomic64_set(&asid_generation, ASID_FIRST_VERSION);
        asid_map = kzalloc(BITS_TO_LONGS(NUM_USER_ASIDS) * sizeof(*asid_map),
                           GFP_KERNEL);
index 8404190..ccfde23 100644 (file)
@@ -150,6 +150,7 @@ static const struct prot_bits pte_bits[] = {
 
 struct pg_level {
        const struct prot_bits *bits;
+       const char *name;
        size_t num;
        u64 mask;
 };
@@ -157,15 +158,19 @@ struct pg_level {
 static struct pg_level pg_level[] = {
        {
        }, { /* pgd */
+               .name   = "PGD",
                .bits   = pte_bits,
                .num    = ARRAY_SIZE(pte_bits),
        }, { /* pud */
+               .name   = (CONFIG_PGTABLE_LEVELS > 3) ? "PUD" : "PGD",
                .bits   = pte_bits,
                .num    = ARRAY_SIZE(pte_bits),
        }, { /* pmd */
+               .name   = (CONFIG_PGTABLE_LEVELS > 2) ? "PMD" : "PGD",
                .bits   = pte_bits,
                .num    = ARRAY_SIZE(pte_bits),
        }, { /* pte */
+               .name   = "PTE",
                .bits   = pte_bits,
                .num    = ARRAY_SIZE(pte_bits),
        },
@@ -214,7 +219,8 @@ static void note_page(struct pg_state *st, unsigned long addr, unsigned level,
                                delta >>= 10;
                                unit++;
                        }
-                       seq_printf(st->seq, "%9lu%c", delta, *unit);
+                       seq_printf(st->seq, "%9lu%c %s", delta, *unit,
+                                  pg_level[st->level].name);
                        if (pg_level[st->level].bits)
                                dump_prot(st, pg_level[st->level].bits,
                                          pg_level[st->level].num);
index 5954881..013e2cb 100644 (file)
@@ -109,7 +109,7 @@ int ptep_set_access_flags(struct vm_area_struct *vma,
         * PTE_RDONLY is cleared by default in the asm below, so set it in
         * back if necessary (read-only or clean PTE).
         */
-       if (!pte_write(entry) || !dirty)
+       if (!pte_write(entry) || !pte_sw_dirty(entry))
                pte_val(entry) |= PTE_RDONLY;
 
        /*
@@ -441,7 +441,7 @@ static int do_bad(unsigned long addr, unsigned int esr, struct pt_regs *regs)
        return 1;
 }
 
-static struct fault_info {
+static const struct fault_info {
        int     (*fn)(unsigned long addr, unsigned int esr, struct pt_regs *regs);
        int     sig;
        int     code;
index dbd12ea..43a76b0 100644 (file)
@@ -71,10 +71,6 @@ void __sync_icache_dcache(pte_t pte, unsigned long addr)
 {
        struct page *page = pte_page(pte);
 
-       /* no flushing needed for anonymous pages */
-       if (!page_mapping(page))
-               return;
-
        if (!test_and_set_bit(PG_dcache_clean, &page->flags))
                sync_icache_aliases(page_address(page),
                                    PAGE_SIZE << compound_order(page));
index aa8aee7..2e49bd2 100644 (file)
@@ -306,6 +306,10 @@ static __init int setup_hugepagesz(char *opt)
                hugetlb_add_hstate(PMD_SHIFT - PAGE_SHIFT);
        } else if (ps == PUD_SIZE) {
                hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT);
+       } else if (ps == (PAGE_SIZE * CONT_PTES)) {
+               hugetlb_add_hstate(CONT_PTE_SHIFT);
+       } else if (ps == (PMD_SIZE * CONT_PMDS)) {
+               hugetlb_add_hstate((PMD_SHIFT + CONT_PMD_SHIFT) - PAGE_SHIFT);
        } else {
                hugetlb_bad_size();
                pr_err("hugepagesz: Unsupported page size %lu K\n", ps >> 10);
@@ -314,3 +318,13 @@ static __init int setup_hugepagesz(char *opt)
        return 1;
 }
 __setup("hugepagesz=", setup_hugepagesz);
+
+#ifdef CONFIG_ARM64_64K_PAGES
+static __init int add_default_hugepagesz(void)
+{
+       if (size_to_hstate(CONT_PTES * PAGE_SIZE) == NULL)
+               hugetlb_add_hstate(CONT_PMD_SHIFT);
+       return 0;
+}
+arch_initcall(add_default_hugepagesz);
+#endif
index 1aba19d..db039cb 100644 (file)
@@ -43,7 +43,7 @@ static inline void pgd_ctor(void *x)
  */
 static inline pgd_t *pgd_alloc(struct mm_struct *mm)
 {
-       return quicklist_alloc(QUICK_PGD, GFP_KERNEL | __GFP_REPEAT, pgd_ctor);
+       return quicklist_alloc(QUICK_PGD, GFP_KERNEL, pgd_ctor);
 }
 
 static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
@@ -54,7 +54,7 @@ static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
 static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
                                          unsigned long address)
 {
-       return quicklist_alloc(QUICK_PT, GFP_KERNEL | __GFP_REPEAT, NULL);
+       return quicklist_alloc(QUICK_PT, GFP_KERNEL, NULL);
 }
 
 static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
@@ -63,7 +63,7 @@ static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
        struct page *page;
        void *pg;
 
-       pg = quicklist_alloc(QUICK_PT, GFP_KERNEL | __GFP_REPEAT, NULL);
+       pg = quicklist_alloc(QUICK_PT, GFP_KERNEL, NULL);
        if (!pg)
                return NULL;
 
index 235ece4..42f1aff 100644 (file)
@@ -24,14 +24,14 @@ static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
 
 static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
 {
-       pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
+       pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_ZERO);
        return pte;
 }
 
 static inline pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
 {
        struct page *pte;
-       pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
+       pte = alloc_pages(GFP_KERNEL|__GFP_ZERO, 0);
        if (!pte)
                return NULL;
        if (!pgtable_page_ctor(pte)) {
index 41907d2..c9ed14f 100644 (file)
@@ -22,7 +22,7 @@ pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((aligned(PAGE_SIZE)));
 
 pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
 {
-       pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT);
+       pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL);
        if (pte)
                clear_page(pte);
        return pte;
@@ -33,9 +33,9 @@ pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
        struct page *page;
 
 #ifdef CONFIG_HIGHPTE
-       page = alloc_pages(GFP_KERNEL|__GFP_HIGHMEM|__GFP_REPEAT, 0);
+       page = alloc_pages(GFP_KERNEL|__GFP_HIGHMEM, 0);
 #else
-       page = alloc_pages(GFP_KERNEL|__GFP_REPEAT, 0);
+       page = alloc_pages(GFP_KERNEL, 0);
 #endif
        if (!page)
                return NULL;
index 77da3b0..eeebf86 100644 (file)
@@ -64,7 +64,7 @@ static inline struct page *pte_alloc_one(struct mm_struct *mm,
 {
        struct page *pte;
 
-       pte = alloc_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO);
+       pte = alloc_page(GFP_KERNEL | __GFP_ZERO);
        if (!pte)
                return NULL;
        if (!pgtable_page_ctor(pte)) {
@@ -78,7 +78,7 @@ static inline struct page *pte_alloc_one(struct mm_struct *mm,
 static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
                                          unsigned long address)
 {
-       gfp_t flags =  GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO;
+       gfp_t flags =  GFP_KERNEL | __GFP_ZERO;
        return (pte_t *) __get_free_page(flags);
 }
 
index f80758c..e109ee9 100644 (file)
@@ -45,7 +45,7 @@ config IA64
        select GENERIC_SMP_IDLE_THREAD
        select ARCH_INIT_TASK
        select ARCH_TASK_STRUCT_ALLOCATOR
-       select ARCH_THREAD_INFO_ALLOCATOR
+       select ARCH_THREAD_STACK_ALLOCATOR
        select ARCH_CLOCKSOURCE_DATA
        select GENERIC_TIME_VSYSCALL_OLD
        select SYSCTL_ARCH_UNALIGN_NO_WARN
index aa995b6..d1212b8 100644 (file)
@@ -48,15 +48,15 @@ struct thread_info {
 #ifndef ASM_OFFSETS_C
 /* how to get the thread information struct from C */
 #define current_thread_info()  ((struct thread_info *) ((char *) current + IA64_TASK_SIZE))
-#define alloc_thread_info_node(tsk, node)      \
-               ((struct thread_info *) ((char *) (tsk) + IA64_TASK_SIZE))
+#define alloc_thread_stack_node(tsk, node)     \
+               ((unsigned long *) ((char *) (tsk) + IA64_TASK_SIZE))
 #define task_thread_info(tsk)  ((struct thread_info *) ((char *) (tsk) + IA64_TASK_SIZE))
 #else
 #define current_thread_info()  ((struct thread_info *) 0)
-#define alloc_thread_info_node(tsk, node)      ((struct thread_info *) 0)
+#define alloc_thread_stack_node(tsk, node)     ((unsigned long *) 0)
 #define task_thread_info(tsk)  ((struct thread_info *) 0)
 #endif
-#define free_thread_info(ti)   /* nothing */
+#define free_thread_stack(ti)  /* nothing */
 #define task_stack_page(tsk)   ((void *)(tsk))
 
 #define __HAVE_THREAD_FUNCTIONS
index f9efe97..0eaa89f 100644 (file)
@@ -26,6 +26,7 @@ static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
  * handled. This is done by having a special ".data..init_task" section...
  */
 #define init_thread_info       init_task_mem.s.thread_info
+#define init_stack             init_task_mem.stack
 
 union {
        struct {
index f9924fb..fb95aed 100644 (file)
@@ -14,7 +14,7 @@ extern const char bad_pmd_string[];
 extern inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
        unsigned long address)
 {
-       unsigned long page = __get_free_page(GFP_DMA|__GFP_REPEAT);
+       unsigned long page = __get_free_page(GFP_DMA);
 
        if (!page)
                return NULL;
@@ -51,7 +51,7 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t page,
 static inline struct page *pte_alloc_one(struct mm_struct *mm,
        unsigned long address)
 {
-       struct page *page = alloc_pages(GFP_DMA|__GFP_REPEAT, 0);
+       struct page *page = alloc_pages(GFP_DMA, 0);
        pte_t *pte;
 
        if (!page)
index 24bcba4..c895b98 100644 (file)
@@ -11,7 +11,7 @@ static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long ad
 {
        pte_t *pte;
 
-       pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
+       pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_ZERO);
        if (pte) {
                __flush_page_to_ram(pte);
                flush_tlb_kernel_page(pte);
@@ -32,7 +32,7 @@ static inline pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long addres
        struct page *page;
        pte_t *pte;
 
-       page = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
+       page = alloc_pages(GFP_KERNEL|__GFP_ZERO, 0);
        if(!page)
                return NULL;
        if (!pgtable_page_ctor(page)) {
index 0931388..1901f61 100644 (file)
@@ -37,7 +37,7 @@ do {                                                  \
 static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
                                          unsigned long address)
 {
-       unsigned long page = __get_free_page(GFP_KERNEL|__GFP_REPEAT);
+       unsigned long page = __get_free_page(GFP_KERNEL);
 
        if (!page)
                return NULL;
@@ -49,7 +49,7 @@ static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
 static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
                                        unsigned long address)
 {
-        struct page *page = alloc_pages(GFP_KERNEL|__GFP_REPEAT, 0);
+        struct page *page = alloc_pages(GFP_KERNEL, 0);
 
        if (page == NULL)
                return NULL;
index 3104df0..c2caa1e 100644 (file)
@@ -42,8 +42,7 @@ static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
 static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
                                          unsigned long address)
 {
-       pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT |
-                                             __GFP_ZERO);
+       pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
        return pte;
 }
 
@@ -51,7 +50,7 @@ static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
                                      unsigned long address)
 {
        struct page *pte;
-       pte = alloc_pages(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO, 0);
+       pte = alloc_pages(GFP_KERNEL  | __GFP_ZERO, 0);
        if (!pte)
                return NULL;
        if (!pgtable_page_ctor(pte)) {
index 61436d6..7c89390 100644 (file)
@@ -116,9 +116,9 @@ static inline struct page *pte_alloc_one(struct mm_struct *mm,
        struct page *ptepage;
 
 #ifdef CONFIG_HIGHPTE
-       int flags = GFP_KERNEL | __GFP_HIGHMEM | __GFP_REPEAT;
+       int flags = GFP_KERNEL | __GFP_HIGHMEM;
 #else
-       int flags = GFP_KERNEL | __GFP_REPEAT;
+       int flags = GFP_KERNEL;
 #endif
 
        ptepage = alloc_pages(flags, 0);
index 4f4520e..eb99fcc 100644 (file)
@@ -239,8 +239,7 @@ __init_refok pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
 {
        pte_t *pte;
        if (mem_init_done) {
-               pte = (pte_t *)__get_free_page(GFP_KERNEL |
-                                       __GFP_REPEAT | __GFP_ZERO);
+               pte = (pte_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
        } else {
                pte = (pte_t *)early_get_page();
                if (pte)
index 6733ac5..36a391d 100644 (file)
@@ -74,7 +74,7 @@
 #define KVM_GUEST_KUSEG                        0x00000000UL
 #define KVM_GUEST_KSEG0                        0x40000000UL
 #define KVM_GUEST_KSEG23               0x60000000UL
-#define KVM_GUEST_KSEGX(a)             ((_ACAST32_(a)) & 0x60000000)
+#define KVM_GUEST_KSEGX(a)             ((_ACAST32_(a)) & 0xe0000000)
 #define KVM_GUEST_CPHYSADDR(a)         ((_ACAST32_(a)) & 0x1fffffff)
 
 #define KVM_GUEST_CKSEG0ADDR(a)                (KVM_GUEST_CPHYSADDR(a) | KVM_GUEST_KSEG0)
@@ -338,6 +338,7 @@ struct kvm_mips_tlb {
 #define KVM_MIPS_GUEST_TLB_SIZE        64
 struct kvm_vcpu_arch {
        void *host_ebase, *guest_ebase;
+       int (*vcpu_run)(struct kvm_run *run, struct kvm_vcpu *vcpu);
        unsigned long host_stack;
        unsigned long host_gp;
 
index b336037..93c079a 100644 (file)
@@ -69,7 +69,7 @@ static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
 {
        pte_t *pte;
 
-       pte = (pte_t *) __get_free_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, PTE_ORDER);
+       pte = (pte_t *) __get_free_pages(GFP_KERNEL|__GFP_ZERO, PTE_ORDER);
 
        return pte;
 }
@@ -79,7 +79,7 @@ static inline struct page *pte_alloc_one(struct mm_struct *mm,
 {
        struct page *pte;
 
-       pte = alloc_pages(GFP_KERNEL | __GFP_REPEAT, PTE_ORDER);
+       pte = alloc_pages(GFP_KERNEL, PTE_ORDER);
        if (!pte)
                return NULL;
        clear_highpage(pte);
@@ -113,7 +113,7 @@ static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
 {
        pmd_t *pmd;
 
-       pmd = (pmd_t *) __get_free_pages(GFP_KERNEL|__GFP_REPEAT, PMD_ORDER);
+       pmd = (pmd_t *) __get_free_pages(GFP_KERNEL, PMD_ORDER);
        if (pmd)
                pmd_init((unsigned long)pmd, (unsigned long)invalid_pte_table);
        return pmd;
index 396df6e..645c8a1 100644 (file)
@@ -1636,6 +1636,7 @@ enum emulation_result kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc,
                if (index < 0) {
                        vcpu->arch.host_cp0_entryhi = (va & VPN2_MASK);
                        vcpu->arch.host_cp0_badvaddr = va;
+                       vcpu->arch.pc = curr_pc;
                        er = kvm_mips_emulate_tlbmiss_ld(cause, NULL, run,
                                                         vcpu);
                        preempt_enable();
@@ -1647,6 +1648,8 @@ enum emulation_result kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc,
                         * invalid exception to the guest
                         */
                        if (!TLB_IS_VALID(*tlb, va)) {
+                               vcpu->arch.host_cp0_badvaddr = va;
+                               vcpu->arch.pc = curr_pc;
                                er = kvm_mips_emulate_tlbinv_ld(cause, NULL,
                                                                run, vcpu);
                                preempt_enable();
@@ -1666,7 +1669,7 @@ enum emulation_result kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc,
                        cache, op, base, arch->gprs[base], offset);
                er = EMULATE_FAIL;
                preempt_enable();
-               goto dont_update_pc;
+               goto done;
 
        }
 
@@ -1694,16 +1697,20 @@ skip_fault:
                kvm_err("NO-OP CACHE (cache: %#x, op: %#x, base[%d]: %#lx, offset: %#x\n",
                        cache, op, base, arch->gprs[base], offset);
                er = EMULATE_FAIL;
-               preempt_enable();
-               goto dont_update_pc;
        }
 
        preempt_enable();
+done:
+       /* Rollback PC only if emulation was unsuccessful */
+       if (er == EMULATE_FAIL)
+               vcpu->arch.pc = curr_pc;
 
 dont_update_pc:
-       /* Rollback PC */
-       vcpu->arch.pc = curr_pc;
-done:
+       /*
+        * This is for exceptions whose emulation updates the PC, so do not
+        * overwrite the PC under any circumstances
+        */
+
        return er;
 }
 
index 4ab4bdf..2143884 100644 (file)
@@ -28,6 +28,7 @@
 #define MIPS_EXC_MAX                12
 /* XXXSL More to follow */
 
+extern char __kvm_mips_vcpu_run_end[];
 extern char mips32_exception[], mips32_exceptionEnd[];
 extern char mips32_GuestException[], mips32_GuestExceptionEnd[];
 
index 3ef0300..828fcfc 100644 (file)
@@ -202,6 +202,7 @@ FEXPORT(__kvm_mips_load_k0k1)
 
        /* Jump to guest */
        eret
+EXPORT(__kvm_mips_vcpu_run_end)
 
 VECTOR(MIPSX(exception), unknown)
 /* Find out what mode we came from and jump to the proper handler. */
index dc052fb..44da525 100644 (file)
@@ -315,6 +315,15 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
        memcpy(gebase + offset, mips32_GuestException,
               mips32_GuestExceptionEnd - mips32_GuestException);
 
+#ifdef MODULE
+       offset += mips32_GuestExceptionEnd - mips32_GuestException;
+       memcpy(gebase + offset, (char *)__kvm_mips_vcpu_run,
+              __kvm_mips_vcpu_run_end - (char *)__kvm_mips_vcpu_run);
+       vcpu->arch.vcpu_run = gebase + offset;
+#else
+       vcpu->arch.vcpu_run = __kvm_mips_vcpu_run;
+#endif
+
        /* Invalidate the icache for these ranges */
        local_flush_icache_range((unsigned long)gebase,
                                (unsigned long)gebase + ALIGN(size, PAGE_SIZE));
@@ -404,7 +413,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
        /* Disable hardware page table walking while in guest */
        htw_stop();
 
-       r = __kvm_mips_vcpu_run(run, vcpu);
+       r = vcpu->arch.vcpu_run(run, vcpu);
 
        /* Re-enable HTW before enabling interrupts */
        htw_start();
index 4861a78..f5f90bb 100644 (file)
@@ -115,7 +115,7 @@ static inline unsigned long current_stack_pointer(void)
 }
 
 #ifndef CONFIG_KGDB
-void arch_release_thread_info(struct thread_info *ti);
+void arch_release_thread_stack(unsigned long *stack);
 #endif
 #define get_thread_info(ti)    get_task_struct((ti)->task)
 #define put_thread_info(ti)    put_task_struct((ti)->task)
index 9977082..2d7986c 100644 (file)
@@ -397,8 +397,9 @@ static bool kgdb_arch_undo_singlestep(struct pt_regs *regs)
  * single-step state is cleared.  At this point the breakpoints should have
  * been removed by __switch_to().
  */
-void arch_release_thread_info(struct thread_info *ti)
+void arch_release_thread_stack(unsigned long *stack)
 {
+       struct thread_info *ti = (void *)stack;
        if (kgdb_sstep_thread == ti) {
                kgdb_sstep_thread = NULL;
 
index e77a7c7..9577cf7 100644 (file)
@@ -63,7 +63,7 @@ void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags)
 
 pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
 {
-       pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT);
+       pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL);
        if (pte)
                clear_page(pte);
        return pte;
@@ -74,9 +74,9 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
        struct page *pte;
 
 #ifdef CONFIG_HIGHPTE
-       pte = alloc_pages(GFP_KERNEL|__GFP_HIGHMEM|__GFP_REPEAT, 0);
+       pte = alloc_pages(GFP_KERNEL|__GFP_HIGHMEM, 0);
 #else
-       pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT, 0);
+       pte = alloc_pages(GFP_KERNEL, 0);
 #endif
        if (!pte)
                return NULL;
index 6e2985e..bb47d08 100644 (file)
@@ -42,8 +42,7 @@ static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
 {
        pte_t *pte;
 
-       pte = (pte_t *) __get_free_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO,
-                                       PTE_ORDER);
+       pte = (pte_t *) __get_free_pages(GFP_KERNEL|__GFP_ZERO, PTE_ORDER);
 
        return pte;
 }
@@ -53,7 +52,7 @@ static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
 {
        struct page *pte;
 
-       pte = alloc_pages(GFP_KERNEL | __GFP_REPEAT, PTE_ORDER);
+       pte = alloc_pages(GFP_KERNEL, PTE_ORDER);
        if (pte) {
                if (!pgtable_page_ctor(pte)) {
                        __free_page(pte);
index 21484e5..87eebd1 100644 (file)
@@ -77,7 +77,7 @@ static inline struct page *pte_alloc_one(struct mm_struct *mm,
                                         unsigned long address)
 {
        struct page *pte;
-       pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT, 0);
+       pte = alloc_pages(GFP_KERNEL, 0);
        if (!pte)
                return NULL;
        clear_page(page_address(pte));
index 62b08ef..5b2a951 100644 (file)
@@ -122,7 +122,7 @@ pte_t __init_refok *pte_alloc_one_kernel(struct mm_struct *mm,
        pte_t *pte;
 
        if (likely(mem_init_done)) {
-               pte = (pte_t *) __get_free_page(GFP_KERNEL | __GFP_REPEAT);
+               pte = (pte_t *) __get_free_page(GFP_KERNEL);
        } else {
                pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
 #if 0
index f2fd327..f08dda3 100644 (file)
@@ -63,8 +63,7 @@ static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmd)
 
 static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
 {
-       pmd_t *pmd = (pmd_t *)__get_free_pages(GFP_KERNEL|__GFP_REPEAT,
-                                              PMD_ORDER);
+       pmd_t *pmd = (pmd_t *)__get_free_pages(GFP_KERNEL, PMD_ORDER);
        if (pmd)
                memset(pmd, 0, PAGE_SIZE<<PMD_ORDER);
        return pmd;
@@ -124,7 +123,7 @@ pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, pte_t *pte)
 static inline pgtable_t
 pte_alloc_one(struct mm_struct *mm, unsigned long address)
 {
-       struct page *page = alloc_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
+       struct page *page = alloc_page(GFP_KERNEL|__GFP_ZERO);
        if (!page)
                return NULL;
        if (!pgtable_page_ctor(page)) {
@@ -137,7 +136,7 @@ pte_alloc_one(struct mm_struct *mm, unsigned long address)
 static inline pte_t *
 pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr)
 {
-       pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
+       pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_ZERO);
        return pte;
 }
 
index 4736020..5e953ab 100644 (file)
@@ -8,6 +8,8 @@ struct pt_regs;
 void parisc_terminate(char *msg, struct pt_regs *regs,
                int code, unsigned long offset) __noreturn __cold;
 
+void die_if_kernel(char *str, struct pt_regs *regs, long err);
+
 /* mm/fault.c */
 void do_page_fault(struct pt_regs *regs, unsigned long code,
                unsigned long address);
index e81ccf1..5adc339 100644 (file)
@@ -324,8 +324,9 @@ int init_per_cpu(int cpunum)
                per_cpu(cpu_data, cpunum).fp_rev = coproc_cfg.revision;
                per_cpu(cpu_data, cpunum).fp_model = coproc_cfg.model;
 
-               printk(KERN_INFO  "FP[%d] enabled: Rev %ld Model %ld\n",
-                       cpunum, coproc_cfg.revision, coproc_cfg.model);
+               if (cpunum == 0)
+                       printk(KERN_INFO  "FP[%d] enabled: Rev %ld Model %ld\n",
+                               cpunum, coproc_cfg.revision, coproc_cfg.model);
 
                /*
                ** store status register to stack (hopefully aligned)
index 58dd680..31ec99a 100644 (file)
@@ -309,11 +309,6 @@ void __init time_init(void)
        clocks_calc_mult_shift(&cyc2ns_mul, &cyc2ns_shift, current_cr16_khz,
                                NSEC_PER_MSEC, 0);
 
-#if defined(CONFIG_HAVE_UNSTABLE_SCHED_CLOCK) && defined(CONFIG_64BIT)
-       /* At bootup only one 64bit CPU is online and cr16 is "stable" */
-       set_sched_clock_stable();
-#endif
-
        start_cpu_itimer();     /* get CPU 0 started */
 
        /* register at clocksource framework */
index d7c0acb..2b65c01 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/ratelimit.h>
 #include <asm/uaccess.h>
 #include <asm/hardirq.h>
+#include <asm/traps.h>
 
 /* #define DEBUG_UNALIGNED 1 */
 
 
 int unaligned_enabled __read_mostly = 1;
 
-void die_if_kernel (char *str, struct pt_regs *regs, long err);
-
 static int emulate_ldh(struct pt_regs *regs, int toreg)
 {
        unsigned long saddr = regs->ior;
@@ -666,7 +665,7 @@ void handle_unaligned(struct pt_regs *regs)
                break;
        }
 
-       if (modify && R1(regs->iir))
+       if (ret == 0 && modify && R1(regs->iir))
                regs->gr[R1(regs->iir)] = newbase;
 
 
@@ -677,6 +676,14 @@ void handle_unaligned(struct pt_regs *regs)
 
        if (ret)
        {
+               /*
+                * The unaligned handler failed.
+                * If we were called by __get_user() or __put_user() jump
+                * to it's exception fixup handler instead of crashing.
+                */
+               if (!user_mode(regs) && fixup_exception(regs))
+                       return;
+
                printk(KERN_CRIT "Unaligned handler failed, ret = %d\n", ret);
                die_if_kernel("Unaligned data reference", regs, 28);
 
index ddd988b..e278a87 100644 (file)
@@ -75,7 +75,10 @@ find_unwind_entry(unsigned long addr)
        if (addr >= kernel_unwind_table.start && 
            addr <= kernel_unwind_table.end)
                e = find_unwind_entry_in_table(&kernel_unwind_table, addr);
-       else 
+       else {
+               unsigned long flags;
+
+               spin_lock_irqsave(&unwind_lock, flags);
                list_for_each_entry(table, &unwind_tables, list) {
                        if (addr >= table->start && 
                            addr <= table->end)
@@ -86,6 +89,8 @@ find_unwind_entry(unsigned long addr)
                                break;
                        }
                }
+               spin_unlock_irqrestore(&unwind_lock, flags);
+       }
 
        return e;
 }
@@ -303,18 +308,16 @@ static void unwind_frame_regs(struct unwind_frame_info *info)
 
                        insn = *(unsigned int *)npc;
 
-                       if ((insn & 0xffffc000) == 0x37de0000 ||
-                           (insn & 0xffe00000) == 0x6fc00000) {
+                       if ((insn & 0xffffc001) == 0x37de0000 ||
+                           (insn & 0xffe00001) == 0x6fc00000) {
                                /* ldo X(sp), sp, or stwm X,D(sp) */
-                               frame_size += (insn & 0x1 ? -1 << 13 : 0) | 
-                                       ((insn & 0x3fff) >> 1);
+                               frame_size += (insn & 0x3fff) >> 1;
                                dbg("analyzing func @ %lx, insn=%08x @ "
                                    "%lx, frame_size = %ld\n", info->ip,
                                    insn, npc, frame_size);
-                       } else if ((insn & 0xffe00008) == 0x73c00008) {
+                       } else if ((insn & 0xffe00009) == 0x73c00008) {
                                /* std,ma X,D(sp) */
-                               frame_size += (insn & 0x1 ? -1 << 13 : 0) | 
-                                       (((insn >> 4) & 0x3ff) << 3);
+                               frame_size += ((insn >> 4) & 0x3ff) << 3;
                                dbg("analyzing func @ %lx, insn=%08x @ "
                                    "%lx, frame_size = %ld\n", info->ip,
                                    insn, npc, frame_size);
@@ -333,6 +336,9 @@ static void unwind_frame_regs(struct unwind_frame_info *info)
                        }
                }
 
+               if (frame_size > e->Total_frame_size << 3)
+                       frame_size = e->Total_frame_size << 3;
+
                if (!unwind_special(info, e->region_start, frame_size)) {
                        info->prev_sp = info->sp - frame_size;
                        if (e->Millicode)
index 01f7464..0a9d439 100644 (file)
@@ -128,7 +128,7 @@ config PPC
        select IRQ_FORCED_THREADING
        select HAVE_RCU_TABLE_FREE if SMP
        select HAVE_SYSCALL_TRACEPOINTS
-       select HAVE_CBPF_JIT
+       select HAVE_CBPF_JIT if CPU_BIG_ENDIAN
        select HAVE_ARCH_JUMP_LABEL
        select ARCH_HAVE_NMI_SAFE_CMPXCHG
        select ARCH_HAS_GCOV_PROFILE_ALL
index a235019..8e21bb4 100644 (file)
@@ -102,7 +102,6 @@ static inline void pgtable_free_tlb(struct mmu_gather *tlb,
 static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table,
                                  unsigned long address)
 {
-       tlb_flush_pgtable(tlb, address);
        pgtable_page_dtor(table);
        pgtable_free_tlb(tlb, page_address(table), 0);
 }
index 290157e..74839f2 100644 (file)
@@ -88,6 +88,7 @@
 #define HPTE_R_RPN_SHIFT       12
 #define HPTE_R_RPN             ASM_CONST(0x0ffffffffffff000)
 #define HPTE_R_PP              ASM_CONST(0x0000000000000003)
+#define HPTE_R_PPP             ASM_CONST(0x8000000000000003)
 #define HPTE_R_N               ASM_CONST(0x0000000000000004)
 #define HPTE_R_G               ASM_CONST(0x0000000000000008)
 #define HPTE_R_M               ASM_CONST(0x0000000000000010)
index 488279e..cd5e7aa 100644 (file)
@@ -41,7 +41,7 @@ extern struct kmem_cache *pgtable_cache[];
                        pgtable_cache[(shift) - 1];     \
                })
 
-#define PGALLOC_GFP GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO
+#define PGALLOC_GFP GFP_KERNEL | __GFP_NOTRACK | __GFP_ZERO
 
 extern pte_t *pte_fragment_alloc(struct mm_struct *, unsigned long, int);
 extern void pte_fragment_free(unsigned long *, int);
@@ -56,7 +56,7 @@ static inline pgd_t *radix__pgd_alloc(struct mm_struct *mm)
        return (pgd_t *)__get_free_page(PGALLOC_GFP);
 #else
        struct page *page;
-       page = alloc_pages(PGALLOC_GFP, 4);
+       page = alloc_pages(PGALLOC_GFP | __GFP_REPEAT, 4);
        if (!page)
                return NULL;
        return (pgd_t *) page_address(page);
@@ -93,8 +93,7 @@ static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)
 
 static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
 {
-       return kmem_cache_alloc(PGT_CACHE(PUD_INDEX_SIZE),
-                               GFP_KERNEL|__GFP_REPEAT);
+       return kmem_cache_alloc(PGT_CACHE(PUD_INDEX_SIZE), GFP_KERNEL);
 }
 
 static inline void pud_free(struct mm_struct *mm, pud_t *pud)
@@ -110,13 +109,17 @@ static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
 static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
                                   unsigned long address)
 {
+       /*
+        * By now all the pud entries should be none entries. So go
+        * ahead and flush the page walk cache
+        */
+       flush_tlb_pgtable(tlb, address);
         pgtable_free_tlb(tlb, pud, PUD_INDEX_SIZE);
 }
 
 static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
 {
-       return kmem_cache_alloc(PGT_CACHE(PMD_CACHE_INDEX),
-                               GFP_KERNEL|__GFP_REPEAT);
+       return kmem_cache_alloc(PGT_CACHE(PMD_CACHE_INDEX), GFP_KERNEL);
 }
 
 static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
@@ -127,6 +130,11 @@ static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
 static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd,
                                   unsigned long address)
 {
+       /*
+        * By now all the pud entries should be none entries. So go
+        * ahead and flush the page walk cache
+        */
+       flush_tlb_pgtable(tlb, address);
         return pgtable_free_tlb(tlb, pmd, PMD_CACHE_INDEX);
 }
 
@@ -151,7 +159,7 @@ static inline pgtable_t pmd_pgtable(pmd_t pmd)
 static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
                                          unsigned long address)
 {
-       return (pte_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO);
+       return (pte_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
 }
 
 static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
@@ -198,7 +206,11 @@ static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage)
 static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table,
                                  unsigned long address)
 {
-       tlb_flush_pgtable(tlb, address);
+       /*
+        * By now all the pud entries should be none entries. So go
+        * ahead and flush the page walk cache
+        */
+       flush_tlb_pgtable(tlb, address);
        pgtable_free_tlb(tlb, table, 0);
 }
 
index 937d4e2..df29422 100644 (file)
@@ -228,5 +228,20 @@ extern void radix__vmemmap_remove_mapping(unsigned long start,
 
 extern int radix__map_kernel_page(unsigned long ea, unsigned long pa,
                                 pgprot_t flags, unsigned int psz);
+
+static inline unsigned long radix__get_tree_size(void)
+{
+       unsigned long rts_field;
+       /*
+        * we support 52 bits, hence 52-31 = 21, 0b10101
+        * RTS encoding details
+        * bits 0 - 3 of rts -> bits 6 - 8 unsigned long
+        * bits 4 - 5 of rts -> bits 62 - 63 of unsigned long
+        */
+       rts_field = (0x5UL << 5); /* 6 - 8 bits */
+       rts_field |= (0x2UL << 61);
+
+       return rts_field;
+}
 #endif /* __ASSEMBLY__ */
 #endif
index 13ef388..3fa94fc 100644 (file)
@@ -18,16 +18,19 @@ extern void radix__local_flush_tlb_mm(struct mm_struct *mm);
 extern void radix__local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
 extern void radix___local_flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
                                    unsigned long ap, int nid);
+extern void radix__local_flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr);
 extern void radix__tlb_flush(struct mmu_gather *tlb);
 #ifdef CONFIG_SMP
 extern void radix__flush_tlb_mm(struct mm_struct *mm);
 extern void radix__flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
 extern void radix___flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
                              unsigned long ap, int nid);
+extern void radix__flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr);
 #else
 #define radix__flush_tlb_mm(mm)                radix__local_flush_tlb_mm(mm)
 #define radix__flush_tlb_page(vma,addr)        radix__local_flush_tlb_page(vma,addr)
 #define radix___flush_tlb_page(mm,addr,p,i)    radix___local_flush_tlb_page(mm,addr,p,i)
+#define radix__flush_tlb_pwc(tlb, addr)        radix__local_flush_tlb_pwc(tlb, addr)
 #endif
 
 #endif
index d98424a..96e5769 100644 (file)
@@ -72,5 +72,19 @@ static inline void flush_tlb_page(struct vm_area_struct *vma,
 #define flush_tlb_mm(mm)               local_flush_tlb_mm(mm)
 #define flush_tlb_page(vma, addr)      local_flush_tlb_page(vma, addr)
 #endif /* CONFIG_SMP */
+/*
+ * flush the page walk cache for the address
+ */
+static inline void flush_tlb_pgtable(struct mmu_gather *tlb, unsigned long address)
+{
+       /*
+        * Flush the page table walk cache on freeing a page table. We already
+        * have marked the upper/higher level page table entry none by now.
+        * So it is safe to flush PWC here.
+        */
+       if (!radix_enabled())
+               return;
 
+       radix__flush_tlb_pwc(tlb, address);
+}
 #endif /*  _ASM_POWERPC_BOOK3S_64_TLBFLUSH_H */
index 54f591e..c0a69ae 100644 (file)
@@ -4,11 +4,6 @@
 #include <linux/mm.h>
 
 extern void tlb_remove_table(struct mmu_gather *tlb, void *table);
-static inline void tlb_flush_pgtable(struct mmu_gather *tlb,
-                                    unsigned long address)
-{
-
-}
 
 #ifdef CONFIG_PPC64
 #include <asm/book3s/64/pgalloc.h>
index 0c12a3b..897d2e1 100644 (file)
@@ -57,8 +57,7 @@ static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
 
 static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
 {
-       return kmem_cache_alloc(PGT_CACHE(PUD_INDEX_SIZE),
-                               GFP_KERNEL|__GFP_REPEAT);
+       return kmem_cache_alloc(PGT_CACHE(PUD_INDEX_SIZE), GFP_KERNEL);
 }
 
 static inline void pud_free(struct mm_struct *mm, pud_t *pud)
@@ -88,7 +87,7 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
 static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
                                          unsigned long address)
 {
-       return (pte_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO);
+       return (pte_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
 }
 
 static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
@@ -172,7 +171,7 @@ static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
 
 static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
 {
-       pte_fragment_fre((unsigned long *)pte, 1);
+       pte_fragment_free((unsigned long *)pte, 1);
 }
 
 static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage)
@@ -190,8 +189,7 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table,
 
 static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
 {
-       return kmem_cache_alloc(PGT_CACHE(PMD_CACHE_INDEX),
-                               GFP_KERNEL|__GFP_REPEAT);
+       return kmem_cache_alloc(PGT_CACHE(PMD_CACHE_INDEX), GFP_KERNEL);
 }
 
 static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
index c1e82e9..a0948f4 100644 (file)
 #define   MMCR0_FCWAIT 0x00000002UL /* freeze counter in WAIT state */
 #define   MMCR0_FCHV   0x00000001UL /* freeze conditions in hypervisor mode */
 #define SPRN_MMCR1     798
-#define SPRN_MMCR2     769
+#define SPRN_MMCR2     785
 #define SPRN_MMCRA     0x312
 #define   MMCRA_SDSYNC 0x80000000UL /* SDAR synced with SIAR */
 #define   MMCRA_SDAR_DCACHE_MISS 0x40000000UL
 #define SPRN_PMC6      792
 #define SPRN_PMC7      793
 #define SPRN_PMC8      794
-#define SPRN_SIAR      780
-#define SPRN_SDAR      781
 #define SPRN_SIER      784
 #define   SIER_SIPR            0x2000000       /* Sampled MSR_PR */
 #define   SIER_SIHV            0x1000000       /* Sampled MSR_HV */
 #define   SIER_SIAR_VALID      0x0400000       /* SIAR contents valid */
 #define   SIER_SDAR_VALID      0x0200000       /* SDAR contents valid */
+#define SPRN_SIAR      796
+#define SPRN_SDAR      797
 #define SPRN_TACR      888
 #define SPRN_TCSCR     889
 #define SPRN_CSIGR     890
index 2714a3b..b5f73cb 100644 (file)
@@ -642,7 +642,6 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus,
                if (pe->type & EEH_PE_VF) {
                        eeh_pe_dev_traverse(pe, eeh_rmv_device, NULL);
                } else {
-                       eeh_pe_state_clear(pe, EEH_PE_PRI_BUS);
                        pci_lock_rescan_remove();
                        pci_hp_remove_devices(bus);
                        pci_unlock_rescan_remove();
@@ -692,10 +691,12 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus,
                 */
                edev = list_first_entry(&pe->edevs, struct eeh_dev, list);
                eeh_pe_traverse(pe, eeh_pe_detach_dev, NULL);
-               if (pe->type & EEH_PE_VF)
+               if (pe->type & EEH_PE_VF) {
                        eeh_add_virt_device(edev, NULL);
-               else
+               } else {
+                       eeh_pe_state_clear(pe, EEH_PE_PRI_BUS);
                        pci_hp_add_devices(bus);
+               }
        } else if (frozen_bus && rmv_data->removed) {
                pr_info("EEH: Sleep 5s ahead of partial hotplug\n");
                ssleep(5);
index 4c94406..8bcc1b4 100644 (file)
@@ -1399,11 +1399,12 @@ END_MMU_FTR_SECTION_IFCLR(MMU_FTR_RADIX)
        lwz     r9,PACA_EXSLB+EX_CCR(r13)       /* get saved CR */
 
        mtlr    r10
-BEGIN_MMU_FTR_SECTION
-       b       2f
-END_MMU_FTR_SECTION_IFSET(MMU_FTR_RADIX)
        andi.   r10,r12,MSR_RI  /* check for unrecoverable exception */
+BEGIN_MMU_FTR_SECTION
        beq-    2f
+FTR_SECTION_ELSE
+       b       2f
+ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_RADIX)
 
 .machine       push
 .machine       "power4"
index da51925..6ee4b72 100644 (file)
@@ -656,6 +656,7 @@ unsigned char ibm_architecture_vec[] = {
        W(0xffff0000), W(0x003e0000),   /* POWER6 */
        W(0xffff0000), W(0x003f0000),   /* POWER7 */
        W(0xffff0000), W(0x004b0000),   /* POWER8E */
+       W(0xffff0000), W(0x004c0000),   /* POWER8NVL */
        W(0xffff0000), W(0x004d0000),   /* POWER8 */
        W(0xffffffff), W(0x0f000004),   /* all 2.07-compliant */
        W(0xffffffff), W(0x0f000003),   /* all 2.06-compliant */
@@ -718,7 +719,7 @@ unsigned char ibm_architecture_vec[] = {
         * must match by the macro below. Update the definition if
         * the structure layout changes.
         */
-#define IBM_ARCH_VEC_NRCORES_OFFSET    125
+#define IBM_ARCH_VEC_NRCORES_OFFSET    133
        W(NR_CPUS),                     /* number of cores supported */
        0,
        0,
index 30a03c0..060b140 100644 (file)
@@ -377,7 +377,7 @@ static int fpr_get(struct task_struct *target, const struct user_regset *regset,
 
 #else
        BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) !=
-                    offsetof(struct thread_fp_state, fpr[32][0]));
+                    offsetof(struct thread_fp_state, fpr[32]));
 
        return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
                                   &target->thread.fp_state, 0, -1);
@@ -405,7 +405,7 @@ static int fpr_set(struct task_struct *target, const struct user_regset *regset,
        return 0;
 #else
        BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) !=
-                    offsetof(struct thread_fp_state, fpr[32][0]));
+                    offsetof(struct thread_fp_state, fpr[32]));
 
        return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
                                  &target->thread.fp_state, 0, -1);
index d873f65..f8a871a 100644 (file)
@@ -316,8 +316,8 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
                        DBG_LOW(" -> hit\n");
                        /* Update the HPTE */
                        hptep->r = cpu_to_be64((be64_to_cpu(hptep->r) &
-                                               ~(HPTE_R_PP | HPTE_R_N)) |
-                                              (newpp & (HPTE_R_PP | HPTE_R_N |
+                                               ~(HPTE_R_PPP | HPTE_R_N)) |
+                                              (newpp & (HPTE_R_PPP | HPTE_R_N |
                                                         HPTE_R_C)));
                }
                native_unlock_hpte(hptep);
@@ -385,8 +385,8 @@ static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
 
        /* Update the HPTE */
        hptep->r = cpu_to_be64((be64_to_cpu(hptep->r) &
-                       ~(HPTE_R_PP | HPTE_R_N)) |
-               (newpp & (HPTE_R_PP | HPTE_R_N)));
+                               ~(HPTE_R_PPP | HPTE_R_N)) |
+                              (newpp & (HPTE_R_PPP | HPTE_R_N)));
        /*
         * Ensure it is out of the tlb too. Bolted entries base and
         * actual page size will be same.
@@ -550,7 +550,11 @@ static void hpte_decode(struct hash_pte *hpte, unsigned long slot,
                }
        }
        /* This works for all page sizes, and for 256M and 1T segments */
-       *ssize = hpte_v >> HPTE_V_SSIZE_SHIFT;
+       if (cpu_has_feature(CPU_FTR_ARCH_300))
+               *ssize = hpte_r >> HPTE_R_3_0_SSIZE_SHIFT;
+       else
+               *ssize = hpte_v >> HPTE_V_SSIZE_SHIFT;
+
        shift = mmu_psize_defs[size].shift;
 
        avpn = (HPTE_V_AVPN_VAL(hpte_v) & ~mmu_psize_defs[size].avpnm);
index 5926896..5b22ba0 100644 (file)
@@ -159,6 +159,19 @@ static struct mmu_psize_def mmu_psize_defaults_gp[] = {
        },
 };
 
+/*
+ * 'R' and 'C' update notes:
+ *  - Under pHyp or KVM, the updatepp path will not set C, thus it *will*
+ *     create writeable HPTEs without C set, because the hcall H_PROTECT
+ *     that we use in that case will not update C
+ *  - The above is however not a problem, because we also don't do that
+ *     fancy "no flush" variant of eviction and we use H_REMOVE which will
+ *     do the right thing and thus we don't have the race I described earlier
+ *
+ *    - Under bare metal,  we do have the race, so we need R and C set
+ *    - We make sure R is always set and never lost
+ *    - C is _PAGE_DIRTY, and *should* always be set for a writeable mapping
+ */
 unsigned long htab_convert_pte_flags(unsigned long pteflags)
 {
        unsigned long rflags = 0;
@@ -186,19 +199,28 @@ unsigned long htab_convert_pte_flags(unsigned long pteflags)
                        rflags |= 0x1;
        }
        /*
-        * Always add "C" bit for perf. Memory coherence is always enabled
+        * We can't allow hardware to update hpte bits. Hence always
+        * set 'R' bit and set 'C' if it is a write fault
         */
-       rflags |=  HPTE_R_C | HPTE_R_M;
+       rflags |=  HPTE_R_R;
+
+       if (pteflags & _PAGE_DIRTY)
+               rflags |= HPTE_R_C;
        /*
         * Add in WIG bits
         */
 
        if ((pteflags & _PAGE_CACHE_CTL) == _PAGE_TOLERANT)
                rflags |= HPTE_R_I;
-       if ((pteflags & _PAGE_CACHE_CTL ) == _PAGE_NON_IDEMPOTENT)
+       else if ((pteflags & _PAGE_CACHE_CTL) == _PAGE_NON_IDEMPOTENT)
                rflags |= (HPTE_R_I | HPTE_R_G);
-       if ((pteflags & _PAGE_CACHE_CTL) == _PAGE_SAO)
-               rflags |= (HPTE_R_I | HPTE_R_W);
+       else if ((pteflags & _PAGE_CACHE_CTL) == _PAGE_SAO)
+               rflags |= (HPTE_R_W | HPTE_R_I | HPTE_R_M);
+       else
+               /*
+                * Add memory coherence if cache inhibited is not set
+                */
+               rflags |= HPTE_R_M;
 
        return rflags;
 }
index 5aac1a3..119d186 100644 (file)
@@ -73,7 +73,7 @@ static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
        cachep = PGT_CACHE(pdshift - pshift);
 #endif
 
-       new = kmem_cache_zalloc(cachep, GFP_KERNEL|__GFP_REPEAT);
+       new = kmem_cache_zalloc(cachep, GFP_KERNEL);
 
        BUG_ON(pshift > HUGEPD_SHIFT_MASK);
        BUG_ON((unsigned long)new & HUGEPD_SHIFT_MASK);
index 227b2a6..1962222 100644 (file)
@@ -65,7 +65,7 @@ static int radix__init_new_context(struct mm_struct *mm, int index)
        /*
         * set the process table entry,
         */
-       rts_field = 3ull << PPC_BITLSHIFT(2);
+       rts_field = radix__get_tree_size();
        process_tb[index].prtb0 = cpu_to_be64(rts_field | __pa(mm->pgd) | RADIX_PGD_INDEX_SIZE);
        return 0;
 }
index eb44511..6703187 100644 (file)
@@ -33,10 +33,7 @@ int pmdp_set_access_flags(struct vm_area_struct *vma, unsigned long address,
        changed = !pmd_same(*(pmdp), entry);
        if (changed) {
                __ptep_set_access_flags(pmdp_ptep(pmdp), pmd_pte(entry));
-               /*
-                * Since we are not supporting SW TLB systems, we don't
-                * have any thing similar to flush_tlb_page_nohash()
-                */
+               flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
        }
        return changed;
 }
index 18b2c11..e58707d 100644 (file)
@@ -160,9 +160,8 @@ redo:
        process_tb = early_alloc_pgtable(1UL << PRTB_SIZE_SHIFT);
        /*
         * Fill in the process table.
-        * we support 52 bits, hence 52-28 = 24, 11000
         */
-       rts_field = 3ull << PPC_BITLSHIFT(2);
+       rts_field = radix__get_tree_size();
        process_tb->prtb0 = cpu_to_be64(rts_field | __pa(init_mm.pgd) | RADIX_PGD_INDEX_SIZE);
        /*
         * Fill in the partition table. We are suppose to use effective address
@@ -176,10 +175,8 @@ redo:
 static void __init radix_init_partition_table(void)
 {
        unsigned long rts_field;
-       /*
-        * we support 52 bits, hence 52-28 = 24, 11000
-        */
-       rts_field = 3ull << PPC_BITLSHIFT(2);
+
+       rts_field = radix__get_tree_size();
 
        BUILD_BUG_ON_MSG((PATB_SIZE_SHIFT > 24), "Partition table size too large.");
        partition_tb = early_alloc_pgtable(1UL << PATB_SIZE_SHIFT);
@@ -296,11 +293,6 @@ found:
 void __init radix__early_init_mmu(void)
 {
        unsigned long lpcr;
-       /*
-        * setup LPCR UPRT based on mmu_features
-        */
-       lpcr = mfspr(SPRN_LPCR);
-       mtspr(SPRN_LPCR, lpcr | LPCR_UPRT);
 
 #ifdef CONFIG_PPC_64K_PAGES
        /* PAGE_SIZE mappings */
@@ -343,8 +335,11 @@ void __init radix__early_init_mmu(void)
        __pte_frag_size_shift = H_PTE_FRAG_SIZE_SHIFT;
 
        radix_init_page_sizes();
-       if (!firmware_has_feature(FW_FEATURE_LPAR))
+       if (!firmware_has_feature(FW_FEATURE_LPAR)) {
+               lpcr = mfspr(SPRN_LPCR);
+               mtspr(SPRN_LPCR, lpcr | LPCR_UPRT);
                radix_init_partition_table();
+       }
 
        radix_init_pgtable();
 }
@@ -353,16 +348,15 @@ void radix__early_init_mmu_secondary(void)
 {
        unsigned long lpcr;
        /*
-        * setup LPCR UPRT based on mmu_features
-        */
-       lpcr = mfspr(SPRN_LPCR);
-       mtspr(SPRN_LPCR, lpcr | LPCR_UPRT);
-       /*
-        * update partition table control register, 64 K size.
+        * update partition table control register and UPRT
         */
-       if (!firmware_has_feature(FW_FEATURE_LPAR))
+       if (!firmware_has_feature(FW_FEATURE_LPAR)) {
+               lpcr = mfspr(SPRN_LPCR);
+               mtspr(SPRN_LPCR, lpcr | LPCR_UPRT);
+
                mtspr(SPRN_PTCR,
                      __pa(partition_tb) | (PATB_SIZE_SHIFT - 12));
+       }
 }
 
 void radix__setup_initial_memory_limit(phys_addr_t first_memblock_base,
index bf7bf32..7f922f5 100644 (file)
@@ -84,7 +84,7 @@ __init_refok pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long add
        pte_t *pte;
 
        if (slab_is_available()) {
-               pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
+               pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_ZERO);
        } else {
                pte = __va(memblock_alloc(PAGE_SIZE, PAGE_SIZE));
                if (pte)
@@ -97,7 +97,7 @@ pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
 {
        struct page *ptepage;
 
-       gfp_t flags = GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO;
+       gfp_t flags = GFP_KERNEL | __GFP_ZERO;
 
        ptepage = alloc_pages(flags, 0);
        if (!ptepage)
index e009e06..f5e8d4e 100644 (file)
@@ -350,8 +350,7 @@ static pte_t *get_from_cache(struct mm_struct *mm)
 static pte_t *__alloc_for_cache(struct mm_struct *mm, int kernel)
 {
        void *ret = NULL;
-       struct page *page = alloc_page(GFP_KERNEL | __GFP_NOTRACK |
-                                      __GFP_REPEAT | __GFP_ZERO);
+       struct page *page = alloc_page(GFP_KERNEL | __GFP_NOTRACK | __GFP_ZERO);
        if (!page)
                return NULL;
        if (!kernel && !pgtable_page_ctor(page)) {
index 0fdaf93..ab2f60e 100644 (file)
 
 static DEFINE_RAW_SPINLOCK(native_tlbie_lock);
 
-static inline void __tlbiel_pid(unsigned long pid, int set)
+#define RIC_FLUSH_TLB 0
+#define RIC_FLUSH_PWC 1
+#define RIC_FLUSH_ALL 2
+
+static inline void __tlbiel_pid(unsigned long pid, int set,
+                               unsigned long ric)
 {
-       unsigned long rb,rs,ric,prs,r;
+       unsigned long rb,rs,prs,r;
 
        rb = PPC_BIT(53); /* IS = 1 */
        rb |= set << PPC_BITLSHIFT(51);
        rs = ((unsigned long)pid) << PPC_BITLSHIFT(31);
        prs = 1; /* process scoped */
        r = 1;   /* raidx format */
-       ric = 2;  /* invalidate all the caches */
 
        asm volatile("ptesync": : :"memory");
        asm volatile(".long 0x7c000224 | (%0 << 11) | (%1 << 16) |"
@@ -39,25 +43,24 @@ static inline void __tlbiel_pid(unsigned long pid, int set)
 /*
  * We use 128 set in radix mode and 256 set in hpt mode.
  */
-static inline void _tlbiel_pid(unsigned long pid)
+static inline void _tlbiel_pid(unsigned long pid, unsigned long ric)
 {
        int set;
 
        for (set = 0; set < POWER9_TLB_SETS_RADIX ; set++) {
-               __tlbiel_pid(pid, set);
+               __tlbiel_pid(pid, set, ric);
        }
        return;
 }
 
-static inline void _tlbie_pid(unsigned long pid)
+static inline void _tlbie_pid(unsigned long pid, unsigned long ric)
 {
-       unsigned long rb,rs,ric,prs,r;
+       unsigned long rb,rs,prs,r;
 
        rb = PPC_BIT(53); /* IS = 1 */
        rs = pid << PPC_BITLSHIFT(31);
        prs = 1; /* process scoped */
        r = 1;   /* raidx format */
-       ric = 2;  /* invalidate all the caches */
 
        asm volatile("ptesync": : :"memory");
        asm volatile(".long 0x7c000264 | (%0 << 11) | (%1 << 16) |"
@@ -67,16 +70,15 @@ static inline void _tlbie_pid(unsigned long pid)
 }
 
 static inline void _tlbiel_va(unsigned long va, unsigned long pid,
-                             unsigned long ap)
+                             unsigned long ap, unsigned long ric)
 {
-       unsigned long rb,rs,ric,prs,r;
+       unsigned long rb,rs,prs,r;
 
        rb = va & ~(PPC_BITMASK(52, 63));
        rb |= ap << PPC_BITLSHIFT(58);
        rs = pid << PPC_BITLSHIFT(31);
        prs = 1; /* process scoped */
        r = 1;   /* raidx format */
-       ric = 0;  /* no cluster flush yet */
 
        asm volatile("ptesync": : :"memory");
        asm volatile(".long 0x7c000224 | (%0 << 11) | (%1 << 16) |"
@@ -86,16 +88,15 @@ static inline void _tlbiel_va(unsigned long va, unsigned long pid,
 }
 
 static inline void _tlbie_va(unsigned long va, unsigned long pid,
-                            unsigned long ap)
+                            unsigned long ap, unsigned long ric)
 {
-       unsigned long rb,rs,ric,prs,r;
+       unsigned long rb,rs,prs,r;
 
        rb = va & ~(PPC_BITMASK(52, 63));
        rb |= ap << PPC_BITLSHIFT(58);
        rs = pid << PPC_BITLSHIFT(31);
        prs = 1; /* process scoped */
        r = 1;   /* raidx format */
-       ric = 0;  /* no cluster flush yet */
 
        asm volatile("ptesync": : :"memory");
        asm volatile(".long 0x7c000264 | (%0 << 11) | (%1 << 16) |"
@@ -117,25 +118,40 @@ static inline void _tlbie_va(unsigned long va, unsigned long pid,
  */
 void radix__local_flush_tlb_mm(struct mm_struct *mm)
 {
-       unsigned int pid;
+       unsigned long pid;
 
        preempt_disable();
        pid = mm->context.id;
        if (pid != MMU_NO_CONTEXT)
-               _tlbiel_pid(pid);
+               _tlbiel_pid(pid, RIC_FLUSH_ALL);
        preempt_enable();
 }
 EXPORT_SYMBOL(radix__local_flush_tlb_mm);
 
+void radix__local_flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr)
+{
+       unsigned long pid;
+       struct mm_struct *mm = tlb->mm;
+
+       preempt_disable();
+
+       pid = mm->context.id;
+       if (pid != MMU_NO_CONTEXT)
+               _tlbiel_pid(pid, RIC_FLUSH_PWC);
+
+       preempt_enable();
+}
+EXPORT_SYMBOL(radix__local_flush_tlb_pwc);
+
 void radix___local_flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
                            unsigned long ap, int nid)
 {
-       unsigned int pid;
+       unsigned long pid;
 
        preempt_disable();
        pid = mm ? mm->context.id : 0;
        if (pid != MMU_NO_CONTEXT)
-               _tlbiel_va(vmaddr, pid, ap);
+               _tlbiel_va(vmaddr, pid, ap, RIC_FLUSH_TLB);
        preempt_enable();
 }
 
@@ -160,7 +176,7 @@ static int mm_is_core_local(struct mm_struct *mm)
 
 void radix__flush_tlb_mm(struct mm_struct *mm)
 {
-       unsigned int pid;
+       unsigned long pid;
 
        preempt_disable();
        pid = mm->context.id;
@@ -172,20 +188,46 @@ void radix__flush_tlb_mm(struct mm_struct *mm)
 
                if (lock_tlbie)
                        raw_spin_lock(&native_tlbie_lock);
-               _tlbie_pid(pid);
+               _tlbie_pid(pid, RIC_FLUSH_ALL);
                if (lock_tlbie)
                        raw_spin_unlock(&native_tlbie_lock);
        } else
-               _tlbiel_pid(pid);
+               _tlbiel_pid(pid, RIC_FLUSH_ALL);
 no_context:
        preempt_enable();
 }
 EXPORT_SYMBOL(radix__flush_tlb_mm);
 
+void radix__flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr)
+{
+       unsigned long pid;
+       struct mm_struct *mm = tlb->mm;
+
+       preempt_disable();
+
+       pid = mm->context.id;
+       if (unlikely(pid == MMU_NO_CONTEXT))
+               goto no_context;
+
+       if (!mm_is_core_local(mm)) {
+               int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
+
+               if (lock_tlbie)
+                       raw_spin_lock(&native_tlbie_lock);
+               _tlbie_pid(pid, RIC_FLUSH_PWC);
+               if (lock_tlbie)
+                       raw_spin_unlock(&native_tlbie_lock);
+       } else
+               _tlbiel_pid(pid, RIC_FLUSH_PWC);
+no_context:
+       preempt_enable();
+}
+EXPORT_SYMBOL(radix__flush_tlb_pwc);
+
 void radix___flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
                       unsigned long ap, int nid)
 {
-       unsigned int pid;
+       unsigned long pid;
 
        preempt_disable();
        pid = mm ? mm->context.id : 0;
@@ -196,11 +238,11 @@ void radix___flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
 
                if (lock_tlbie)
                        raw_spin_lock(&native_tlbie_lock);
-               _tlbie_va(vmaddr, pid, ap);
+               _tlbie_va(vmaddr, pid, ap, RIC_FLUSH_TLB);
                if (lock_tlbie)
                        raw_spin_unlock(&native_tlbie_lock);
        } else
-               _tlbiel_va(vmaddr, pid, ap);
+               _tlbiel_va(vmaddr, pid, ap, RIC_FLUSH_TLB);
 bail:
        preempt_enable();
 }
@@ -224,7 +266,7 @@ void radix__flush_tlb_kernel_range(unsigned long start, unsigned long end)
 
        if (lock_tlbie)
                raw_spin_lock(&native_tlbie_lock);
-       _tlbie_pid(0);
+       _tlbie_pid(0, RIC_FLUSH_ALL);
        if (lock_tlbie)
                raw_spin_unlock(&native_tlbie_lock);
 }
index c50ea76..6081fbd 100644 (file)
@@ -221,7 +221,7 @@ static bool soc_has_mclk_mux0_canin(void)
 /* convenience wrappers around the common clk API */
 static inline struct clk *mpc512x_clk_fixed(const char *name, int rate)
 {
-       return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate);
+       return clk_register_fixed_rate(NULL, name, NULL, 0, rate);
 }
 
 static inline struct clk *mpc512x_clk_factor(
index 84fb984..85c85eb 100644 (file)
@@ -172,7 +172,7 @@ static int spufs_arch_write_note(struct spu_context *ctx, int i,
        if (rc < 0)
                goto out;
 
-       skip = roundup(cprm->file->f_pos - total + sz, 4) - cprm->file->f_pos;
+       skip = roundup(cprm->pos - total + sz, 4) - cprm->pos;
        if (!dump_skip(cprm, skip))
                goto Eio;
 out:
index ac3ffd9..3998e0f 100644 (file)
@@ -53,7 +53,6 @@ static int ibm_read_slot_reset_state2;
 static int ibm_slot_error_detail;
 static int ibm_get_config_addr_info;
 static int ibm_get_config_addr_info2;
-static int ibm_configure_bridge;
 static int ibm_configure_pe;
 
 /*
@@ -81,7 +80,14 @@ static int pseries_eeh_init(void)
        ibm_get_config_addr_info2       = rtas_token("ibm,get-config-addr-info2");
        ibm_get_config_addr_info        = rtas_token("ibm,get-config-addr-info");
        ibm_configure_pe                = rtas_token("ibm,configure-pe");
-       ibm_configure_bridge            = rtas_token("ibm,configure-bridge");
+
+       /*
+        * ibm,configure-pe and ibm,configure-bridge have the same semantics,
+        * however ibm,configure-pe can be faster.  If we can't find
+        * ibm,configure-pe then fall back to using ibm,configure-bridge.
+        */
+       if (ibm_configure_pe == RTAS_UNKNOWN_SERVICE)
+               ibm_configure_pe        = rtas_token("ibm,configure-bridge");
 
        /*
         * Necessary sanity check. We needn't check "get-config-addr-info"
@@ -93,8 +99,7 @@ static int pseries_eeh_init(void)
            (ibm_read_slot_reset_state2 == RTAS_UNKNOWN_SERVICE &&
             ibm_read_slot_reset_state == RTAS_UNKNOWN_SERVICE) ||
            ibm_slot_error_detail == RTAS_UNKNOWN_SERVICE       ||
-           (ibm_configure_pe == RTAS_UNKNOWN_SERVICE           &&
-            ibm_configure_bridge == RTAS_UNKNOWN_SERVICE)) {
+           ibm_configure_pe == RTAS_UNKNOWN_SERVICE) {
                pr_info("EEH functionality not supported\n");
                return -EINVAL;
        }
@@ -615,29 +620,41 @@ static int pseries_eeh_configure_bridge(struct eeh_pe *pe)
 {
        int config_addr;
        int ret;
+       /* Waiting 0.2s maximum before skipping configuration */
+       int max_wait = 200;
 
        /* Figure out the PE address */
        config_addr = pe->config_addr;
        if (pe->addr)
                config_addr = pe->addr;
 
-       /* Use new configure-pe function, if supported */
-       if (ibm_configure_pe != RTAS_UNKNOWN_SERVICE) {
+       while (max_wait > 0) {
                ret = rtas_call(ibm_configure_pe, 3, 1, NULL,
                                config_addr, BUID_HI(pe->phb->buid),
                                BUID_LO(pe->phb->buid));
-       } else if (ibm_configure_bridge != RTAS_UNKNOWN_SERVICE) {
-               ret = rtas_call(ibm_configure_bridge, 3, 1, NULL,
-                               config_addr, BUID_HI(pe->phb->buid),
-                               BUID_LO(pe->phb->buid));
-       } else {
-               return -EFAULT;
-       }
 
-       if (ret)
-               pr_warn("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n",
-                       __func__, pe->phb->global_number, pe->addr, ret);
+               if (!ret)
+                       return ret;
+
+               /*
+                * If RTAS returns a delay value that's above 100ms, cut it
+                * down to 100ms in case firmware made a mistake.  For more
+                * on how these delay values work see rtas_busy_delay_time
+                */
+               if (ret > RTAS_EXTENDED_DELAY_MIN+2 &&
+                   ret <= RTAS_EXTENDED_DELAY_MAX)
+                       ret = RTAS_EXTENDED_DELAY_MIN+2;
+
+               max_wait -= rtas_busy_delay_time(ret);
+
+               if (max_wait < 0)
+                       break;
+
+               rtas_busy_delay(ret);
+       }
 
+       pr_warn("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n",
+               __func__, pe->phb->global_number, pe->addr, ret);
        return ret;
 }
 
index b7dfc13..3e8865b 100644 (file)
@@ -927,7 +927,7 @@ static int query_ddw(struct pci_dev *dev, const u32 *ddw_avail,
        dn = pci_device_to_OF_node(dev);
        pdn = PCI_DN(dn);
        buid = pdn->phb->buid;
-       cfg_addr = (pdn->busno << 8) | pdn->devfn;
+       cfg_addr = ((pdn->busno << 16) | (pdn->devfn << 8));
 
        ret = rtas_call(ddw_avail[0], 3, 5, (u32 *)query,
                  cfg_addr, BUID_HI(buid), BUID_LO(buid));
@@ -956,7 +956,7 @@ static int create_ddw(struct pci_dev *dev, const u32 *ddw_avail,
        dn = pci_device_to_OF_node(dev);
        pdn = PCI_DN(dn);
        buid = pdn->phb->buid;
-       cfg_addr = (pdn->busno << 8) | pdn->devfn;
+       cfg_addr = ((pdn->busno << 16) | (pdn->devfn << 8));
 
        do {
                /* extra outputs are LIOBN and dma-addr (hi, lo) */
index 0ac42cc..d5ec71b 100644 (file)
@@ -1,8 +1,7 @@
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
-CONFIG_FHANDLE=y
 CONFIG_AUDIT=y
-CONFIG_NO_HZ=y
+CONFIG_NO_HZ_IDLE=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_BSD_PROCESS_ACCT_V3=y
@@ -13,19 +12,19 @@ CONFIG_TASK_IO_ACCOUNTING=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_NUMA_BALANCING=y
-CONFIG_CGROUP_FREEZER=y
-CONFIG_CGROUP_PIDS=y
-CONFIG_CGROUP_DEVICE=y
-CONFIG_CPUSETS=y
-CONFIG_CGROUP_CPUACCT=y
 CONFIG_MEMCG=y
 CONFIG_MEMCG_SWAP=y
-CONFIG_MEMCG_KMEM=y
-CONFIG_CGROUP_HUGETLB=y
-CONFIG_CGROUP_PERF=y
+CONFIG_BLK_CGROUP=y
 CONFIG_CFS_BANDWIDTH=y
 CONFIG_RT_GROUP_SCHED=y
-CONFIG_BLK_CGROUP=y
+CONFIG_CGROUP_PIDS=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_HUGETLB=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_PERF=y
+CONFIG_CHECKPOINT_RESTORE=y
 CONFIG_NAMESPACES=y
 CONFIG_USER_NS=y
 CONFIG_SCHED_AUTOGROUP=y
@@ -55,7 +54,6 @@ CONFIG_UNIXWARE_DISKLABEL=y
 CONFIG_CFQ_GROUP_IOSCHED=y
 CONFIG_DEFAULT_DEADLINE=y
 CONFIG_LIVEPATCH=y
-CONFIG_MARCH_Z196=y
 CONFIG_TUNE_ZEC12=y
 CONFIG_NR_CPUS=256
 CONFIG_NUMA=y
@@ -65,6 +63,15 @@ CONFIG_MEMORY_HOTPLUG=y
 CONFIG_MEMORY_HOTREMOVE=y
 CONFIG_KSM=y
 CONFIG_TRANSPARENT_HUGEPAGE=y
+CONFIG_CLEANCACHE=y
+CONFIG_FRONTSWAP=y
+CONFIG_CMA=y
+CONFIG_MEM_SOFT_DIRTY=y
+CONFIG_ZPOOL=m
+CONFIG_ZBUD=m
+CONFIG_ZSMALLOC=m
+CONFIG_ZSMALLOC_STAT=y
+CONFIG_IDLE_PAGE_TRACKING=y
 CONFIG_PCI=y
 CONFIG_PCI_DEBUG=y
 CONFIG_HOTPLUG_PCI=y
@@ -452,6 +459,7 @@ CONFIG_HW_RANDOM_VIRTIO=m
 CONFIG_RAW_DRIVER=m
 CONFIG_HANGCHECK_TIMER=m
 CONFIG_TN3270_FS=y
+# CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 CONFIG_WATCHDOG_NOWAYOUT=y
 CONFIG_SOFT_WATCHDOG=m
@@ -537,6 +545,8 @@ CONFIG_DLM=m
 CONFIG_PRINTK_TIME=y
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_INFO_DWARF4=y
+CONFIG_GDB_SCRIPTS=y
 CONFIG_FRAME_WARN=1024
 CONFIG_READABLE_ASM=y
 CONFIG_UNUSED_SYMBOLS=y
@@ -555,13 +565,17 @@ CONFIG_SLUB_DEBUG_ON=y
 CONFIG_SLUB_STATS=y
 CONFIG_DEBUG_STACK_USAGE=y
 CONFIG_DEBUG_VM=y
+CONFIG_DEBUG_VM_VMACACHE=y
 CONFIG_DEBUG_VM_RB=y
+CONFIG_DEBUG_VM_PGFLAGS=y
 CONFIG_DEBUG_MEMORY_INIT=y
 CONFIG_MEMORY_NOTIFIER_ERROR_INJECT=m
 CONFIG_DEBUG_PER_CPU_MAPS=y
 CONFIG_DEBUG_SHIRQ=y
 CONFIG_DETECT_HUNG_TASK=y
+CONFIG_WQ_WATCHDOG=y
 CONFIG_PANIC_ON_OOPS=y
+CONFIG_DEBUG_TIMEKEEPING=y
 CONFIG_TIMER_STATS=y
 CONFIG_DEBUG_RT_MUTEXES=y
 CONFIG_DEBUG_WW_MUTEX_SLOWPATH=y
@@ -596,6 +610,8 @@ CONFIG_FTRACE_SYSCALLS=y
 CONFIG_STACK_TRACER=y
 CONFIG_BLK_DEV_IO_TRACE=y
 CONFIG_UPROBE_EVENT=y
+CONFIG_FUNCTION_PROFILER=y
+CONFIG_TRACE_ENUM_MAP_FILE=y
 CONFIG_LKDTM=m
 CONFIG_TEST_LIST_SORT=y
 CONFIG_KPROBES_SANITY_TEST=y
@@ -607,7 +623,6 @@ CONFIG_TEST_STRING_HELPERS=y
 CONFIG_TEST_KSTRTOX=y
 CONFIG_DMA_API_DEBUG=y
 CONFIG_TEST_BPF=m
-# CONFIG_STRICT_DEVMEM is not set
 CONFIG_S390_PTDUMP=y
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_SECURITY=y
@@ -651,7 +666,6 @@ CONFIG_CRYPTO_SEED=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_ZLIB=y
 CONFIG_CRYPTO_LZO=m
 CONFIG_CRYPTO_LZ4=m
 CONFIG_CRYPTO_LZ4HC=m
@@ -664,7 +678,7 @@ CONFIG_CRYPTO_SHA512_S390=m
 CONFIG_CRYPTO_DES_S390=m
 CONFIG_CRYPTO_AES_S390=m
 CONFIG_CRYPTO_GHASH_S390=m
-CONFIG_ASYMMETRIC_KEY_TYPE=m
+CONFIG_ASYMMETRIC_KEY_TYPE=y
 CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m
 CONFIG_X509_CERTIFICATE_PARSER=m
 CONFIG_CRC7=m
index a31dcd5..f46a351 100644 (file)
@@ -1,8 +1,7 @@
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
-CONFIG_FHANDLE=y
 CONFIG_AUDIT=y
-CONFIG_NO_HZ=y
+CONFIG_NO_HZ_IDLE=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_BSD_PROCESS_ACCT_V3=y
@@ -13,17 +12,17 @@ CONFIG_TASK_IO_ACCOUNTING=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_NUMA_BALANCING=y
-CONFIG_CGROUP_FREEZER=y
-CONFIG_CGROUP_PIDS=y
-CONFIG_CGROUP_DEVICE=y
-CONFIG_CPUSETS=y
-CONFIG_CGROUP_CPUACCT=y
 CONFIG_MEMCG=y
 CONFIG_MEMCG_SWAP=y
-CONFIG_MEMCG_KMEM=y
+CONFIG_BLK_CGROUP=y
+CONFIG_CGROUP_PIDS=y
+CONFIG_CGROUP_FREEZER=y
 CONFIG_CGROUP_HUGETLB=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_CPUACCT=y
 CONFIG_CGROUP_PERF=y
-CONFIG_BLK_CGROUP=y
+CONFIG_CHECKPOINT_RESTORE=y
 CONFIG_NAMESPACES=y
 CONFIG_USER_NS=y
 CONFIG_SCHED_AUTOGROUP=y
@@ -53,7 +52,6 @@ CONFIG_SOLARIS_X86_PARTITION=y
 CONFIG_UNIXWARE_DISKLABEL=y
 CONFIG_CFQ_GROUP_IOSCHED=y
 CONFIG_DEFAULT_DEADLINE=y
-CONFIG_MARCH_Z196=y
 CONFIG_TUNE_ZEC12=y
 CONFIG_NR_CPUS=256
 CONFIG_NUMA=y
@@ -62,6 +60,14 @@ CONFIG_MEMORY_HOTPLUG=y
 CONFIG_MEMORY_HOTREMOVE=y
 CONFIG_KSM=y
 CONFIG_TRANSPARENT_HUGEPAGE=y
+CONFIG_CLEANCACHE=y
+CONFIG_FRONTSWAP=y
+CONFIG_CMA=y
+CONFIG_ZSWAP=y
+CONFIG_ZBUD=m
+CONFIG_ZSMALLOC=m
+CONFIG_ZSMALLOC_STAT=y
+CONFIG_IDLE_PAGE_TRACKING=y
 CONFIG_PCI=y
 CONFIG_HOTPLUG_PCI=y
 CONFIG_HOTPLUG_PCI_S390=y
@@ -530,6 +536,8 @@ CONFIG_NLS_UTF8=m
 CONFIG_DLM=m
 CONFIG_PRINTK_TIME=y
 CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_INFO_DWARF4=y
+CONFIG_GDB_SCRIPTS=y
 # CONFIG_ENABLE_MUST_CHECK is not set
 CONFIG_FRAME_WARN=1024
 CONFIG_UNUSED_SYMBOLS=y
@@ -547,13 +555,13 @@ CONFIG_LATENCYTOP=y
 CONFIG_DEBUG_STRICT_USER_COPY_CHECKS=y
 CONFIG_BLK_DEV_IO_TRACE=y
 # CONFIG_KPROBE_EVENT is not set
+CONFIG_TRACE_ENUM_MAP_FILE=y
 CONFIG_LKDTM=m
 CONFIG_RBTREE_TEST=m
 CONFIG_INTERVAL_TREE_TEST=m
 CONFIG_PERCPU_TEST=m
 CONFIG_ATOMIC64_SELFTEST=y
 CONFIG_TEST_BPF=m
-# CONFIG_STRICT_DEVMEM is not set
 CONFIG_S390_PTDUMP=y
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_SECURITY=y
@@ -597,8 +605,6 @@ CONFIG_CRYPTO_SEED=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_ZLIB=y
-CONFIG_CRYPTO_LZO=m
 CONFIG_CRYPTO_LZ4=m
 CONFIG_CRYPTO_LZ4HC=m
 CONFIG_CRYPTO_USER_API_HASH=m
@@ -610,7 +616,7 @@ CONFIG_CRYPTO_SHA512_S390=m
 CONFIG_CRYPTO_DES_S390=m
 CONFIG_CRYPTO_AES_S390=m
 CONFIG_CRYPTO_GHASH_S390=m
-CONFIG_ASYMMETRIC_KEY_TYPE=m
+CONFIG_ASYMMETRIC_KEY_TYPE=y
 CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m
 CONFIG_X509_CERTIFICATE_PARSER=m
 CONFIG_CRC7=m
index 7b73bf3..ba0f2a5 100644 (file)
@@ -1,8 +1,7 @@
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
-CONFIG_FHANDLE=y
 CONFIG_AUDIT=y
-CONFIG_NO_HZ=y
+CONFIG_NO_HZ_IDLE=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_BSD_PROCESS_ACCT_V3=y
@@ -14,17 +13,17 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_NUMA_BALANCING=y
 # CONFIG_NUMA_BALANCING_DEFAULT_ENABLED is not set
-CONFIG_CGROUP_FREEZER=y
-CONFIG_CGROUP_PIDS=y
-CONFIG_CGROUP_DEVICE=y
-CONFIG_CPUSETS=y
-CONFIG_CGROUP_CPUACCT=y
 CONFIG_MEMCG=y
 CONFIG_MEMCG_SWAP=y
-CONFIG_MEMCG_KMEM=y
+CONFIG_BLK_CGROUP=y
+CONFIG_CGROUP_PIDS=y
+CONFIG_CGROUP_FREEZER=y
 CONFIG_CGROUP_HUGETLB=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_CPUACCT=y
 CONFIG_CGROUP_PERF=y
-CONFIG_BLK_CGROUP=y
+CONFIG_CHECKPOINT_RESTORE=y
 CONFIG_NAMESPACES=y
 CONFIG_USER_NS=y
 CONFIG_SCHED_AUTOGROUP=y
@@ -53,7 +52,6 @@ CONFIG_UNIXWARE_DISKLABEL=y
 CONFIG_CFQ_GROUP_IOSCHED=y
 CONFIG_DEFAULT_DEADLINE=y
 CONFIG_LIVEPATCH=y
-CONFIG_MARCH_Z196=y
 CONFIG_TUNE_ZEC12=y
 CONFIG_NR_CPUS=512
 CONFIG_NUMA=y
@@ -62,6 +60,14 @@ CONFIG_MEMORY_HOTPLUG=y
 CONFIG_MEMORY_HOTREMOVE=y
 CONFIG_KSM=y
 CONFIG_TRANSPARENT_HUGEPAGE=y
+CONFIG_CLEANCACHE=y
+CONFIG_FRONTSWAP=y
+CONFIG_CMA=y
+CONFIG_ZSWAP=y
+CONFIG_ZBUD=m
+CONFIG_ZSMALLOC=m
+CONFIG_ZSMALLOC_STAT=y
+CONFIG_IDLE_PAGE_TRACKING=y
 CONFIG_PCI=y
 CONFIG_HOTPLUG_PCI=y
 CONFIG_HOTPLUG_PCI_S390=y
@@ -447,6 +453,7 @@ CONFIG_HW_RANDOM_VIRTIO=m
 CONFIG_RAW_DRIVER=m
 CONFIG_HANGCHECK_TIMER=m
 CONFIG_TN3270_FS=y
+# CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 CONFIG_WATCHDOG_NOWAYOUT=y
 CONFIG_SOFT_WATCHDOG=m
@@ -530,6 +537,8 @@ CONFIG_NLS_UTF8=m
 CONFIG_DLM=m
 CONFIG_PRINTK_TIME=y
 CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_INFO_DWARF4=y
+CONFIG_GDB_SCRIPTS=y
 # CONFIG_ENABLE_MUST_CHECK is not set
 CONFIG_FRAME_WARN=1024
 CONFIG_UNUSED_SYMBOLS=y
@@ -546,11 +555,12 @@ CONFIG_FTRACE_SYSCALLS=y
 CONFIG_STACK_TRACER=y
 CONFIG_BLK_DEV_IO_TRACE=y
 CONFIG_UPROBE_EVENT=y
+CONFIG_FUNCTION_PROFILER=y
+CONFIG_TRACE_ENUM_MAP_FILE=y
 CONFIG_LKDTM=m
 CONFIG_PERCPU_TEST=m
 CONFIG_ATOMIC64_SELFTEST=y
 CONFIG_TEST_BPF=m
-# CONFIG_STRICT_DEVMEM is not set
 CONFIG_S390_PTDUMP=y
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_SECURITY=y
@@ -594,8 +604,6 @@ CONFIG_CRYPTO_SEED=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_ZLIB=y
-CONFIG_CRYPTO_LZO=m
 CONFIG_CRYPTO_LZ4=m
 CONFIG_CRYPTO_LZ4HC=m
 CONFIG_CRYPTO_USER_API_HASH=m
@@ -607,7 +615,7 @@ CONFIG_CRYPTO_SHA512_S390=m
 CONFIG_CRYPTO_DES_S390=m
 CONFIG_CRYPTO_AES_S390=m
 CONFIG_CRYPTO_GHASH_S390=m
-CONFIG_ASYMMETRIC_KEY_TYPE=m
+CONFIG_ASYMMETRIC_KEY_TYPE=y
 CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m
 CONFIG_X509_CERTIFICATE_PARSER=m
 CONFIG_CRC7=m
index 1719843..4366a3e 100644 (file)
@@ -1,5 +1,5 @@
 # CONFIG_SWAP is not set
-CONFIG_NO_HZ=y
+CONFIG_NO_HZ_IDLE=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -7,7 +7,6 @@ CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_IBM_PARTITION=y
 CONFIG_DEFAULT_DEADLINE=y
-CONFIG_MARCH_Z196=y
 CONFIG_TUNE_ZEC12=y
 # CONFIG_COMPAT is not set
 CONFIG_NR_CPUS=2
@@ -64,7 +63,6 @@ CONFIG_PANIC_ON_OOPS=y
 # CONFIG_SCHED_DEBUG is not set
 CONFIG_RCU_CPU_STALL_TIMEOUT=60
 # CONFIG_FTRACE is not set
-# CONFIG_STRICT_DEVMEM is not set
 # CONFIG_PFAULT is not set
 # CONFIG_S390_HYPFS_FS is not set
 # CONFIG_VIRTUALIZATION is not set
index e24f2af..3f571ea 100644 (file)
@@ -1,8 +1,8 @@
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
-CONFIG_FHANDLE=y
+CONFIG_USELIB=y
 CONFIG_AUDIT=y
-CONFIG_NO_HZ=y
+CONFIG_NO_HZ_IDLE=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_TASKSTATS=y
 CONFIG_TASK_DELAY_ACCT=y
@@ -11,19 +11,19 @@ CONFIG_TASK_IO_ACCOUNTING=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_CGROUPS=y
-CONFIG_CGROUP_FREEZER=y
-CONFIG_CGROUP_PIDS=y
-CONFIG_CGROUP_DEVICE=y
-CONFIG_CPUSETS=y
-CONFIG_CGROUP_CPUACCT=y
 CONFIG_MEMCG=y
 CONFIG_MEMCG_SWAP=y
-CONFIG_MEMCG_KMEM=y
-CONFIG_CGROUP_HUGETLB=y
-CONFIG_CGROUP_PERF=y
+CONFIG_BLK_CGROUP=y
 CONFIG_CGROUP_SCHED=y
 CONFIG_RT_GROUP_SCHED=y
-CONFIG_BLK_CGROUP=y
+CONFIG_CGROUP_PIDS=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_HUGETLB=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_PERF=y
+CONFIG_CHECKPOINT_RESTORE=y
 CONFIG_NAMESPACES=y
 CONFIG_USER_NS=y
 CONFIG_BLK_DEV_INITRD=y
@@ -44,7 +44,6 @@ CONFIG_PARTITION_ADVANCED=y
 CONFIG_IBM_PARTITION=y
 CONFIG_DEFAULT_DEADLINE=y
 CONFIG_LIVEPATCH=y
-CONFIG_MARCH_Z196=y
 CONFIG_NR_CPUS=256
 CONFIG_NUMA=y
 CONFIG_HZ_100=y
@@ -52,6 +51,14 @@ CONFIG_MEMORY_HOTPLUG=y
 CONFIG_MEMORY_HOTREMOVE=y
 CONFIG_KSM=y
 CONFIG_TRANSPARENT_HUGEPAGE=y
+CONFIG_CLEANCACHE=y
+CONFIG_FRONTSWAP=y
+CONFIG_CMA=y
+CONFIG_ZSWAP=y
+CONFIG_ZBUD=m
+CONFIG_ZSMALLOC=m
+CONFIG_ZSMALLOC_STAT=y
+CONFIG_IDLE_PAGE_TRACKING=y
 CONFIG_CRASH_DUMP=y
 CONFIG_BINFMT_MISC=m
 CONFIG_HIBERNATION=y
@@ -61,7 +68,6 @@ CONFIG_UNIX=y
 CONFIG_NET_KEY=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
-# CONFIG_INET_LRO is not set
 CONFIG_L2TP=m
 CONFIG_L2TP_DEBUGFS=m
 CONFIG_VLAN_8021Q=y
@@ -144,6 +150,9 @@ CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
 CONFIG_HUGETLBFS=y
 # CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_INFO_DWARF4=y
+CONFIG_GDB_SCRIPTS=y
 CONFIG_UNUSED_SYMBOLS=y
 CONFIG_DEBUG_SECTION_MISMATCH=y
 CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y
@@ -158,20 +167,21 @@ CONFIG_LOCK_STAT=y
 CONFIG_DEBUG_LOCKDEP=y
 CONFIG_DEBUG_ATOMIC_SLEEP=y
 CONFIG_DEBUG_LIST=y
-CONFIG_DEBUG_PI_LIST=y
 CONFIG_DEBUG_SG=y
 CONFIG_DEBUG_NOTIFIERS=y
 CONFIG_RCU_CPU_STALL_TIMEOUT=60
 CONFIG_RCU_TRACE=y
 CONFIG_LATENCYTOP=y
 CONFIG_DEBUG_STRICT_USER_COPY_CHECKS=y
-CONFIG_TRACER_SNAPSHOT=y
+CONFIG_SCHED_TRACER=y
+CONFIG_FTRACE_SYSCALLS=y
 CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP=y
 CONFIG_STACK_TRACER=y
 CONFIG_BLK_DEV_IO_TRACE=y
 CONFIG_UPROBE_EVENT=y
+CONFIG_FUNCTION_PROFILER=y
+CONFIG_TRACE_ENUM_MAP_FILE=y
 CONFIG_KPROBES_SANITY_TEST=y
-# CONFIG_STRICT_DEVMEM is not set
 CONFIG_S390_PTDUMP=y
 CONFIG_CRYPTO_CRYPTD=m
 CONFIG_CRYPTO_AUTHENC=m
@@ -212,8 +222,6 @@ CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_ZLIB=m
-CONFIG_CRYPTO_LZO=m
 CONFIG_CRYPTO_LZ4=m
 CONFIG_CRYPTO_LZ4HC=m
 CONFIG_CRYPTO_ANSI_CPRNG=m
index 37b9017..ac82e8e 100644 (file)
@@ -245,6 +245,7 @@ struct kvm_vcpu_stat {
        u32 exit_stop_request;
        u32 exit_validity;
        u32 exit_instruction;
+       u32 exit_pei;
        u32 halt_successful_poll;
        u32 halt_attempted_poll;
        u32 halt_poll_invalid;
index 59215c5..7ec63b1 100644 (file)
@@ -649,6 +649,8 @@ static int cpumf_pmu_commit_txn(struct pmu *pmu)
 
 /* Performance monitoring unit for s390x */
 static struct pmu cpumf_pmu = {
+       .task_ctx_nr  = perf_sw_context,
+       .capabilities = PERF_PMU_CAP_NO_INTERRUPT,
        .pmu_enable   = cpumf_pmu_enable,
        .pmu_disable  = cpumf_pmu_disable,
        .event_init   = cpumf_pmu_event_init,
@@ -708,12 +710,6 @@ static int __init cpumf_pmu_init(void)
                goto out;
        }
 
-       /* The CPU measurement counter facility does not have overflow
-        * interrupts to do sampling.  Sampling must be provided by
-        * external means, for example, by timers.
-        */
-       cpumf_pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
-
        cpumf_pmu.attr_groups = cpumf_cf_event_group();
        rc = perf_pmu_register(&cpumf_pmu, "cpum_cf", PERF_TYPE_RAW);
        if (rc) {
index 2e6b54e..2521571 100644 (file)
@@ -341,6 +341,8 @@ static int handle_mvpg_pei(struct kvm_vcpu *vcpu)
 
 static int handle_partial_execution(struct kvm_vcpu *vcpu)
 {
+       vcpu->stat.exit_pei++;
+
        if (vcpu->arch.sie_block->ipa == 0xb254)        /* MVPG */
                return handle_mvpg_pei(vcpu);
        if (vcpu->arch.sie_block->ipa >> 8 == 0xae)     /* SIGP */
index 6d8ec3a..43f2a2b 100644 (file)
@@ -61,6 +61,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
        { "exit_external_request", VCPU_STAT(exit_external_request) },
        { "exit_external_interrupt", VCPU_STAT(exit_external_interrupt) },
        { "exit_instruction", VCPU_STAT(exit_instruction) },
+       { "exit_pei", VCPU_STAT(exit_pei) },
        { "exit_program_interruption", VCPU_STAT(exit_program_interruption) },
        { "exit_instr_and_program_int", VCPU_STAT(exit_instr_and_program) },
        { "halt_successful_poll", VCPU_STAT(halt_successful_poll) },
@@ -657,7 +658,7 @@ static int kvm_s390_set_processor(struct kvm *kvm, struct kvm_device_attr *attr)
                kvm->arch.model.cpuid = proc->cpuid;
                lowest_ibc = sclp.ibc >> 16 & 0xfff;
                unblocked_ibc = sclp.ibc & 0xfff;
-               if (lowest_ibc) {
+               if (lowest_ibc && proc->ibc) {
                        if (proc->ibc > unblocked_ibc)
                                kvm->arch.model.ibc = unblocked_ibc;
                        else if (proc->ibc < lowest_ibc)
index 7a31440..19288c1 100644 (file)
@@ -250,6 +250,7 @@ static noinline void do_sigsegv(struct pt_regs *regs, int si_code)
 
        report_user_fault(regs, SIGSEGV, 1);
        si.si_signo = SIGSEGV;
+       si.si_errno = 0;
        si.si_code = si_code;
        si.si_addr = (void __user *)(regs->int_parm_long & __FAIL_ADDR_MASK);
        force_sig_info(SIGSEGV, &si, current);
index e8b5962..e2565d2 100644 (file)
@@ -169,7 +169,7 @@ unsigned long *page_table_alloc(struct mm_struct *mm)
                        return table;
        }
        /* Allocate a fresh page */
-       page = alloc_page(GFP_KERNEL|__GFP_REPEAT);
+       page = alloc_page(GFP_KERNEL);
        if (!page)
                return NULL;
        if (!pgtable_page_ctor(page)) {
index 4324b87..9f0ce0e 100644 (file)
@@ -437,7 +437,7 @@ void ptep_zap_unused(struct mm_struct *mm, unsigned long addr,
        pgste = pgste_get_lock(ptep);
        pgstev = pgste_val(pgste);
        pte = *ptep;
-       if (pte_swap(pte) &&
+       if (!reset && pte_swap(pte) &&
            ((pgstev & _PGSTE_GPS_USAGE_MASK) == _PGSTE_GPS_USAGE_UNUSED ||
             (pgstev & _PGSTE_GPS_ZERO))) {
                ptep_zap_swap_entry(mm, pte_to_swp_entry(pte));
index f010c93..fda605d 100644 (file)
@@ -37,7 +37,7 @@ extern u8 sk_load_word[], sk_load_half[], sk_load_byte[];
  *           |               |     |
  *           +---------------+     |
  *           | 8 byte skbp   |     |
- * R15+170 -> +---------------+     |
+ * R15+176 -> +---------------+     |
  *           | 8 byte hlen   |     |
  * R15+168 -> +---------------+     |
  *           | 4 byte align  |     |
@@ -58,7 +58,7 @@ extern u8 sk_load_word[], sk_load_half[], sk_load_byte[];
 #define STK_OFF                (STK_SPACE - STK_160_UNUSED)
 #define STK_OFF_TMP    160     /* Offset of tmp buffer on stack */
 #define STK_OFF_HLEN   168     /* Offset of SKB header length on stack */
-#define STK_OFF_SKBP   170     /* Offset of SKB pointer on stack */
+#define STK_OFF_SKBP   176     /* Offset of SKB pointer on stack */
 
 #define STK_OFF_R6     (160 - 11 * 8)  /* Offset of r6 on stack */
 #define STK_OFF_TCCNT  (160 - 12 * 8)  /* Offset of tail_call_cnt on stack */
index 9133b0e..bee281f 100644 (file)
@@ -45,7 +45,7 @@ struct bpf_jit {
        int labels[1];          /* Labels for local jumps */
 };
 
-#define BPF_SIZE_MAX   0x7ffff /* Max size for program (20 bit signed displ) */
+#define BPF_SIZE_MAX   0xffff  /* Max size for program (16 bit branches) */
 
 #define SEEN_SKB       1       /* skb access */
 #define SEEN_MEM       2       /* use mem[] for temporary storage */
@@ -450,7 +450,7 @@ static void bpf_jit_prologue(struct bpf_jit *jit)
                emit_load_skb_data_hlen(jit);
        if (jit->seen & SEEN_SKB_CHANGE)
                /* stg %b1,ST_OFF_SKBP(%r0,%r15) */
-               EMIT6_DISP_LH(0xe3000000, 0x0024, REG_W1, REG_0, REG_15,
+               EMIT6_DISP_LH(0xe3000000, 0x0024, BPF_REG_1, REG_0, REG_15,
                              STK_OFF_SKBP);
 }
 
index 2e06765..49b012d 100644 (file)
@@ -42,8 +42,7 @@ static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
 {
        pte_t *pte;
 
-       pte = (pte_t *) __get_free_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO,
-                                       PTE_ORDER);
+       pte = (pte_t *) __get_free_pages(GFP_KERNEL|__GFP_ZERO, PTE_ORDER);
 
        return pte;
 }
@@ -53,7 +52,7 @@ static inline struct page *pte_alloc_one(struct mm_struct *mm,
 {
        struct page *pte;
 
-       pte = alloc_pages(GFP_KERNEL | __GFP_REPEAT, PTE_ORDER);
+       pte = alloc_pages(GFP_KERNEL, PTE_ORDER);
        if (!pte)
                return NULL;
        clear_highpage(pte);
index a33673b..f3f42c8 100644 (file)
@@ -34,7 +34,7 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
 static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
                                          unsigned long address)
 {
-       return quicklist_alloc(QUICK_PT, GFP_KERNEL | __GFP_REPEAT, NULL);
+       return quicklist_alloc(QUICK_PT, GFP_KERNEL, NULL);
 }
 
 static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
@@ -43,7 +43,7 @@ static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
        struct page *page;
        void *pg;
 
-       pg = quicklist_alloc(QUICK_PT, GFP_KERNEL | __GFP_REPEAT, NULL);
+       pg = quicklist_alloc(QUICK_PT, GFP_KERNEL, NULL);
        if (!pg)
                return NULL;
        page = virt_to_page(pg);
index 26e03a1..a62bd86 100644 (file)
@@ -1,7 +1,7 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 
-#define PGALLOC_GFP GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO
+#define PGALLOC_GFP GFP_KERNEL | __GFP_ZERO
 
 static struct kmem_cache *pgd_cachep;
 #if PAGETABLE_LEVELS > 2
index 10e9dab..f0700cf 100644 (file)
 
 #define        PTREGS_OFF      (STACK_BIAS + STACKFRAME_SZ)
 
+#define        RTRAP_PSTATE            (PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV|PSTATE_IE)
+#define        RTRAP_PSTATE_IRQOFF     (PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV)
+#define RTRAP_PSTATE_AG_IRQOFF (PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV|PSTATE_AG)
+
 #define __CHEETAH_ID   0x003e0014
 #define __JALAPENO_ID  0x003e0016
 #define __SERRANO_ID   0x003e0022
index 5e31871..3529f13 100644 (file)
@@ -41,8 +41,7 @@ static inline void __pud_populate(pud_t *pud, pmd_t *pmd)
 
 static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
 {
-       return kmem_cache_alloc(pgtable_cache,
-                               GFP_KERNEL|__GFP_REPEAT);
+       return kmem_cache_alloc(pgtable_cache, GFP_KERNEL);
 }
 
 static inline void pud_free(struct mm_struct *mm, pud_t *pud)
@@ -52,8 +51,7 @@ static inline void pud_free(struct mm_struct *mm, pud_t *pud)
 
 static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
 {
-       return kmem_cache_alloc(pgtable_cache,
-                               GFP_KERNEL|__GFP_REPEAT);
+       return kmem_cache_alloc(pgtable_cache, GFP_KERNEL);
 }
 
 static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
index 71b5a67..781b9f1 100644 (file)
@@ -589,8 +589,8 @@ user_rtt_fill_64bit:                                        \
         restored;                                      \
        nop; nop; nop; nop; nop; nop;                   \
        nop; nop; nop; nop; nop;                        \
-       ba,a,pt %xcc, user_rtt_fill_fixup;              \
-       ba,a,pt %xcc, user_rtt_fill_fixup;              \
+       ba,a,pt %xcc, user_rtt_fill_fixup_dax;          \
+       ba,a,pt %xcc, user_rtt_fill_fixup_mna;          \
        ba,a,pt %xcc, user_rtt_fill_fixup;
 
 
@@ -652,8 +652,8 @@ user_rtt_fill_32bit:                                        \
         restored;                                      \
        nop; nop; nop; nop; nop;                        \
        nop; nop; nop;                                  \
-       ba,a,pt %xcc, user_rtt_fill_fixup;              \
-       ba,a,pt %xcc, user_rtt_fill_fixup;              \
+       ba,a,pt %xcc, user_rtt_fill_fixup_dax;          \
+       ba,a,pt %xcc, user_rtt_fill_fixup_mna;          \
        ba,a,pt %xcc, user_rtt_fill_fixup;
 
 
index 7cf9c6e..fdb1332 100644 (file)
@@ -21,6 +21,7 @@ CFLAGS_REMOVE_perf_event.o := -pg
 CFLAGS_REMOVE_pcr.o := -pg
 endif
 
+obj-$(CONFIG_SPARC64)   += urtt_fill.o
 obj-$(CONFIG_SPARC32)   += entry.o wof.o wuf.o
 obj-$(CONFIG_SPARC32)   += etrap_32.o
 obj-$(CONFIG_SPARC32)   += rtrap_32.o
index d08bdaf..216948c 100644 (file)
 #include <asm/visasm.h>
 #include <asm/processor.h>
 
-#define                RTRAP_PSTATE            (PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV|PSTATE_IE)
-#define                RTRAP_PSTATE_IRQOFF     (PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV)
-#define                RTRAP_PSTATE_AG_IRQOFF  (PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV|PSTATE_AG)
-
 #ifdef CONFIG_CONTEXT_TRACKING
 # define SCHEDULE_USER schedule_user
 #else
@@ -242,52 +238,17 @@ rt_continue:      ldx                     [%sp + PTREGS_OFF + PT_V9_G1], %g1
                 wrpr                   %g1, %cwp
                ba,a,pt                 %xcc, user_rtt_fill_64bit
 
-user_rtt_fill_fixup:
-               rdpr    %cwp, %g1
-               add     %g1, 1, %g1
-               wrpr    %g1, 0x0, %cwp
-
-               rdpr    %wstate, %g2
-               sll     %g2, 3, %g2
-               wrpr    %g2, 0x0, %wstate
-
-               /* We know %canrestore and %otherwin are both zero.  */
-
-               sethi   %hi(sparc64_kern_pri_context), %g2
-               ldx     [%g2 + %lo(sparc64_kern_pri_context)], %g2
-               mov     PRIMARY_CONTEXT, %g1
-
-661:           stxa    %g2, [%g1] ASI_DMMU
-               .section .sun4v_1insn_patch, "ax"
-               .word   661b
-               stxa    %g2, [%g1] ASI_MMU
-               .previous
-
-               sethi   %hi(KERNBASE), %g1
-               flush   %g1
+user_rtt_fill_fixup_dax:
+               ba,pt   %xcc, user_rtt_fill_fixup_common
+                mov    1, %g3
 
-               or      %g4, FAULT_CODE_WINFIXUP, %g4
-               stb     %g4, [%g6 + TI_FAULT_CODE]
-               stx     %g5, [%g6 + TI_FAULT_ADDR]
+user_rtt_fill_fixup_mna:
+               ba,pt   %xcc, user_rtt_fill_fixup_common
+                mov    2, %g3
 
-               mov     %g6, %l1
-               wrpr    %g0, 0x0, %tl
-
-661:           nop
-               .section                .sun4v_1insn_patch, "ax"
-               .word                   661b
-               SET_GL(0)
-               .previous
-
-               wrpr    %g0, RTRAP_PSTATE, %pstate
-
-               mov     %l1, %g6
-               ldx     [%g6 + TI_TASK], %g4
-               LOAD_PER_CPU_BASE(%g5, %g6, %g1, %g2, %g3)
-               call    do_sparc64_fault
-                add    %sp, PTREGS_OFF, %o0
-               ba,pt   %xcc, rtrap
-                nop
+user_rtt_fill_fixup:
+               ba,pt   %xcc, user_rtt_fill_fixup_common
+                clr    %g3
 
 user_rtt_pre_restore:
                add                     %g1, 1, %g1
index 3c25241..91cc2f4 100644 (file)
@@ -138,12 +138,24 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
        return 0;
 }
 
+/* Checks if the fp is valid.  We always build signal frames which are
+ * 16-byte aligned, therefore we can always enforce that the restore
+ * frame has that property as well.
+ */
+static bool invalid_frame_pointer(void __user *fp, int fplen)
+{
+       if ((((unsigned long) fp) & 15) ||
+           ((unsigned long)fp) > 0x100000000ULL - fplen)
+               return true;
+       return false;
+}
+
 void do_sigreturn32(struct pt_regs *regs)
 {
        struct signal_frame32 __user *sf;
        compat_uptr_t fpu_save;
        compat_uptr_t rwin_save;
-       unsigned int psr;
+       unsigned int psr, ufp;
        unsigned int pc, npc;
        sigset_t set;
        compat_sigset_t seta;
@@ -158,11 +170,16 @@ void do_sigreturn32(struct pt_regs *regs)
        sf = (struct signal_frame32 __user *) regs->u_regs[UREG_FP];
 
        /* 1. Make sure we are not getting garbage from the user */
-       if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) ||
-           (((unsigned long) sf) & 3))
+       if (invalid_frame_pointer(sf, sizeof(*sf)))
+               goto segv;
+
+       if (get_user(ufp, &sf->info.si_regs.u_regs[UREG_FP]))
+               goto segv;
+
+       if (ufp & 0x7)
                goto segv;
 
-       if (get_user(pc, &sf->info.si_regs.pc) ||
+       if (__get_user(pc, &sf->info.si_regs.pc) ||
            __get_user(npc, &sf->info.si_regs.npc))
                goto segv;
 
@@ -227,7 +244,7 @@ segv:
 asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
 {
        struct rt_signal_frame32 __user *sf;
-       unsigned int psr, pc, npc;
+       unsigned int psr, pc, npc, ufp;
        compat_uptr_t fpu_save;
        compat_uptr_t rwin_save;
        sigset_t set;
@@ -242,11 +259,16 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
        sf = (struct rt_signal_frame32 __user *) regs->u_regs[UREG_FP];
 
        /* 1. Make sure we are not getting garbage from the user */
-       if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) ||
-           (((unsigned long) sf) & 3))
+       if (invalid_frame_pointer(sf, sizeof(*sf)))
                goto segv;
 
-       if (get_user(pc, &sf->regs.pc) || 
+       if (get_user(ufp, &sf->regs.u_regs[UREG_FP]))
+               goto segv;
+
+       if (ufp & 0x7)
+               goto segv;
+
+       if (__get_user(pc, &sf->regs.pc) || 
            __get_user(npc, &sf->regs.npc))
                goto segv;
 
@@ -307,14 +329,6 @@ segv:
        force_sig(SIGSEGV, current);
 }
 
-/* Checks if the fp is valid */
-static int invalid_frame_pointer(void __user *fp, int fplen)
-{
-       if ((((unsigned long) fp) & 7) || ((unsigned long)fp) > 0x100000000ULL - fplen)
-               return 1;
-       return 0;
-}
-
 static void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize)
 {
        unsigned long sp;
index 52aa5e4..c3c12ef 100644 (file)
@@ -60,10 +60,22 @@ struct rt_signal_frame {
 #define SF_ALIGNEDSZ  (((sizeof(struct signal_frame) + 7) & (~7)))
 #define RT_ALIGNEDSZ  (((sizeof(struct rt_signal_frame) + 7) & (~7)))
 
+/* Checks if the fp is valid.  We always build signal frames which are
+ * 16-byte aligned, therefore we can always enforce that the restore
+ * frame has that property as well.
+ */
+static inline bool invalid_frame_pointer(void __user *fp, int fplen)
+{
+       if ((((unsigned long) fp) & 15) || !__access_ok((unsigned long)fp, fplen))
+               return true;
+
+       return false;
+}
+
 asmlinkage void do_sigreturn(struct pt_regs *regs)
 {
+       unsigned long up_psr, pc, npc, ufp;
        struct signal_frame __user *sf;
-       unsigned long up_psr, pc, npc;
        sigset_t set;
        __siginfo_fpu_t __user *fpu_save;
        __siginfo_rwin_t __user *rwin_save;
@@ -77,10 +89,13 @@ asmlinkage void do_sigreturn(struct pt_regs *regs)
        sf = (struct signal_frame __user *) regs->u_regs[UREG_FP];
 
        /* 1. Make sure we are not getting garbage from the user */
-       if (!access_ok(VERIFY_READ, sf, sizeof(*sf)))
+       if (!invalid_frame_pointer(sf, sizeof(*sf)))
+               goto segv_and_exit;
+
+       if (get_user(ufp, &sf->info.si_regs.u_regs[UREG_FP]))
                goto segv_and_exit;
 
-       if (((unsigned long) sf) & 3)
+       if (ufp & 0x7)
                goto segv_and_exit;
 
        err = __get_user(pc,  &sf->info.si_regs.pc);
@@ -127,7 +142,7 @@ segv_and_exit:
 asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
 {
        struct rt_signal_frame __user *sf;
-       unsigned int psr, pc, npc;
+       unsigned int psr, pc, npc, ufp;
        __siginfo_fpu_t __user *fpu_save;
        __siginfo_rwin_t __user *rwin_save;
        sigset_t set;
@@ -135,8 +150,13 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
 
        synchronize_user_stack();
        sf = (struct rt_signal_frame __user *) regs->u_regs[UREG_FP];
-       if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) ||
-           (((unsigned long) sf) & 0x03))
+       if (!invalid_frame_pointer(sf, sizeof(*sf)))
+               goto segv;
+
+       if (get_user(ufp, &sf->regs.u_regs[UREG_FP]))
+               goto segv;
+
+       if (ufp & 0x7)
                goto segv;
 
        err = __get_user(pc, &sf->regs.pc);
@@ -178,15 +198,6 @@ segv:
        force_sig(SIGSEGV, current);
 }
 
-/* Checks if the fp is valid */
-static inline int invalid_frame_pointer(void __user *fp, int fplen)
-{
-       if ((((unsigned long) fp) & 7) || !__access_ok((unsigned long)fp, fplen))
-               return 1;
-
-       return 0;
-}
-
 static inline void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize)
 {
        unsigned long sp = regs->u_regs[UREG_FP];
index 39aaec1..5ee930c 100644 (file)
@@ -234,6 +234,17 @@ do_sigsegv:
        goto out;
 }
 
+/* Checks if the fp is valid.  We always build rt signal frames which
+ * are 16-byte aligned, therefore we can always enforce that the
+ * restore frame has that property as well.
+ */
+static bool invalid_frame_pointer(void __user *fp)
+{
+       if (((unsigned long) fp) & 15)
+               return true;
+       return false;
+}
+
 struct rt_signal_frame {
        struct sparc_stackf     ss;
        siginfo_t               info;
@@ -246,8 +257,8 @@ struct rt_signal_frame {
 
 void do_rt_sigreturn(struct pt_regs *regs)
 {
+       unsigned long tpc, tnpc, tstate, ufp;
        struct rt_signal_frame __user *sf;
-       unsigned long tpc, tnpc, tstate;
        __siginfo_fpu_t __user *fpu_save;
        __siginfo_rwin_t __user *rwin_save;
        sigset_t set;
@@ -261,10 +272,16 @@ void do_rt_sigreturn(struct pt_regs *regs)
                (regs->u_regs [UREG_FP] + STACK_BIAS);
 
        /* 1. Make sure we are not getting garbage from the user */
-       if (((unsigned long) sf) & 3)
+       if (invalid_frame_pointer(sf))
+               goto segv;
+
+       if (get_user(ufp, &sf->regs.u_regs[UREG_FP]))
                goto segv;
 
-       err = get_user(tpc, &sf->regs.tpc);
+       if ((ufp + STACK_BIAS) & 0x7)
+               goto segv;
+
+       err = __get_user(tpc, &sf->regs.tpc);
        err |= __get_user(tnpc, &sf->regs.tnpc);
        if (test_thread_flag(TIF_32BIT)) {
                tpc &= 0xffffffff;
@@ -308,14 +325,6 @@ segv:
        force_sig(SIGSEGV, current);
 }
 
-/* Checks if the fp is valid */
-static int invalid_frame_pointer(void __user *fp)
-{
-       if (((unsigned long) fp) & 15)
-               return 1;
-       return 0;
-}
-
 static inline void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize)
 {
        unsigned long sp = regs->u_regs[UREG_FP] + STACK_BIAS;
index 0f6eebe..e5fe8ce 100644 (file)
@@ -48,6 +48,10 @@ int save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
 int restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
 {
        int err;
+
+       if (((unsigned long) fpu) & 3)
+               return -EFAULT;
+
 #ifdef CONFIG_SMP
        if (test_tsk_thread_flag(current, TIF_USEDFPU))
                regs->psr &= ~PSR_EF;
@@ -97,7 +101,10 @@ int restore_rwin_state(__siginfo_rwin_t __user *rp)
        struct thread_info *t = current_thread_info();
        int i, wsaved, err;
 
-       __get_user(wsaved, &rp->wsaved);
+       if (((unsigned long) rp) & 3)
+               return -EFAULT;
+
+       get_user(wsaved, &rp->wsaved);
        if (wsaved > NSWINS)
                return -EFAULT;
 
index 387834a..36aadcb 100644 (file)
@@ -37,7 +37,10 @@ int restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
        unsigned long fprs;
        int err;
 
-       err = __get_user(fprs, &fpu->si_fprs);
+       if (((unsigned long) fpu) & 7)
+               return -EFAULT;
+
+       err = get_user(fprs, &fpu->si_fprs);
        fprs_write(0);
        regs->tstate &= ~TSTATE_PEF;
        if (fprs & FPRS_DL)
@@ -72,7 +75,10 @@ int restore_rwin_state(__siginfo_rwin_t __user *rp)
        struct thread_info *t = current_thread_info();
        int i, wsaved, err;
 
-       __get_user(wsaved, &rp->wsaved);
+       if (((unsigned long) rp) & 7)
+               return -EFAULT;
+
+       get_user(wsaved, &rp->wsaved);
        if (wsaved > NSWINS)
                return -EFAULT;
 
diff --git a/arch/sparc/kernel/urtt_fill.S b/arch/sparc/kernel/urtt_fill.S
new file mode 100644 (file)
index 0000000..5604a2b
--- /dev/null
@@ -0,0 +1,98 @@
+#include <asm/thread_info.h>
+#include <asm/trap_block.h>
+#include <asm/spitfire.h>
+#include <asm/ptrace.h>
+#include <asm/head.h>
+
+               .text
+               .align  8
+               .globl  user_rtt_fill_fixup_common
+user_rtt_fill_fixup_common:
+               rdpr    %cwp, %g1
+               add     %g1, 1, %g1
+               wrpr    %g1, 0x0, %cwp
+
+               rdpr    %wstate, %g2
+               sll     %g2, 3, %g2
+               wrpr    %g2, 0x0, %wstate
+
+               /* We know %canrestore and %otherwin are both zero.  */
+
+               sethi   %hi(sparc64_kern_pri_context), %g2
+               ldx     [%g2 + %lo(sparc64_kern_pri_context)], %g2
+               mov     PRIMARY_CONTEXT, %g1
+
+661:           stxa    %g2, [%g1] ASI_DMMU
+               .section .sun4v_1insn_patch, "ax"
+               .word   661b
+               stxa    %g2, [%g1] ASI_MMU
+               .previous
+
+               sethi   %hi(KERNBASE), %g1
+               flush   %g1
+
+               mov     %g4, %l4
+               mov     %g5, %l5
+               brnz,pn %g3, 1f
+                mov    %g3, %l3
+
+               or      %g4, FAULT_CODE_WINFIXUP, %g4
+               stb     %g4, [%g6 + TI_FAULT_CODE]
+               stx     %g5, [%g6 + TI_FAULT_ADDR]
+1:
+               mov     %g6, %l1
+               wrpr    %g0, 0x0, %tl
+
+661:           nop
+               .section                .sun4v_1insn_patch, "ax"
+               .word                   661b
+               SET_GL(0)
+               .previous
+
+               wrpr    %g0, RTRAP_PSTATE, %pstate
+
+               mov     %l1, %g6
+               ldx     [%g6 + TI_TASK], %g4
+               LOAD_PER_CPU_BASE(%g5, %g6, %g1, %g2, %g3)
+
+               brnz,pn %l3, 1f
+                nop
+
+               call    do_sparc64_fault
+                add    %sp, PTREGS_OFF, %o0
+               ba,pt   %xcc, rtrap
+                nop
+
+1:             cmp     %g3, 2
+               bne,pn  %xcc, 2f
+                nop
+
+               sethi   %hi(tlb_type), %g1
+               lduw    [%g1 + %lo(tlb_type)], %g1
+               cmp     %g1, 3
+               bne,pt  %icc, 1f
+                add    %sp, PTREGS_OFF, %o0
+               mov     %l4, %o2
+               call    sun4v_do_mna
+                mov    %l5, %o1
+               ba,a,pt %xcc, rtrap
+1:             mov     %l4, %o1
+               mov     %l5, %o2
+               call    mem_address_unaligned
+                nop
+               ba,a,pt %xcc, rtrap
+
+2:             sethi   %hi(tlb_type), %g1
+               mov     %l4, %o1
+               lduw    [%g1 + %lo(tlb_type)], %g1
+               mov     %l5, %o2
+               cmp     %g1, 3
+               bne,pt  %icc, 1f
+                add    %sp, PTREGS_OFF, %o0
+               call    sun4v_data_access_exception
+                nop
+               ba,a,pt %xcc, rtrap
+
+1:             call    spitfire_data_access_exception
+                nop
+               ba,a,pt %xcc, rtrap
index 652683c..aec508e 100644 (file)
@@ -2704,8 +2704,7 @@ void __flush_tlb_all(void)
 pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
                            unsigned long address)
 {
-       struct page *page = alloc_page(GFP_KERNEL | __GFP_NOTRACK |
-                                      __GFP_REPEAT | __GFP_ZERO);
+       struct page *page = alloc_page(GFP_KERNEL | __GFP_NOTRACK | __GFP_ZERO);
        pte_t *pte = NULL;
 
        if (page)
@@ -2717,8 +2716,7 @@ pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
 pgtable_t pte_alloc_one(struct mm_struct *mm,
                        unsigned long address)
 {
-       struct page *page = alloc_page(GFP_KERNEL | __GFP_NOTRACK |
-                                      __GFP_REPEAT | __GFP_ZERO);
+       struct page *page = alloc_page(GFP_KERNEL | __GFP_NOTRACK | __GFP_ZERO);
        if (!page)
                return NULL;
        if (!pgtable_page_ctor(page)) {
@@ -2824,9 +2822,10 @@ void hugetlb_setup(struct pt_regs *regs)
         * the Data-TLB for huge pages.
         */
        if (tlb_type == cheetah_plus) {
+               bool need_context_reload = false;
                unsigned long ctx;
 
-               spin_lock(&ctx_alloc_lock);
+               spin_lock_irq(&ctx_alloc_lock);
                ctx = mm->context.sparc64_ctx_val;
                ctx &= ~CTX_PGSZ_MASK;
                ctx |= CTX_PGSZ_BASE << CTX_PGSZ0_SHIFT;
@@ -2845,9 +2844,12 @@ void hugetlb_setup(struct pt_regs *regs)
                         * also executing in this address space.
                         */
                        mm->context.sparc64_ctx_val = ctx;
-                       on_each_cpu(context_reload, mm, 0);
+                       need_context_reload = true;
                }
-               spin_unlock(&ctx_alloc_lock);
+               spin_unlock_irq(&ctx_alloc_lock);
+
+               if (need_context_reload)
+                       on_each_cpu(context_reload, mm, 0);
        }
 }
 #endif
index 4b7cef9..c1467ac 100644 (file)
@@ -78,7 +78,7 @@ struct thread_info {
 
 #ifndef __ASSEMBLY__
 
-void arch_release_thread_info(struct thread_info *info);
+void arch_release_thread_stack(unsigned long *stack);
 
 /* How to get the thread information struct from C. */
 register unsigned long stack_pointer __asm__("sp");
index 6b705cc..a465d83 100644 (file)
@@ -73,8 +73,9 @@ void arch_cpu_idle(void)
 /*
  * Release a thread_info structure
  */
-void arch_release_thread_info(struct thread_info *info)
+void arch_release_thread_stack(unsigned long *stack)
 {
+       struct thread_info *info = (void *)stack;
        struct single_step_state *step_state = info->step_state;
 
        if (step_state) {
index 7bf2491..c4d5bf8 100644 (file)
@@ -231,7 +231,7 @@ void pgd_free(struct mm_struct *mm, pgd_t *pgd)
 struct page *pgtable_alloc_one(struct mm_struct *mm, unsigned long address,
                               int order)
 {
-       gfp_t flags = GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO;
+       gfp_t flags = GFP_KERNEL|__GFP_ZERO;
        struct page *p;
        int i;
 
index b2a2dff..e7437ec 100644 (file)
@@ -204,7 +204,7 @@ pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
 {
        pte_t *pte;
 
-       pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
+       pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_ZERO);
        return pte;
 }
 
@@ -212,7 +212,7 @@ pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
 {
        struct page *pte;
 
-       pte = alloc_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
+       pte = alloc_page(GFP_KERNEL|__GFP_ZERO);
        if (!pte)
                return NULL;
        if (!pgtable_page_ctor(pte)) {
index 2e02d13..2677579 100644 (file)
@@ -28,7 +28,7 @@ extern void free_pgd_slow(struct mm_struct *mm, pgd_t *pgd);
 #define pgd_alloc(mm)                  get_pgd_slow(mm)
 #define pgd_free(mm, pgd)              free_pgd_slow(mm, pgd)
 
-#define PGALLOC_GFP    (GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO)
+#define PGALLOC_GFP    (GFP_KERNEL | __GFP_NOTRACK | __GFP_ZERO)
 
 /*
  * Allocate one PTE table.
index 0a7b885..d9a94da 100644 (file)
@@ -2439,6 +2439,15 @@ config PCI_CNB20LE_QUIRK
 
 source "drivers/pci/Kconfig"
 
+config ISA_BUS
+       bool "ISA-style bus support on modern systems" if EXPERT
+       select ISA_BUS_API
+       help
+         Enables ISA-style drivers on modern systems. This is necessary to
+         support PC/104 devices on X86_64 platforms.
+
+         If unsure, say N.
+
 # x86_64 have no ISA slots, but can have ISA-style DMA.
 config ISA_DMA_API
        bool "ISA-style DMA support" if (X86_64 && EXPERT)
index 700a9c6..be8e688 100644 (file)
@@ -162,6 +162,9 @@ isoimage: $(obj)/bzImage
        for i in lib lib64 share end ; do \
                if [ -f /usr/$$i/syslinux/isolinux.bin ] ; then \
                        cp /usr/$$i/syslinux/isolinux.bin $(obj)/isoimage ; \
+                       if [ -f /usr/$$i/syslinux/ldlinux.c32 ]; then \
+                               cp /usr/$$i/syslinux/ldlinux.c32 $(obj)/isoimage ; \
+                       fi ; \
                        break ; \
                fi ; \
                if [ $$i = end ] ; then exit 1 ; fi ; \
index 99c4bab..e30eef4 100644 (file)
@@ -714,7 +714,7 @@ static void cleanup_rapl_pmus(void)
        int i;
 
        for (i = 0; i < rapl_pmus->maxpkg; i++)
-               kfree(rapl_pmus->pmus + i);
+               kfree(rapl_pmus->pmus[i]);
        kfree(rapl_pmus);
 }
 
index b262586..874e8bd 100644 (file)
@@ -2868,27 +2868,10 @@ static struct intel_uncore_type bdx_uncore_cbox = {
        .format_group           = &hswep_uncore_cbox_format_group,
 };
 
-static struct intel_uncore_type bdx_uncore_sbox = {
-       .name                   = "sbox",
-       .num_counters           = 4,
-       .num_boxes              = 4,
-       .perf_ctr_bits          = 48,
-       .event_ctl              = HSWEP_S0_MSR_PMON_CTL0,
-       .perf_ctr               = HSWEP_S0_MSR_PMON_CTR0,
-       .event_mask             = HSWEP_S_MSR_PMON_RAW_EVENT_MASK,
-       .box_ctl                = HSWEP_S0_MSR_PMON_BOX_CTL,
-       .msr_offset             = HSWEP_SBOX_MSR_OFFSET,
-       .ops                    = &hswep_uncore_sbox_msr_ops,
-       .format_group           = &hswep_uncore_sbox_format_group,
-};
-
-#define BDX_MSR_UNCORE_SBOX    3
-
 static struct intel_uncore_type *bdx_msr_uncores[] = {
        &bdx_uncore_ubox,
        &bdx_uncore_cbox,
        &hswep_uncore_pcu,
-       &bdx_uncore_sbox,
        NULL,
 };
 
@@ -2897,10 +2880,6 @@ void bdx_uncore_cpu_init(void)
        if (bdx_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores)
                bdx_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores;
        uncore_msr_uncores = bdx_msr_uncores;
-
-       /* BDX-DE doesn't have SBOX */
-       if (boot_cpu_data.x86_model == 86)
-               uncore_msr_uncores[BDX_MSR_UNCORE_SBOX] = NULL;
 }
 
 static struct intel_uncore_type bdx_uncore_ha = {
diff --git a/arch/x86/include/asm/intel-family.h b/arch/x86/include/asm/intel-family.h
new file mode 100644 (file)
index 0000000..6999f7d
--- /dev/null
@@ -0,0 +1,68 @@
+#ifndef _ASM_X86_INTEL_FAMILY_H
+#define _ASM_X86_INTEL_FAMILY_H
+
+/*
+ * "Big Core" Processors (Branded as Core, Xeon, etc...)
+ *
+ * The "_X" parts are generally the EP and EX Xeons, or the
+ * "Extreme" ones, like Broadwell-E.
+ *
+ * Things ending in "2" are usually because we have no better
+ * name for them.  There's no processor called "WESTMERE2".
+ */
+
+#define INTEL_FAM6_CORE_YONAH          0x0E
+#define INTEL_FAM6_CORE2_MEROM         0x0F
+#define INTEL_FAM6_CORE2_MEROM_L       0x16
+#define INTEL_FAM6_CORE2_PENRYN                0x17
+#define INTEL_FAM6_CORE2_DUNNINGTON    0x1D
+
+#define INTEL_FAM6_NEHALEM             0x1E
+#define INTEL_FAM6_NEHALEM_EP          0x1A
+#define INTEL_FAM6_NEHALEM_EX          0x2E
+#define INTEL_FAM6_WESTMERE            0x25
+#define INTEL_FAM6_WESTMERE2           0x1F
+#define INTEL_FAM6_WESTMERE_EP         0x2C
+#define INTEL_FAM6_WESTMERE_EX         0x2F
+
+#define INTEL_FAM6_SANDYBRIDGE         0x2A
+#define INTEL_FAM6_SANDYBRIDGE_X       0x2D
+#define INTEL_FAM6_IVYBRIDGE           0x3A
+#define INTEL_FAM6_IVYBRIDGE_X         0x3E
+
+#define INTEL_FAM6_HASWELL_CORE                0x3C
+#define INTEL_FAM6_HASWELL_X           0x3F
+#define INTEL_FAM6_HASWELL_ULT         0x45
+#define INTEL_FAM6_HASWELL_GT3E                0x46
+
+#define INTEL_FAM6_BROADWELL_CORE      0x3D
+#define INTEL_FAM6_BROADWELL_XEON_D    0x56
+#define INTEL_FAM6_BROADWELL_GT3E      0x47
+#define INTEL_FAM6_BROADWELL_X         0x4F
+
+#define INTEL_FAM6_SKYLAKE_MOBILE      0x4E
+#define INTEL_FAM6_SKYLAKE_DESKTOP     0x5E
+#define INTEL_FAM6_SKYLAKE_X           0x55
+#define INTEL_FAM6_KABYLAKE_MOBILE     0x8E
+#define INTEL_FAM6_KABYLAKE_DESKTOP    0x9E
+
+/* "Small Core" Processors (Atom) */
+
+#define INTEL_FAM6_ATOM_PINEVIEW       0x1C
+#define INTEL_FAM6_ATOM_LINCROFT       0x26
+#define INTEL_FAM6_ATOM_PENWELL                0x27
+#define INTEL_FAM6_ATOM_CLOVERVIEW     0x35
+#define INTEL_FAM6_ATOM_CEDARVIEW      0x36
+#define INTEL_FAM6_ATOM_SILVERMONT1    0x37 /* BayTrail/BYT / Valleyview */
+#define INTEL_FAM6_ATOM_SILVERMONT2    0x4D /* Avaton/Rangely */
+#define INTEL_FAM6_ATOM_AIRMONT                0x4C /* CherryTrail / Braswell */
+#define INTEL_FAM6_ATOM_MERRIFIELD1    0x4A /* Tangier */
+#define INTEL_FAM6_ATOM_MERRIFIELD2    0x5A /* Annidale */
+#define INTEL_FAM6_ATOM_GOLDMONT       0x5C
+#define INTEL_FAM6_ATOM_DENVERTON      0x5F /* Goldmont Microserver */
+
+/* Xeon Phi */
+
+#define INTEL_FAM6_XEON_PHI_KNL                0x57 /* Knights Landing */
+
+#endif /* _ASM_X86_INTEL_FAMILY_H */
index 4421b5d..d1d1e50 100644 (file)
@@ -38,12 +38,11 @@ typedef u8 kprobe_opcode_t;
 #define RELATIVECALL_OPCODE 0xe8
 #define RELATIVE_ADDR_SIZE 4
 #define MAX_STACK_SIZE 64
-#define MIN_STACK_SIZE(ADDR)                                          \
-       (((MAX_STACK_SIZE) < (((unsigned long)current_thread_info()) + \
-                             THREAD_SIZE - (unsigned long)(ADDR)))    \
-        ? (MAX_STACK_SIZE)                                            \
-        : (((unsigned long)current_thread_info()) +                   \
-           THREAD_SIZE - (unsigned long)(ADDR)))
+#define CUR_STACK_SIZE(ADDR) \
+       (current_top_of_stack() - (unsigned long)(ADDR))
+#define MIN_STACK_SIZE(ADDR)                           \
+       (MAX_STACK_SIZE < CUR_STACK_SIZE(ADDR) ?        \
+        MAX_STACK_SIZE : CUR_STACK_SIZE(ADDR))
 
 #define flush_insn_slot(p)     do { } while (0)
 
index e0fbe7e..69e6286 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/irqbypass.h>
 #include <linux/hyperv.h>
 
+#include <asm/apic.h>
 #include <asm/pvclock-abi.h>
 #include <asm/desc.h>
 #include <asm/mtrr.h>
@@ -1368,4 +1369,14 @@ static inline void kvm_arch_vcpu_unblocking(struct kvm_vcpu *vcpu)
 
 static inline void kvm_arch_vcpu_block_finish(struct kvm_vcpu *vcpu) {}
 
+static inline int kvm_cpu_get_apicid(int mps_cpu)
+{
+#ifdef CONFIG_X86_LOCAL_APIC
+       return __default_cpu_present_to_apicid(mps_cpu);
+#else
+       WARN_ON_ONCE(1);
+       return BAD_APICID;
+#endif
+}
+
 #endif /* _ASM_X86_KVM_HOST_H */
index 7dc1d8f..b5fee97 100644 (file)
@@ -122,7 +122,7 @@ notrace static inline void native_write_msr(unsigned int msr,
                     "2:\n"
                     _ASM_EXTABLE_HANDLE(1b, 2b, ex_handler_wrmsr_unsafe)
                     : : "c" (msr), "a"(low), "d" (high) : "memory");
-       if (msr_tracepoint_active(__tracepoint_read_msr))
+       if (msr_tracepoint_active(__tracepoint_write_msr))
                do_trace_write_msr(msr, ((u64)high << 32 | low), 0);
 }
 
@@ -141,7 +141,7 @@ notrace static inline int native_write_msr_safe(unsigned int msr,
                     : "c" (msr), "0" (low), "d" (high),
                       [fault] "i" (-EIO)
                     : "memory");
-       if (msr_tracepoint_active(__tracepoint_read_msr))
+       if (msr_tracepoint_active(__tracepoint_write_msr))
                do_trace_write_msr(msr, ((u64)high << 32 | low), err);
        return err;
 }
index bf7f8b5..574c23c 100644 (file)
@@ -81,7 +81,7 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
 static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
 {
        struct page *page;
-       page = alloc_pages(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO, 0);
+       page = alloc_pages(GFP_KERNEL |  __GFP_ZERO, 0);
        if (!page)
                return NULL;
        if (!pgtable_pmd_page_ctor(page)) {
@@ -125,7 +125,7 @@ static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)
 
 static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
 {
-       return (pud_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
+       return (pud_t *)get_zeroed_page(GFP_KERNEL);
 }
 
 static inline void pud_free(struct mm_struct *mm, pud_t *pud)
index 7c247e7..0944218 100644 (file)
@@ -14,7 +14,7 @@ extern int kstack_depth_to_print;
 struct thread_info;
 struct stacktrace_ops;
 
-typedef unsigned long (*walk_stack_t)(struct thread_info *tinfo,
+typedef unsigned long (*walk_stack_t)(struct task_struct *task,
                                      unsigned long *stack,
                                      unsigned long bp,
                                      const struct stacktrace_ops *ops,
@@ -23,13 +23,13 @@ typedef unsigned long (*walk_stack_t)(struct thread_info *tinfo,
                                      int *graph);
 
 extern unsigned long
-print_context_stack(struct thread_info *tinfo,
+print_context_stack(struct task_struct *task,
                    unsigned long *stack, unsigned long bp,
                    const struct stacktrace_ops *ops, void *data,
                    unsigned long *end, int *graph);
 
 extern unsigned long
-print_context_stack_bp(struct thread_info *tinfo,
+print_context_stack_bp(struct task_struct *task,
                       unsigned long *stack, unsigned long bp,
                       const struct stacktrace_ops *ops, void *data,
                       unsigned long *end, int *graph);
index 84e33ff..446702e 100644 (file)
@@ -2588,8 +2588,8 @@ static struct resource * __init ioapic_setup_resources(void)
                res[num].flags = IORESOURCE_MEM | IORESOURCE_BUSY;
                snprintf(mem, IOAPIC_RESOURCE_NAME_SIZE, "IOAPIC %u", i);
                mem += IOAPIC_RESOURCE_NAME_SIZE;
+               ioapics[i].iomem_res = &res[num];
                num++;
-               ioapics[i].iomem_res = res;
        }
 
        ioapic_resources = res;
index c343a54..f5c69d8 100644 (file)
@@ -674,14 +674,14 @@ static void init_amd_bd(struct cpuinfo_x86 *c)
        u64 value;
 
        /* re-enable TopologyExtensions if switched off by BIOS */
-       if ((c->x86_model >= 0x10) && (c->x86_model <= 0x1f) &&
+       if ((c->x86_model >= 0x10) && (c->x86_model <= 0x6f) &&
            !cpu_has(c, X86_FEATURE_TOPOEXT)) {
 
                if (msr_set_bit(0xc0011005, 54) > 0) {
                        rdmsrl(0xc0011005, value);
                        if (value & BIT_64(54)) {
                                set_cpu_cap(c, X86_FEATURE_TOPOEXT);
-                               pr_info(FW_INFO "CPU: Re-enabling disabled Topology Extensions Support.\n");
+                               pr_info_once(FW_INFO "CPU: Re-enabling disabled Topology Extensions Support.\n");
                        }
                }
        }
index 2bb25c3..ef8017c 100644 (file)
@@ -42,16 +42,14 @@ void printk_address(unsigned long address)
 static void
 print_ftrace_graph_addr(unsigned long addr, void *data,
                        const struct stacktrace_ops *ops,
-                       struct thread_info *tinfo, int *graph)
+                       struct task_struct *task, int *graph)
 {
-       struct task_struct *task;
        unsigned long ret_addr;
        int index;
 
        if (addr != (unsigned long)return_to_handler)
                return;
 
-       task = tinfo->task;
        index = task->curr_ret_stack;
 
        if (!task->ret_stack || index < *graph)
@@ -68,7 +66,7 @@ print_ftrace_graph_addr(unsigned long addr, void *data,
 static inline void
 print_ftrace_graph_addr(unsigned long addr, void *data,
                        const struct stacktrace_ops *ops,
-                       struct thread_info *tinfo, int *graph)
+                       struct task_struct *task, int *graph)
 { }
 #endif
 
@@ -79,10 +77,10 @@ print_ftrace_graph_addr(unsigned long addr, void *data,
  * severe exception (double fault, nmi, stack fault, debug, mce) hardware stack
  */
 
-static inline int valid_stack_ptr(struct thread_info *tinfo,
+static inline int valid_stack_ptr(struct task_struct *task,
                        void *p, unsigned int size, void *end)
 {
-       void *t = tinfo;
+       void *t = task_stack_page(task);
        if (end) {
                if (p < end && p >= (end-THREAD_SIZE))
                        return 1;
@@ -93,14 +91,14 @@ static inline int valid_stack_ptr(struct thread_info *tinfo,
 }
 
 unsigned long
-print_context_stack(struct thread_info *tinfo,
+print_context_stack(struct task_struct *task,
                unsigned long *stack, unsigned long bp,
                const struct stacktrace_ops *ops, void *data,
                unsigned long *end, int *graph)
 {
        struct stack_frame *frame = (struct stack_frame *)bp;
 
-       while (valid_stack_ptr(tinfo, stack, sizeof(*stack), end)) {
+       while (valid_stack_ptr(task, stack, sizeof(*stack), end)) {
                unsigned long addr;
 
                addr = *stack;
@@ -112,7 +110,7 @@ print_context_stack(struct thread_info *tinfo,
                        } else {
                                ops->address(data, addr, 0);
                        }
-                       print_ftrace_graph_addr(addr, data, ops, tinfo, graph);
+                       print_ftrace_graph_addr(addr, data, ops, task, graph);
                }
                stack++;
        }
@@ -121,7 +119,7 @@ print_context_stack(struct thread_info *tinfo,
 EXPORT_SYMBOL_GPL(print_context_stack);
 
 unsigned long
-print_context_stack_bp(struct thread_info *tinfo,
+print_context_stack_bp(struct task_struct *task,
                       unsigned long *stack, unsigned long bp,
                       const struct stacktrace_ops *ops, void *data,
                       unsigned long *end, int *graph)
@@ -129,7 +127,7 @@ print_context_stack_bp(struct thread_info *tinfo,
        struct stack_frame *frame = (struct stack_frame *)bp;
        unsigned long *ret_addr = &frame->return_address;
 
-       while (valid_stack_ptr(tinfo, ret_addr, sizeof(*ret_addr), end)) {
+       while (valid_stack_ptr(task, ret_addr, sizeof(*ret_addr), end)) {
                unsigned long addr = *ret_addr;
 
                if (!__kernel_text_address(addr))
@@ -139,7 +137,7 @@ print_context_stack_bp(struct thread_info *tinfo,
                        break;
                frame = frame->next_frame;
                ret_addr = &frame->return_address;
-               print_ftrace_graph_addr(addr, data, ops, tinfo, graph);
+               print_ftrace_graph_addr(addr, data, ops, task, graph);
        }
 
        return (unsigned long)frame;
index 464ffd6..fef917e 100644 (file)
@@ -61,15 +61,13 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
                bp = stack_frame(task, regs);
 
        for (;;) {
-               struct thread_info *context;
                void *end_stack;
 
                end_stack = is_hardirq_stack(stack, cpu);
                if (!end_stack)
                        end_stack = is_softirq_stack(stack, cpu);
 
-               context = task_thread_info(task);
-               bp = ops->walk_stack(context, stack, bp, ops, data,
+               bp = ops->walk_stack(task, stack, bp, ops, data,
                                     end_stack, &graph);
 
                /* Stop if not on irq stack */
index 5f1c626..d558a8a 100644 (file)
@@ -153,7 +153,6 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
                const struct stacktrace_ops *ops, void *data)
 {
        const unsigned cpu = get_cpu();
-       struct thread_info *tinfo;
        unsigned long *irq_stack = (unsigned long *)per_cpu(irq_stack_ptr, cpu);
        unsigned long dummy;
        unsigned used = 0;
@@ -179,7 +178,6 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
         * current stack address. If the stacks consist of nested
         * exceptions
         */
-       tinfo = task_thread_info(task);
        while (!done) {
                unsigned long *stack_end;
                enum stack_type stype;
@@ -202,7 +200,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
                        if (ops->stack(data, id) < 0)
                                break;
 
-                       bp = ops->walk_stack(tinfo, stack, bp, ops,
+                       bp = ops->walk_stack(task, stack, bp, ops,
                                             data, stack_end, &graph);
                        ops->stack(data, "<EOE>");
                        /*
@@ -218,7 +216,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
 
                        if (ops->stack(data, "IRQ") < 0)
                                break;
-                       bp = ops->walk_stack(tinfo, stack, bp,
+                       bp = ops->walk_stack(task, stack, bp,
                                     ops, data, stack_end, &graph);
                        /*
                         * We link to the next stack (which would be
@@ -240,7 +238,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
        /*
         * This handles the process stack:
         */
-       bp = ops->walk_stack(tinfo, stack, bp, ops, data, NULL, &graph);
+       bp = ops->walk_stack(task, stack, bp, ops, data, NULL, &graph);
        put_cpu();
 }
 EXPORT_SYMBOL(dump_trace);
index 4d38416..04f89ca 100644 (file)
@@ -57,7 +57,7 @@
 # error "Need more than one PGD for the ESPFIX hack"
 #endif
 
-#define PGALLOC_GFP (GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO)
+#define PGALLOC_GFP (GFP_KERNEL | __GFP_NOTRACK | __GFP_ZERO)
 
 /* This contains the *bottom* address of the espfix stack */
 DEFINE_PER_CPU_READ_MOSTLY(unsigned long, espfix_stack);
index 38da8f2..c627bf8 100644 (file)
@@ -130,11 +130,9 @@ void irq_ctx_init(int cpu)
 
 void do_softirq_own_stack(void)
 {
-       struct thread_info *curstk;
        struct irq_stack *irqstk;
        u32 *isp, *prev_esp;
 
-       curstk = current_stack();
        irqstk = __this_cpu_read(softirq_stack);
 
        /* build the stack frame on the softirq stack */
index 38cf7a7..7847e5c 100644 (file)
@@ -961,7 +961,19 @@ int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
                 * normal page fault.
                 */
                regs->ip = (unsigned long)cur->addr;
+               /*
+                * Trap flag (TF) has been set here because this fault
+                * happened where the single stepping will be done.
+                * So clear it by resetting the current kprobe:
+                */
+               regs->flags &= ~X86_EFLAGS_TF;
+
+               /*
+                * If the TF flag was set before the kprobe hit,
+                * don't touch it:
+                */
                regs->flags |= kcb->kprobe_old_flags;
+
                if (kcb->kprobe_status == KPROBE_REENTER)
                        restore_previous_kprobe(kcb);
                else
index d159048..00f03d8 100644 (file)
@@ -96,6 +96,12 @@ static inline void cond_local_irq_disable(struct pt_regs *regs)
                local_irq_disable();
 }
 
+/*
+ * In IST context, we explicitly disable preemption.  This serves two
+ * purposes: it makes it much less likely that we would accidentally
+ * schedule in IST context and it will force a warning if we somehow
+ * manage to schedule by accident.
+ */
 void ist_enter(struct pt_regs *regs)
 {
        if (user_mode(regs)) {
@@ -110,13 +116,7 @@ void ist_enter(struct pt_regs *regs)
                rcu_nmi_enter();
        }
 
-       /*
-        * We are atomic because we're on the IST stack; or we're on
-        * x86_32, in which case we still shouldn't schedule; or we're
-        * on x86_64 and entered from user mode, in which case we're
-        * still atomic unless ist_begin_non_atomic is called.
-        */
-       preempt_count_add(HARDIRQ_OFFSET);
+       preempt_disable();
 
        /* This code is a bit fragile.  Test it. */
        RCU_LOCKDEP_WARN(!rcu_is_watching(), "ist_enter didn't work");
@@ -124,7 +124,7 @@ void ist_enter(struct pt_regs *regs)
 
 void ist_exit(struct pt_regs *regs)
 {
-       preempt_count_sub(HARDIRQ_OFFSET);
+       preempt_enable_no_resched();
 
        if (!user_mode(regs))
                rcu_nmi_exit();
@@ -155,7 +155,7 @@ void ist_begin_non_atomic(struct pt_regs *regs)
        BUG_ON((unsigned long)(current_top_of_stack() -
                               current_stack_pointer()) >= THREAD_SIZE);
 
-       preempt_count_sub(HARDIRQ_OFFSET);
+       preempt_enable_no_resched();
 }
 
 /**
@@ -165,7 +165,7 @@ void ist_begin_non_atomic(struct pt_regs *regs)
  */
 void ist_end_non_atomic(void)
 {
-       preempt_count_add(HARDIRQ_OFFSET);
+       preempt_disable();
 }
 
 static nokprobe_inline int
index 769af90..7597b42 100644 (file)
@@ -181,19 +181,22 @@ int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu,
                             struct kvm_cpuid_entry __user *entries)
 {
        int r, i;
-       struct kvm_cpuid_entry *cpuid_entries;
+       struct kvm_cpuid_entry *cpuid_entries = NULL;
 
        r = -E2BIG;
        if (cpuid->nent > KVM_MAX_CPUID_ENTRIES)
                goto out;
        r = -ENOMEM;
-       cpuid_entries = vmalloc(sizeof(struct kvm_cpuid_entry) * cpuid->nent);
-       if (!cpuid_entries)
-               goto out;
-       r = -EFAULT;
-       if (copy_from_user(cpuid_entries, entries,
-                          cpuid->nent * sizeof(struct kvm_cpuid_entry)))
-               goto out_free;
+       if (cpuid->nent) {
+               cpuid_entries = vmalloc(sizeof(struct kvm_cpuid_entry) *
+                                       cpuid->nent);
+               if (!cpuid_entries)
+                       goto out;
+               r = -EFAULT;
+               if (copy_from_user(cpuid_entries, entries,
+                                  cpuid->nent * sizeof(struct kvm_cpuid_entry)))
+                       goto out;
+       }
        for (i = 0; i < cpuid->nent; i++) {
                vcpu->arch.cpuid_entries[i].function = cpuid_entries[i].function;
                vcpu->arch.cpuid_entries[i].eax = cpuid_entries[i].eax;
@@ -212,9 +215,8 @@ int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu,
        kvm_x86_ops->cpuid_update(vcpu);
        r = kvm_update_cpuid(vcpu);
 
-out_free:
-       vfree(cpuid_entries);
 out:
+       vfree(cpuid_entries);
        return r;
 }
 
index 24e8001..def97b3 100644 (file)
@@ -336,12 +336,12 @@ static gfn_t pse36_gfn_delta(u32 gpte)
 #ifdef CONFIG_X86_64
 static void __set_spte(u64 *sptep, u64 spte)
 {
-       *sptep = spte;
+       WRITE_ONCE(*sptep, spte);
 }
 
 static void __update_clear_spte_fast(u64 *sptep, u64 spte)
 {
-       *sptep = spte;
+       WRITE_ONCE(*sptep, spte);
 }
 
 static u64 __update_clear_spte_slow(u64 *sptep, u64 spte)
@@ -390,7 +390,7 @@ static void __set_spte(u64 *sptep, u64 spte)
         */
        smp_wmb();
 
-       ssptep->spte_low = sspte.spte_low;
+       WRITE_ONCE(ssptep->spte_low, sspte.spte_low);
 }
 
 static void __update_clear_spte_fast(u64 *sptep, u64 spte)
@@ -400,7 +400,7 @@ static void __update_clear_spte_fast(u64 *sptep, u64 spte)
        ssptep = (union split_spte *)sptep;
        sspte = (union split_spte)spte;
 
-       ssptep->spte_low = sspte.spte_low;
+       WRITE_ONCE(ssptep->spte_low, sspte.spte_low);
 
        /*
         * If we map the spte from present to nonpresent, we should clear
index 1163e81..16ef31b 100644 (file)
@@ -238,7 +238,9 @@ module_param(nested, int, S_IRUGO);
 
 /* enable / disable AVIC */
 static int avic;
+#ifdef CONFIG_X86_LOCAL_APIC
 module_param(avic, int, S_IRUGO);
+#endif
 
 static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0);
 static void svm_flush_tlb(struct kvm_vcpu *vcpu);
@@ -981,11 +983,14 @@ static __init int svm_hardware_setup(void)
        } else
                kvm_disable_tdp();
 
-       if (avic && (!npt_enabled || !boot_cpu_has(X86_FEATURE_AVIC)))
-               avic = false;
-
-       if (avic)
-               pr_info("AVIC enabled\n");
+       if (avic) {
+               if (!npt_enabled ||
+                   !boot_cpu_has(X86_FEATURE_AVIC) ||
+                   !IS_ENABLED(CONFIG_X86_LOCAL_APIC))
+                       avic = false;
+               else
+                       pr_info("AVIC enabled\n");
+       }
 
        return 0;
 
@@ -1324,7 +1329,7 @@ free_avic:
 static void avic_set_running(struct kvm_vcpu *vcpu, bool is_run)
 {
        u64 entry;
-       int h_physical_id = __default_cpu_present_to_apicid(vcpu->cpu);
+       int h_physical_id = kvm_cpu_get_apicid(vcpu->cpu);
        struct vcpu_svm *svm = to_svm(vcpu);
 
        if (!kvm_vcpu_apicv_active(vcpu))
@@ -1349,7 +1354,7 @@ static void avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 {
        u64 entry;
        /* ID = 0xff (broadcast), ID > 0xff (reserved) */
-       int h_physical_id = __default_cpu_present_to_apicid(cpu);
+       int h_physical_id = kvm_cpu_get_apicid(cpu);
        struct vcpu_svm *svm = to_svm(vcpu);
 
        if (!kvm_vcpu_apicv_active(vcpu))
@@ -4236,7 +4241,7 @@ static void svm_deliver_avic_intr(struct kvm_vcpu *vcpu, int vec)
 
        if (avic_vcpu_is_running(vcpu))
                wrmsrl(SVM_AVIC_DOORBELL,
-                      __default_cpu_present_to_apicid(vcpu->cpu));
+                      kvm_cpu_get_apicid(vcpu->cpu));
        else
                kvm_vcpu_wake_up(vcpu);
 }
index fb93010..003618e 100644 (file)
@@ -2072,7 +2072,8 @@ static void vmx_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu)
        unsigned int dest;
 
        if (!kvm_arch_has_assigned_device(vcpu->kvm) ||
-               !irq_remapping_cap(IRQ_POSTING_CAP))
+               !irq_remapping_cap(IRQ_POSTING_CAP)  ||
+               !kvm_vcpu_apicv_active(vcpu))
                return;
 
        do {
@@ -2180,7 +2181,8 @@ static void vmx_vcpu_pi_put(struct kvm_vcpu *vcpu)
        struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);
 
        if (!kvm_arch_has_assigned_device(vcpu->kvm) ||
-               !irq_remapping_cap(IRQ_POSTING_CAP))
+               !irq_remapping_cap(IRQ_POSTING_CAP)  ||
+               !kvm_vcpu_apicv_active(vcpu))
                return;
 
        /* Set SN when the vCPU is preempted */
@@ -10714,7 +10716,8 @@ static int vmx_pre_block(struct kvm_vcpu *vcpu)
        struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);
 
        if (!kvm_arch_has_assigned_device(vcpu->kvm) ||
-               !irq_remapping_cap(IRQ_POSTING_CAP))
+               !irq_remapping_cap(IRQ_POSTING_CAP)  ||
+               !kvm_vcpu_apicv_active(vcpu))
                return 0;
 
        vcpu->pre_pcpu = vcpu->cpu;
@@ -10780,7 +10783,8 @@ static void vmx_post_block(struct kvm_vcpu *vcpu)
        unsigned long flags;
 
        if (!kvm_arch_has_assigned_device(vcpu->kvm) ||
-               !irq_remapping_cap(IRQ_POSTING_CAP))
+               !irq_remapping_cap(IRQ_POSTING_CAP)  ||
+               !kvm_vcpu_apicv_active(vcpu))
                return;
 
        do {
@@ -10833,7 +10837,8 @@ static int vmx_update_pi_irte(struct kvm *kvm, unsigned int host_irq,
        int idx, ret = -EINVAL;
 
        if (!kvm_arch_has_assigned_device(kvm) ||
-               !irq_remapping_cap(IRQ_POSTING_CAP))
+               !irq_remapping_cap(IRQ_POSTING_CAP) ||
+               !kvm_vcpu_apicv_active(kvm->vcpus[0]))
                return 0;
 
        idx = srcu_read_lock(&kvm->irq_srcu);
index c805cf4..902d9da 100644 (file)
@@ -2314,6 +2314,7 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
        case MSR_AMD64_NB_CFG:
        case MSR_FAM10H_MMIO_CONF_BASE:
        case MSR_AMD64_BU_CFG2:
+       case MSR_IA32_PERF_CTL:
                msr_info->data = 0;
                break;
        case MSR_K7_EVNTSEL0 ... MSR_K7_EVNTSEL3:
@@ -2972,6 +2973,10 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct kvm_vcpu *vcpu,
                              | KVM_VCPUEVENT_VALID_SMM))
                return -EINVAL;
 
+       if (events->exception.injected &&
+           (events->exception.nr > 31 || events->exception.nr == NMI_VECTOR))
+               return -EINVAL;
+
        process_nmi(vcpu);
        vcpu->arch.exception.pending = events->exception.injected;
        vcpu->arch.exception.nr = events->exception.nr;
@@ -3036,6 +3041,11 @@ static int kvm_vcpu_ioctl_x86_set_debugregs(struct kvm_vcpu *vcpu,
        if (dbgregs->flags)
                return -EINVAL;
 
+       if (dbgregs->dr6 & ~0xffffffffull)
+               return -EINVAL;
+       if (dbgregs->dr7 & ~0xffffffffull)
+               return -EINVAL;
+
        memcpy(vcpu->arch.db, dbgregs->db, sizeof(vcpu->arch.db));
        kvm_update_dr0123(vcpu);
        vcpu->arch.dr6 = dbgregs->dr6;
@@ -7815,7 +7825,7 @@ int __x86_set_memory_region(struct kvm *kvm, int id, gpa_t gpa, u32 size)
 
        slot = id_to_memslot(slots, id);
        if (size) {
-               if (WARN_ON(slot->npages))
+               if (slot->npages)
                        return -EEXIST;
 
                /*
index 4eb287e..aa0ff4b 100644 (file)
@@ -6,7 +6,7 @@
 #include <asm/fixmap.h>
 #include <asm/mtrr.h>
 
-#define PGALLOC_GFP GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO
+#define PGALLOC_GFP GFP_KERNEL | __GFP_NOTRACK | __GFP_ZERO
 
 #ifdef CONFIG_HIGHPTE
 #define PGALLOC_USER_GFP __GFP_HIGHMEM
index 6e7242b..b226b3f 100644 (file)
@@ -139,7 +139,7 @@ int __init efi_alloc_page_tables(void)
        if (efi_enabled(EFI_OLD_MEMMAP))
                return 0;
 
-       gfp_mask = GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO;
+       gfp_mask = GFP_KERNEL | __GFP_NOTRACK | __GFP_ZERO;
        efi_pgd = (pgd_t *)__get_free_page(gfp_mask);
        if (!efi_pgd)
                return -ENOMEM;
index 478a2de..6743371 100644 (file)
@@ -1113,7 +1113,7 @@ static void __init xen_cleanhighmap(unsigned long vaddr,
 
        /* NOTE: The loop is more greedy than the cleanup_highmap variant.
         * We include the PMD passed in on _both_ boundaries. */
-       for (; vaddr <= vaddr_end && (pmd < (level2_kernel_pgt + PAGE_SIZE));
+       for (; vaddr <= vaddr_end && (pmd < (level2_kernel_pgt + PTRS_PER_PMD));
                        pmd++, vaddr += PMD_SIZE) {
                if (pmd_none(*pmd))
                        continue;
@@ -1551,41 +1551,6 @@ static void xen_pgd_free(struct mm_struct *mm, pgd_t *pgd)
 #endif
 }
 
-#ifdef CONFIG_X86_32
-static pte_t __init mask_rw_pte(pte_t *ptep, pte_t pte)
-{
-       /* If there's an existing pte, then don't allow _PAGE_RW to be set */
-       if (pte_val_ma(*ptep) & _PAGE_PRESENT)
-               pte = __pte_ma(((pte_val_ma(*ptep) & _PAGE_RW) | ~_PAGE_RW) &
-                              pte_val_ma(pte));
-
-       return pte;
-}
-#else /* CONFIG_X86_64 */
-static pte_t __init mask_rw_pte(pte_t *ptep, pte_t pte)
-{
-       unsigned long pfn;
-
-       if (xen_feature(XENFEAT_writable_page_tables) ||
-           xen_feature(XENFEAT_auto_translated_physmap) ||
-           xen_start_info->mfn_list >= __START_KERNEL_map)
-               return pte;
-
-       /*
-        * Pages belonging to the initial p2m list mapped outside the default
-        * address range must be mapped read-only. This region contains the
-        * page tables for mapping the p2m list, too, and page tables MUST be
-        * mapped read-only.
-        */
-       pfn = pte_pfn(pte);
-       if (pfn >= xen_start_info->first_p2m_pfn &&
-           pfn < xen_start_info->first_p2m_pfn + xen_start_info->nr_p2m_frames)
-               pte = __pte_ma(pte_val_ma(pte) & ~_PAGE_RW);
-
-       return pte;
-}
-#endif /* CONFIG_X86_64 */
-
 /*
  * Init-time set_pte while constructing initial pagetables, which
  * doesn't allow RO page table pages to be remapped RW.
@@ -1600,13 +1565,37 @@ static pte_t __init mask_rw_pte(pte_t *ptep, pte_t pte)
  * so always write the PTE directly and rely on Xen trapping and
  * emulating any updates as necessary.
  */
-static void __init xen_set_pte_init(pte_t *ptep, pte_t pte)
+__visible pte_t xen_make_pte_init(pteval_t pte)
 {
-       if (pte_mfn(pte) != INVALID_P2M_ENTRY)
-               pte = mask_rw_pte(ptep, pte);
-       else
-               pte = __pte_ma(0);
+#ifdef CONFIG_X86_64
+       unsigned long pfn;
+
+       /*
+        * Pages belonging to the initial p2m list mapped outside the default
+        * address range must be mapped read-only. This region contains the
+        * page tables for mapping the p2m list, too, and page tables MUST be
+        * mapped read-only.
+        */
+       pfn = (pte & PTE_PFN_MASK) >> PAGE_SHIFT;
+       if (xen_start_info->mfn_list < __START_KERNEL_map &&
+           pfn >= xen_start_info->first_p2m_pfn &&
+           pfn < xen_start_info->first_p2m_pfn + xen_start_info->nr_p2m_frames)
+               pte &= ~_PAGE_RW;
+#endif
+       pte = pte_pfn_to_mfn(pte);
+       return native_make_pte(pte);
+}
+PV_CALLEE_SAVE_REGS_THUNK(xen_make_pte_init);
 
+static void __init xen_set_pte_init(pte_t *ptep, pte_t pte)
+{
+#ifdef CONFIG_X86_32
+       /* If there's an existing pte, then don't allow _PAGE_RW to be set */
+       if (pte_mfn(pte) != INVALID_P2M_ENTRY
+           && pte_val_ma(*ptep) & _PAGE_PRESENT)
+               pte = __pte_ma(((pte_val_ma(*ptep) & _PAGE_RW) | ~_PAGE_RW) &
+                              pte_val_ma(pte));
+#endif
        native_set_pte(ptep, pte);
 }
 
@@ -2407,6 +2396,7 @@ static void __init xen_post_allocator_init(void)
        pv_mmu_ops.alloc_pud = xen_alloc_pud;
        pv_mmu_ops.release_pud = xen_release_pud;
 #endif
+       pv_mmu_ops.make_pte = PV_CALLEE_SAVE(xen_make_pte);
 
 #ifdef CONFIG_X86_64
        pv_mmu_ops.write_cr3 = &xen_write_cr3;
@@ -2455,7 +2445,7 @@ static const struct pv_mmu_ops xen_mmu_ops __initconst = {
        .pte_val = PV_CALLEE_SAVE(xen_pte_val),
        .pgd_val = PV_CALLEE_SAVE(xen_pgd_val),
 
-       .make_pte = PV_CALLEE_SAVE(xen_make_pte),
+       .make_pte = PV_CALLEE_SAVE(xen_make_pte_init),
        .make_pgd = PV_CALLEE_SAVE(xen_make_pgd),
 
 #ifdef CONFIG_X86_PAE
index cab9f76..dd2a49a 100644 (file)
@@ -182,7 +182,7 @@ static void * __ref alloc_p2m_page(void)
        if (unlikely(!slab_is_available()))
                return alloc_bootmem_align(PAGE_SIZE, PAGE_SIZE);
 
-       return (void *)__get_free_page(GFP_KERNEL | __GFP_REPEAT);
+       return (void *)__get_free_page(GFP_KERNEL);
 }
 
 static void __ref free_p2m_page(void *p)
index d38eb92..1065bc8 100644 (file)
@@ -44,7 +44,7 @@ static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
        pte_t *ptep;
        int i;
 
-       ptep = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT);
+       ptep = (pte_t *)__get_free_page(GFP_KERNEL);
        if (!ptep)
                return NULL;
        for (i = 0; i < 1024; i++)
index 23d7f30..9e29dc3 100644 (file)
@@ -113,6 +113,7 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
                ret = submit_bio_wait(type, bio);
                if (ret == -EOPNOTSUPP)
                        ret = 0;
+               bio_put(bio);
        }
        blk_finish_plug(&plug);
 
@@ -165,8 +166,10 @@ int blkdev_issue_write_same(struct block_device *bdev, sector_t sector,
                }
        }
 
-       if (bio)
+       if (bio) {
                ret = submit_bio_wait(REQ_WRITE | REQ_WRITE_SAME, bio);
+               bio_put(bio);
+       }
        return ret != -EOPNOTSUPP ? ret : 0;
 }
 EXPORT_SYMBOL(blkdev_issue_write_same);
@@ -206,8 +209,11 @@ static int __blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
                }
        }
 
-       if (bio)
-               return submit_bio_wait(WRITE, bio);
+       if (bio) {
+               ret = submit_bio_wait(WRITE, bio);
+               bio_put(bio);
+               return ret;
+       }
        return 0;
 }
 
index 29cbc1b..f9b9049 100644 (file)
@@ -1262,12 +1262,9 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio)
 
        blk_queue_split(q, &bio, q->bio_split);
 
-       if (!is_flush_fua && !blk_queue_nomerges(q)) {
-               if (blk_attempt_plug_merge(q, bio, &request_count,
-                                          &same_queue_rq))
-                       return BLK_QC_T_NONE;
-       } else
-               request_count = blk_plug_queued_count(q);
+       if (!is_flush_fua && !blk_queue_nomerges(q) &&
+           blk_attempt_plug_merge(q, bio, &request_count, &same_queue_rq))
+               return BLK_QC_T_NONE;
 
        rq = blk_mq_map_request(q, bio, &data);
        if (unlikely(!rq))
@@ -1358,9 +1355,11 @@ static blk_qc_t blk_sq_make_request(struct request_queue *q, struct bio *bio)
 
        blk_queue_split(q, &bio, q->bio_split);
 
-       if (!is_flush_fua && !blk_queue_nomerges(q) &&
-           blk_attempt_plug_merge(q, bio, &request_count, NULL))
-               return BLK_QC_T_NONE;
+       if (!is_flush_fua && !blk_queue_nomerges(q)) {
+               if (blk_attempt_plug_merge(q, bio, &request_count, NULL))
+                       return BLK_QC_T_NONE;
+       } else
+               request_count = blk_plug_queued_count(q);
 
        rq = blk_mq_map_request(q, bio, &data);
        if (unlikely(!rq))
index e28e912..331f6ba 100644 (file)
@@ -13,6 +13,7 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE
        tristate "Asymmetric public-key crypto algorithm subtype"
        select MPILIB
        select CRYPTO_HASH_INFO
+       select CRYPTO_AKCIPHER
        help
          This option provides support for asymmetric public key type handling.
          If signature generation and/or verification are to be used,
index 0d92d0f..c7ba948 100644 (file)
@@ -331,15 +331,6 @@ static int acpi_processor_get_info(struct acpi_device *device)
                pr->throttling.duty_width = acpi_gbl_FADT.duty_width;
 
                pr->pblk = object.processor.pblk_address;
-
-               /*
-                * We don't care about error returns - we just try to mark
-                * these reserved so that nobody else is confused into thinking
-                * that this region might be unused..
-                *
-                * (In particular, allocating the IO range for Cardbus)
-                */
-               request_region(pr->throttling.address, 6, "ACPI CPU throttle");
        }
 
        /*
index 3d5b8a0..c1d138e 100644 (file)
@@ -754,7 +754,8 @@ static int acpi_video_bqc_quirk(struct acpi_video_device *device,
 }
 
 int acpi_video_get_levels(struct acpi_device *device,
-                         struct acpi_video_device_brightness **dev_br)
+                         struct acpi_video_device_brightness **dev_br,
+                         int *pmax_level)
 {
        union acpi_object *obj = NULL;
        int i, max_level = 0, count = 0, level_ac_battery = 0;
@@ -841,6 +842,8 @@ int acpi_video_get_levels(struct acpi_device *device,
 
        br->count = count;
        *dev_br = br;
+       if (pmax_level)
+               *pmax_level = max_level;
 
 out:
        kfree(obj);
@@ -869,7 +872,7 @@ acpi_video_init_brightness(struct acpi_video_device *device)
        struct acpi_video_device_brightness *br = NULL;
        int result = -EINVAL;
 
-       result = acpi_video_get_levels(device->dev, &br);
+       result = acpi_video_get_levels(device->dev, &br, &max_level);
        if (result)
                return result;
        device->brightness = br;
@@ -1737,7 +1740,7 @@ static void acpi_video_run_bcl_for_osi(struct acpi_video_bus *video)
 
        mutex_lock(&video->device_list_lock);
        list_for_each_entry(dev, &video->video_device_list, entry) {
-               if (!acpi_video_device_lcd_query_levels(dev, &levels))
+               if (!acpi_video_device_lcd_query_levels(dev->dev->handle, &levels))
                        kfree(levels);
        }
        mutex_unlock(&video->device_list_lock);
index a1d177d..21932d6 100644 (file)
@@ -108,7 +108,9 @@ acpi_ex_add_table(u32 table_index,
 
        /* Add the table to the namespace */
 
+       acpi_ex_exit_interpreter();
        status = acpi_ns_load_table(table_index, parent_node);
+       acpi_ex_enter_interpreter();
        if (ACPI_FAILURE(status)) {
                acpi_ut_remove_reference(obj_desc);
                *ddb_handle = NULL;
index 0f18dbc..3b7fb99 100644 (file)
@@ -83,27 +83,22 @@ acpi_hw_write_multiple(u32 value,
 static u8
 acpi_hw_get_access_bit_width(struct acpi_generic_address *reg, u8 max_bit_width)
 {
-       u64 address;
-
        if (!reg->access_width) {
+               if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
+                       max_bit_width = 32;
+               }
+
                /*
                 * Detect old register descriptors where only the bit_width field
-                * makes senses. The target address is copied to handle possible
-                * alignment issues.
+                * makes senses.
                 */
-               ACPI_MOVE_64_TO_64(&address, &reg->address);
-               if (!reg->bit_offset && reg->bit_width &&
+               if (reg->bit_width < max_bit_width &&
+                   !reg->bit_offset && reg->bit_width &&
                    ACPI_IS_POWER_OF_TWO(reg->bit_width) &&
-                   ACPI_IS_ALIGNED(reg->bit_width, 8) &&
-                   ACPI_IS_ALIGNED(address, reg->bit_width)) {
+                   ACPI_IS_ALIGNED(reg->bit_width, 8)) {
                        return (reg->bit_width);
-               } else {
-                       if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
-                               return (32);
-                       } else {
-                               return (max_bit_width);
-                       }
                }
+               return (max_bit_width);
        } else {
                return (1 << (reg->access_width + 2));
        }
@@ -311,12 +306,6 @@ acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg)
 acpi_status acpi_hw_write(u32 value, struct acpi_generic_address *reg)
 {
        u64 address;
-       u8 access_width;
-       u32 bit_width;
-       u8 bit_offset;
-       u64 value64;
-       u32 new_value32, old_value32;
-       u8 index;
        acpi_status status;
 
        ACPI_FUNCTION_NAME(hw_write);
@@ -328,145 +317,23 @@ acpi_status acpi_hw_write(u32 value, struct acpi_generic_address *reg)
                return (status);
        }
 
-       /* Convert access_width into number of bits based */
-
-       access_width = acpi_hw_get_access_bit_width(reg, 32);
-       bit_width = reg->bit_offset + reg->bit_width;
-       bit_offset = reg->bit_offset;
-
        /*
         * Two address spaces supported: Memory or IO. PCI_Config is
         * not supported here because the GAS structure is insufficient
         */
-       index = 0;
-       while (bit_width) {
-               /*
-                * Use offset style bit reads because "Index * AccessWidth" is
-                * ensured to be less than 32-bits by acpi_hw_validate_register().
-                */
-               new_value32 = ACPI_GET_BITS(&value, index * access_width,
-                                           ACPI_MASK_BITS_ABOVE_32
-                                           (access_width));
-
-               if (bit_offset >= access_width) {
-                       bit_offset -= access_width;
-               } else {
-                       /*
-                        * Use offset style bit masks because access_width is ensured
-                        * to be less than 32-bits by acpi_hw_validate_register() and
-                        * bit_offset/bit_width is less than access_width here.
-                        */
-                       if (bit_offset) {
-                               new_value32 &= ACPI_MASK_BITS_BELOW(bit_offset);
-                       }
-                       if (bit_width < access_width) {
-                               new_value32 &= ACPI_MASK_BITS_ABOVE(bit_width);
-                       }
-
-                       if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
-                               if (bit_offset || bit_width < access_width) {
-                                       /*
-                                        * Read old values in order not to modify the bits that
-                                        * are beyond the register bit_width/bit_offset setting.
-                                        */
-                                       status =
-                                           acpi_os_read_memory((acpi_physical_address)
-                                                               address +
-                                                               index *
-                                                               ACPI_DIV_8
-                                                               (access_width),
-                                                               &value64,
-                                                               access_width);
-                                       old_value32 = (u32)value64;
-
-                                       /*
-                                        * Use offset style bit masks because access_width is
-                                        * ensured to be less than 32-bits by
-                                        * acpi_hw_validate_register() and bit_offset/bit_width is
-                                        * less than access_width here.
-                                        */
-                                       if (bit_offset) {
-                                               old_value32 &=
-                                                   ACPI_MASK_BITS_ABOVE
-                                                   (bit_offset);
-                                               bit_offset = 0;
-                                       }
-                                       if (bit_width < access_width) {
-                                               old_value32 &=
-                                                   ACPI_MASK_BITS_BELOW
-                                                   (bit_width);
-                                       }
-
-                                       new_value32 |= old_value32;
-                               }
-
-                               value64 = (u64)new_value32;
-                               status =
-                                   acpi_os_write_memory((acpi_physical_address)
-                                                        address +
-                                                        index *
-                                                        ACPI_DIV_8
-                                                        (access_width),
-                                                        value64, access_width);
-                       } else {        /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
-
-                               if (bit_offset || bit_width < access_width) {
-                                       /*
-                                        * Read old values in order not to modify the bits that
-                                        * are beyond the register bit_width/bit_offset setting.
-                                        */
-                                       status =
-                                           acpi_hw_read_port((acpi_io_address)
-                                                             address +
-                                                             index *
-                                                             ACPI_DIV_8
-                                                             (access_width),
-                                                             &old_value32,
-                                                             access_width);
-
-                                       /*
-                                        * Use offset style bit masks because access_width is
-                                        * ensured to be less than 32-bits by
-                                        * acpi_hw_validate_register() and bit_offset/bit_width is
-                                        * less than access_width here.
-                                        */
-                                       if (bit_offset) {
-                                               old_value32 &=
-                                                   ACPI_MASK_BITS_ABOVE
-                                                   (bit_offset);
-                                               bit_offset = 0;
-                                       }
-                                       if (bit_width < access_width) {
-                                               old_value32 &=
-                                                   ACPI_MASK_BITS_BELOW
-                                                   (bit_width);
-                                       }
-
-                                       new_value32 |= old_value32;
-                               }
-
-                               status = acpi_hw_write_port((acpi_io_address)
-                                                           address +
-                                                           index *
-                                                           ACPI_DIV_8
-                                                           (access_width),
-                                                           new_value32,
-                                                           access_width);
-                       }
-               }
-
-               /*
-                * Index * access_width is ensured to be less than 32-bits by
-                * acpi_hw_validate_register().
-                */
-               bit_width -=
-                   bit_width > access_width ? access_width : bit_width;
-               index++;
+       if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
+               status = acpi_os_write_memory((acpi_physical_address)
+                                             address, (u64)value,
+                                             reg->bit_width);
+       } else {                /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
+
+               status = acpi_hw_write_port((acpi_io_address)
+                                           address, value, reg->bit_width);
        }
 
        ACPI_DEBUG_PRINT((ACPI_DB_IO,
                          "Wrote: %8.8X width %2d   to %8.8X%8.8X (%s)\n",
-                         value, access_width, ACPI_FORMAT_UINT64(address),
+                         value, reg->bit_width, ACPI_FORMAT_UINT64(address),
                          acpi_ut_get_region_name(reg->space_id)));
 
        return (status);
index f631a47..1783cd7 100644 (file)
@@ -47,6 +47,7 @@
 #include "acparser.h"
 #include "acdispat.h"
 #include "actables.h"
+#include "acinterp.h"
 
 #define _COMPONENT          ACPI_NAMESPACE
 ACPI_MODULE_NAME("nsparse")
@@ -170,6 +171,8 @@ acpi_ns_parse_table(u32 table_index, struct acpi_namespace_node *start_node)
 
        ACPI_FUNCTION_TRACE(ns_parse_table);
 
+       acpi_ex_enter_interpreter();
+
        /*
         * AML Parse, pass 1
         *
@@ -185,7 +188,7 @@ acpi_ns_parse_table(u32 table_index, struct acpi_namespace_node *start_node)
        status = acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS1,
                                            table_index, start_node);
        if (ACPI_FAILURE(status)) {
-               return_ACPI_STATUS(status);
+               goto error_exit;
        }
 
        /*
@@ -201,8 +204,10 @@ acpi_ns_parse_table(u32 table_index, struct acpi_namespace_node *start_node)
        status = acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS2,
                                            table_index, start_node);
        if (ACPI_FAILURE(status)) {
-               return_ACPI_STATUS(status);
+               goto error_exit;
        }
 
+error_exit:
+       acpi_ex_exit_interpreter();
        return_ACPI_STATUS(status);
 }
index 31e8da6..262ca31 100644 (file)
@@ -1051,7 +1051,7 @@ static int __init acpi_bus_init(void)
         * Maybe EC region is required at bus_scan/acpi_get_devices. So it
         * is necessary to enable it as early as possible.
         */
-       acpi_boot_ec_enable();
+       acpi_ec_dsdt_probe();
 
        printk(KERN_INFO PREFIX "Interpreter enabled\n");
 
index 0e70181..73c76d6 100644 (file)
@@ -1446,10 +1446,30 @@ ec_parse_io_ports(struct acpi_resource *resource, void *context)
        return AE_OK;
 }
 
-int __init acpi_boot_ec_enable(void)
+static const struct acpi_device_id ec_device_ids[] = {
+       {"PNP0C09", 0},
+       {"", 0},
+};
+
+int __init acpi_ec_dsdt_probe(void)
 {
-       if (!boot_ec)
+       acpi_status status;
+
+       if (boot_ec)
                return 0;
+
+       /*
+        * Finding EC from DSDT if there is no ECDT EC available. When this
+        * function is invoked, ACPI tables have been fully loaded, we can
+        * walk namespace now.
+        */
+       boot_ec = make_acpi_ec();
+       if (!boot_ec)
+               return -ENOMEM;
+       status = acpi_get_devices(ec_device_ids[0].id,
+                                 ec_parse_device, boot_ec, NULL);
+       if (ACPI_FAILURE(status) || !boot_ec->handle)
+               return -ENODEV;
        if (!ec_install_handlers(boot_ec)) {
                first_ec = boot_ec;
                return 0;
@@ -1457,11 +1477,6 @@ int __init acpi_boot_ec_enable(void)
        return -EFAULT;
 }
 
-static const struct acpi_device_id ec_device_ids[] = {
-       {"PNP0C09", 0},
-       {"", 0},
-};
-
 #if 0
 /*
  * Some EC firmware variations refuses to respond QR_EC when SCI_EVT is not
index 9bb0773..27cc7fe 100644 (file)
@@ -181,7 +181,7 @@ typedef int (*acpi_ec_query_func) (void *data);
 
 int acpi_ec_init(void);
 int acpi_ec_ecdt_probe(void);
-int acpi_boot_ec_enable(void);
+int acpi_ec_dsdt_probe(void);
 void acpi_ec_block_transactions(void);
 void acpi_ec_unblock_transactions(void);
 void acpi_ec_unblock_transactions_early(void);
index f170d74..c72e648 100644 (file)
@@ -676,6 +676,15 @@ static int acpi_processor_get_throttling_fadt(struct acpi_processor *pr)
        if (!pr->flags.throttling)
                return -ENODEV;
 
+       /*
+        * We don't care about error returns - we just try to mark
+        * these reserved so that nobody else is confused into thinking
+        * that this region might be unused..
+        *
+        * (In particular, allocating the IO range for Cardbus)
+        */
+       request_region(pr->throttling.address, 6, "ACPI CPU throttle");
+
        pr->throttling.state = 0;
 
        duty_mask = pr->throttling.state_count - 1;
index 61dc7a9..c6f0174 100644 (file)
@@ -606,7 +606,7 @@ void ata_scsi_error(struct Scsi_Host *host)
        ata_scsi_port_error_handler(host, ap);
 
        /* finish or retry handled scmd's and clean up */
-       WARN_ON(host->host_failed || !list_empty(&eh_work_q));
+       WARN_ON(!list_empty(&eh_work_q));
 
        DPRINTK("EXIT\n");
 }
index a969a7e..85aaf22 100644 (file)
@@ -181,13 +181,17 @@ static char *res_strings[] = {
        "reserved 27", 
        "reserved 28", 
        "reserved 29", 
-       "reserved 30", 
+       "reserved 30", /* FIXME: The strings between 30-40 might be wrong. */
        "reassembly abort: no buffers", 
        "receive buffer overflow", 
        "change in GFC", 
        "receive buffer full", 
        "low priority discard - no receive descriptor", 
        "low priority discard - missing end of packet", 
+       "reserved 37",
+       "reserved 38",
+       "reserved 39",
+       "reseverd 40",
        "reserved 41", 
        "reserved 42", 
        "reserved 43", 
index 7d00f29..809dd1e 100644 (file)
@@ -1128,7 +1128,7 @@ static int rx_pkt(struct atm_dev *dev)
        /* make the ptr point to the corresponding buffer desc entry */  
        buf_desc_ptr += desc;     
         if (!desc || (desc > iadev->num_rx_desc) || 
-                      ((buf_desc_ptr->vc_index & 0xffff) > iadev->num_vc)) { 
+                      ((buf_desc_ptr->vc_index & 0xffff) >= iadev->num_vc)) {
             free_desc(dev, desc);
             IF_ERR(printk("IA: bad descriptor desc = %d \n", desc);)
             return -1;
index 6b2a84e..2609ba2 100644 (file)
@@ -10,7 +10,7 @@ obj-$(CONFIG_DMA_CMA) += dma-contiguous.o
 obj-y                  += power/
 obj-$(CONFIG_HAS_DMA)  += dma-mapping.o
 obj-$(CONFIG_HAVE_GENERIC_DMA_COHERENT) += dma-coherent.o
-obj-$(CONFIG_ISA)      += isa.o
+obj-$(CONFIG_ISA_BUS_API)      += isa.o
 obj-$(CONFIG_FW_LOADER)        += firmware_class.o
 obj-$(CONFIG_NUMA)     += node.o
 obj-$(CONFIG_MEMORY_HOTPLUG_SPARSE) += memory.o
index 91dba65..cd6ccdc 100644 (file)
@@ -180,4 +180,4 @@ static int __init isa_bus_init(void)
        return error;
 }
 
-device_initcall(isa_bus_init);
+postcore_initcall(isa_bus_init);
index db930d3..2a21578 100644 (file)
@@ -24,10 +24,12 @@ static char *make_driver_name(struct device_driver *drv)
 
 static void module_create_drivers_dir(struct module_kobject *mk)
 {
-       if (!mk || mk->drivers_dir)
-               return;
+       static DEFINE_MUTEX(drivers_dir_mutex);
 
-       mk->drivers_dir = kobject_create_and_add("drivers", &mk->kobj);
+       mutex_lock(&drivers_dir_mutex);
+       if (mk && !mk->drivers_dir)
+               mk->drivers_dir = kobject_create_and_add("drivers", &mk->kobj);
+       mutex_unlock(&drivers_dir_mutex);
 }
 
 void module_add_driver(struct module *mod, struct device_driver *drv)
index 83d6e7b..8c3434b 100644 (file)
@@ -211,7 +211,7 @@ int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev,
                }
 
                /* Mark opp-table as multiple CPUs are sharing it now */
-               opp_table->shared_opp = true;
+               opp_table->shared_opp = OPP_TABLE_ACCESS_SHARED;
        }
 unlock:
        mutex_unlock(&opp_table_lock);
@@ -227,7 +227,8 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_set_sharing_cpus);
  *
  * This updates the @cpumask with CPUs that are sharing OPPs with @cpu_dev.
  *
- * Returns -ENODEV if OPP table isn't already present.
+ * Returns -ENODEV if OPP table isn't already present and -EINVAL if the OPP
+ * table's status is access-unknown.
  *
  * Locking: The internal opp_table and opp structures are RCU protected.
  * Hence this function internally uses RCU updater strategy with mutex locks
@@ -249,9 +250,14 @@ int dev_pm_opp_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask)
                goto unlock;
        }
 
+       if (opp_table->shared_opp == OPP_TABLE_ACCESS_UNKNOWN) {
+               ret = -EINVAL;
+               goto unlock;
+       }
+
        cpumask_clear(cpumask);
 
-       if (opp_table->shared_opp) {
+       if (opp_table->shared_opp == OPP_TABLE_ACCESS_SHARED) {
                list_for_each_entry(opp_dev, &opp_table->dev_list, node)
                        cpumask_set_cpu(opp_dev->dev->id, cpumask);
        } else {
index 94d2010..1dfd3dd 100644 (file)
@@ -34,7 +34,10 @@ static struct opp_table *_managed_opp(const struct device_node *np)
                         * But the OPPs will be considered as shared only if the
                         * OPP table contains a "opp-shared" property.
                         */
-                       return opp_table->shared_opp ? opp_table : NULL;
+                       if (opp_table->shared_opp == OPP_TABLE_ACCESS_SHARED)
+                               return opp_table;
+
+                       return NULL;
                }
        }
 
@@ -353,7 +356,10 @@ static int _of_add_opp_table_v2(struct device *dev, struct device_node *opp_np)
        }
 
        opp_table->np = opp_np;
-       opp_table->shared_opp = of_property_read_bool(opp_np, "opp-shared");
+       if (of_property_read_bool(opp_np, "opp-shared"))
+               opp_table->shared_opp = OPP_TABLE_ACCESS_SHARED;
+       else
+               opp_table->shared_opp = OPP_TABLE_ACCESS_EXCLUSIVE;
 
        mutex_unlock(&opp_table_lock);
 
index 20f3be2..fabd5ca 100644 (file)
@@ -119,6 +119,12 @@ struct opp_device {
 #endif
 };
 
+enum opp_table_access {
+       OPP_TABLE_ACCESS_UNKNOWN = 0,
+       OPP_TABLE_ACCESS_EXCLUSIVE = 1,
+       OPP_TABLE_ACCESS_SHARED = 2,
+};
+
 /**
  * struct opp_table - Device opp structure
  * @node:      table node - contains the devices with OPPs that
@@ -166,7 +172,7 @@ struct opp_table {
        /* For backward compatibility with v1 bindings */
        unsigned int voltage_tolerance_v1;
 
-       bool shared_opp;
+       enum opp_table_access shared_opp;
        struct dev_pm_opp *suspend_opp;
 
        unsigned int *supported_hw;
index d597e43..ab19adb 100644 (file)
@@ -1750,7 +1750,7 @@ aoecmd_init(void)
        int ret;
 
        /* get_zeroed_page returns page with ref count 1 */
-       p = (void *) get_zeroed_page(GFP_KERNEL | __GFP_REPEAT);
+       p = (void *) get_zeroed_page(GFP_KERNEL);
        if (!p)
                return -ENOMEM;
        empty_page = virt_to_page(p);
index 31e73a7..6a48ed4 100644 (file)
@@ -941,7 +941,7 @@ static int nbd_dev_dbg_init(struct nbd_device *nbd)
        debugfs_create_u64("size_bytes", 0444, dir, &nbd->bytesize);
        debugfs_create_u32("timeout", 0444, dir, &nbd->xmit_timeout);
        debugfs_create_u32("blocksize", 0444, dir, &nbd->blksize);
-       debugfs_create_file("flags", 0444, dir, &nbd, &nbd_dbg_flags_ops);
+       debugfs_create_file("flags", 0444, dir, nbd, &nbd_dbg_flags_ops);
 
        return 0;
 }
index ca13df8..2e6d1e9 100644 (file)
@@ -874,8 +874,12 @@ static int blkif_queue_rq(struct blk_mq_hw_ctx *hctx,
                          const struct blk_mq_queue_data *qd)
 {
        unsigned long flags;
-       struct blkfront_ring_info *rinfo = (struct blkfront_ring_info *)hctx->driver_data;
+       int qid = hctx->queue_num;
+       struct blkfront_info *info = hctx->queue->queuedata;
+       struct blkfront_ring_info *rinfo = NULL;
 
+       BUG_ON(info->nr_rings <= qid);
+       rinfo = &info->rinfo[qid];
        blk_mq_start_request(qd->rq);
        spin_lock_irqsave(&rinfo->ring_lock, flags);
        if (RING_FULL(&rinfo->ring))
@@ -901,20 +905,9 @@ out_busy:
        return BLK_MQ_RQ_QUEUE_BUSY;
 }
 
-static int blk_mq_init_hctx(struct blk_mq_hw_ctx *hctx, void *data,
-                           unsigned int index)
-{
-       struct blkfront_info *info = (struct blkfront_info *)data;
-
-       BUG_ON(info->nr_rings <= index);
-       hctx->driver_data = &info->rinfo[index];
-       return 0;
-}
-
 static struct blk_mq_ops blkfront_mq_ops = {
        .queue_rq = blkif_queue_rq,
        .map_queue = blk_mq_map_queue,
-       .init_hctx = blk_mq_init_hctx,
 };
 
 static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size,
@@ -950,6 +943,7 @@ static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size,
                return PTR_ERR(rq);
        }
 
+       rq->queuedata = info;
        queue_flag_set_unlocked(QUEUE_FLAG_VIRT, rq);
 
        if (info->feature_discard) {
@@ -2149,6 +2143,8 @@ static int blkfront_resume(struct xenbus_device *dev)
                return err;
 
        err = talk_to_blkback(dev, info);
+       if (!err)
+               blk_mq_update_nr_hw_queues(&info->tag_set, info->nr_rings);
 
        /*
         * We have to wait for the backend to switch to
@@ -2485,10 +2481,23 @@ static void blkback_changed(struct xenbus_device *dev,
                break;
 
        case XenbusStateConnected:
-               if (dev->state != XenbusStateInitialised) {
+               /*
+                * talk_to_blkback sets state to XenbusStateInitialised
+                * and blkfront_connect sets it to XenbusStateConnected
+                * (if connection went OK).
+                *
+                * If the backend (or toolstack) decides to poke at backend
+                * state (and re-trigger the watch by setting the state repeatedly
+                * to XenbusStateConnected (4)) we need to deal with this.
+                * This is allowed as this is used to communicate to the guest
+                * that the size of disk has changed!
+                */
+               if ((dev->state != XenbusStateInitialised) &&
+                   (dev->state != XenbusStateConnected)) {
                        if (talk_to_blkback(dev, info))
                                break;
                }
+
                blkfront_connect(info);
                break;
 
index 94fb407..44b1bd6 100644 (file)
@@ -3820,6 +3820,7 @@ static void handle_new_recv_msgs(ipmi_smi_t intf)
        while (!list_empty(&intf->waiting_rcv_msgs)) {
                smi_msg = list_entry(intf->waiting_rcv_msgs.next,
                                     struct ipmi_smi_msg, link);
+               list_del(&smi_msg->link);
                if (!run_to_completion)
                        spin_unlock_irqrestore(&intf->waiting_rcv_msgs_lock,
                                               flags);
@@ -3829,11 +3830,14 @@ static void handle_new_recv_msgs(ipmi_smi_t intf)
                if (rv > 0) {
                        /*
                         * To preserve message order, quit if we
-                        * can't handle a message.
+                        * can't handle a message.  Add the message
+                        * back at the head, this is safe because this
+                        * tasklet is the only thing that pulls the
+                        * messages.
                         */
+                       list_add(&smi_msg->link, &intf->waiting_rcv_msgs);
                        break;
                } else {
-                       list_del(&smi_msg->link);
                        if (rv == 0)
                                /* Message handled */
                                ipmi_free_smi_msg(smi_msg);
index 53ddba2..98efbfc 100644 (file)
@@ -175,6 +175,7 @@ config COMMON_CLK_KEYSTONE
 config COMMON_CLK_NXP
        def_bool COMMON_CLK && (ARCH_LPC18XX || ARCH_LPC32XX)
        select REGMAP_MMIO if ARCH_LPC32XX
+       select MFD_SYSCON if ARCH_LPC18XX
        ---help---
          Support for clock providers on NXP platforms.
 
index 020a29a..51f5438 100644 (file)
@@ -180,15 +180,15 @@ static int pic32mzda_clk_probe(struct platform_device *pdev)
 
        /* register fixed rate clocks */
        clks[POSCCLK] = clk_register_fixed_rate(&pdev->dev, "posc_clk", NULL,
-                                               CLK_IS_ROOT, 24000000);
+                                               0, 24000000);
        clks[FRCCLK] =  clk_register_fixed_rate(&pdev->dev, "frc_clk", NULL,
-                                               CLK_IS_ROOT, 8000000);
+                                               0, 8000000);
        clks[BFRCCLK] = clk_register_fixed_rate(&pdev->dev, "bfrc_clk", NULL,
-                                               CLK_IS_ROOT, 8000000);
+                                               0, 8000000);
        clks[LPRCCLK] = clk_register_fixed_rate(&pdev->dev, "lprc_clk", NULL,
-                                               CLK_IS_ROOT, 32000);
+                                               0, 32000);
        clks[UPLLCLK] = clk_register_fixed_rate(&pdev->dev, "usbphy_clk", NULL,
-                                               CLK_IS_ROOT, 24000000);
+                                               0, 24000000);
        /* fixed rate (optional) clock */
        if (of_find_property(np, "microchip,pic32mzda-sosc", NULL)) {
                pr_info("pic32-clk: dt requests SOSC.\n");
index 36bc11a..9009295 100644 (file)
@@ -1832,7 +1832,7 @@ EXPORT_SYMBOL(cpufreq_unregister_notifier);
 unsigned int cpufreq_driver_fast_switch(struct cpufreq_policy *policy,
                                        unsigned int target_freq)
 {
-       clamp_val(target_freq, policy->min, policy->max);
+       target_freq = clamp_val(target_freq, policy->min, policy->max);
 
        return cpufreq_driver->fast_switch(policy, target_freq);
 }
index 3a9c432..fe9dc17 100644 (file)
@@ -372,26 +372,9 @@ static bool intel_pstate_get_ppc_enable_status(void)
        return acpi_ppc;
 }
 
-/*
- * The max target pstate ratio is a 8 bit value in both PLATFORM_INFO MSR and
- * in TURBO_RATIO_LIMIT MSR, which pstate driver stores in max_pstate and
- * max_turbo_pstate fields. The PERF_CTL MSR contains 16 bit value for P state
- * ratio, out of it only high 8 bits are used. For example 0x1700 is setting
- * target ratio 0x17. The _PSS control value stores in a format which can be
- * directly written to PERF_CTL MSR. But in intel_pstate driver this shift
- * occurs during write to PERF_CTL (E.g. for cores core_set_pstate()).
- * This function converts the _PSS control value to intel pstate driver format
- * for comparison and assignment.
- */
-static int convert_to_native_pstate_format(struct cpudata *cpu, int index)
-{
-       return cpu->acpi_perf_data.states[index].control >> 8;
-}
-
 static void intel_pstate_init_acpi_perf_limits(struct cpufreq_policy *policy)
 {
        struct cpudata *cpu;
-       int turbo_pss_ctl;
        int ret;
        int i;
 
@@ -441,15 +424,14 @@ static void intel_pstate_init_acpi_perf_limits(struct cpufreq_policy *policy)
         * max frequency, which will cause a reduced performance as
         * this driver uses real max turbo frequency as the max
         * frequency. So correct this frequency in _PSS table to
-        * correct max turbo frequency based on the turbo ratio.
+        * correct max turbo frequency based on the turbo state.
         * Also need to convert to MHz as _PSS freq is in MHz.
         */
-       turbo_pss_ctl = convert_to_native_pstate_format(cpu, 0);
-       if (turbo_pss_ctl > cpu->pstate.max_pstate)
+       if (!limits->turbo_disabled)
                cpu->acpi_perf_data.states[0].core_frequency =
                                        policy->cpuinfo.max_freq / 1000;
        cpu->valid_pss_table = true;
-       pr_info("_PPC limits will be enforced\n");
+       pr_debug("_PPC limits will be enforced\n");
 
        return;
 
@@ -1460,6 +1442,9 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
 
        intel_pstate_clear_update_util_hook(policy->cpu);
 
+       pr_debug("set_policy cpuinfo.max %u policy->max %u\n",
+                policy->cpuinfo.max_freq, policy->max);
+
        cpu = all_cpu_data[0];
        if (cpu->pstate.max_pstate_physical > cpu->pstate.max_pstate &&
            policy->max < policy->cpuinfo.max_freq &&
@@ -1495,13 +1480,13 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
                                   limits->max_sysfs_pct);
        limits->max_perf_pct = max(limits->min_policy_pct,
                                   limits->max_perf_pct);
-       limits->max_perf = round_up(limits->max_perf, FRAC_BITS);
 
        /* Make sure min_perf_pct <= max_perf_pct */
        limits->min_perf_pct = min(limits->max_perf_pct, limits->min_perf_pct);
 
        limits->min_perf = div_fp(limits->min_perf_pct, 100);
        limits->max_perf = div_fp(limits->max_perf_pct, 100);
+       limits->max_perf = round_up(limits->max_perf, FRAC_BITS);
 
  out:
        intel_pstate_set_update_util_hook(policy->cpu);
@@ -1558,8 +1543,11 @@ static int intel_pstate_cpu_init(struct cpufreq_policy *policy)
 
        /* cpuinfo and default policy values */
        policy->cpuinfo.min_freq = cpu->pstate.min_pstate * cpu->pstate.scaling;
-       policy->cpuinfo.max_freq =
-               cpu->pstate.turbo_pstate * cpu->pstate.scaling;
+       update_turbo_state();
+       policy->cpuinfo.max_freq = limits->turbo_disabled ?
+                       cpu->pstate.max_pstate : cpu->pstate.turbo_pstate;
+       policy->cpuinfo.max_freq *= cpu->pstate.scaling;
+
        intel_pstate_init_acpi_perf_limits(policy);
        policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
        cpumask_set_cpu(policy->cpu, policy->cpus);
index 808a320..a7ecb9a 100644 (file)
@@ -487,7 +487,7 @@ static int __init pcc_cpufreq_probe(void)
        doorbell.space_id = reg_resource->space_id;
        doorbell.bit_width = reg_resource->bit_width;
        doorbell.bit_offset = reg_resource->bit_offset;
-       doorbell.access_width = 64;
+       doorbell.access_width = 4;
        doorbell.address = reg_resource->address;
 
        pr_debug("probe: doorbell: space_id is %d, bit_width is %d, "
index 52c7395..0d0d452 100644 (file)
@@ -122,6 +122,7 @@ static int ccp_aes_xts_crypt(struct ablkcipher_request *req,
        struct ccp_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
        struct ccp_aes_req_ctx *rctx = ablkcipher_request_ctx(req);
        unsigned int unit;
+       u32 unit_size;
        int ret;
 
        if (!ctx->u.aes.key_len)
@@ -133,11 +134,17 @@ static int ccp_aes_xts_crypt(struct ablkcipher_request *req,
        if (!req->info)
                return -EINVAL;
 
-       for (unit = 0; unit < ARRAY_SIZE(unit_size_map); unit++)
-               if (!(req->nbytes & (unit_size_map[unit].size - 1)))
-                       break;
+       unit_size = CCP_XTS_AES_UNIT_SIZE__LAST;
+       if (req->nbytes <= unit_size_map[0].size) {
+               for (unit = 0; unit < ARRAY_SIZE(unit_size_map); unit++) {
+                       if (!(req->nbytes & (unit_size_map[unit].size - 1))) {
+                               unit_size = unit_size_map[unit].value;
+                               break;
+                       }
+               }
+       }
 
-       if ((unit_size_map[unit].value == CCP_XTS_AES_UNIT_SIZE__LAST) ||
+       if ((unit_size == CCP_XTS_AES_UNIT_SIZE__LAST) ||
            (ctx->u.aes.key_len != AES_KEYSIZE_128)) {
                /* Use the fallback to process the request for any
                 * unsupported unit sizes or key sizes
@@ -158,7 +165,7 @@ static int ccp_aes_xts_crypt(struct ablkcipher_request *req,
        rctx->cmd.engine = CCP_ENGINE_XTS_AES_128;
        rctx->cmd.u.xts.action = (encrypt) ? CCP_AES_ACTION_ENCRYPT
                                           : CCP_AES_ACTION_DECRYPT;
-       rctx->cmd.u.xts.unit_size = unit_size_map[unit].value;
+       rctx->cmd.u.xts.unit_size = unit_size;
        rctx->cmd.u.xts.key = &ctx->u.aes.key_sg;
        rctx->cmd.u.xts.key_len = ctx->u.aes.key_len;
        rctx->cmd.u.xts.iv = &rctx->iv_sg;
index 6eefaa2..63464e8 100644 (file)
@@ -1986,7 +1986,7 @@ err_algs:
                                        &dd->pdata->algs_info[i].algs_list[j]);
 err_pm:
        pm_runtime_disable(dev);
-       if (dd->polling_mode)
+       if (!dd->polling_mode)
                dma_release_channel(dd->dma_lch);
 data_err:
        dev_err(dev, "initialization failed.\n");
index 1d6c803..e92418f 100644 (file)
@@ -268,8 +268,11 @@ int update_devfreq(struct devfreq *devfreq)
        devfreq_notify_transition(devfreq, &freqs, DEVFREQ_PRECHANGE);
 
        err = devfreq->profile->target(devfreq->dev.parent, &freq, flags);
-       if (err)
+       if (err) {
+               freqs.new = cur_freq;
+               devfreq_notify_transition(devfreq, &freqs, DEVFREQ_POSTCHANGE);
                return err;
+       }
 
        freqs.new = freq;
        devfreq_notify_transition(devfreq, &freqs, DEVFREQ_POSTCHANGE);
@@ -552,6 +555,7 @@ struct devfreq *devfreq_add_device(struct device *dev,
        devfreq->profile = profile;
        strncpy(devfreq->governor_name, governor_name, DEVFREQ_NAME_LEN);
        devfreq->previous_freq = profile->initial_freq;
+       devfreq->last_status.current_frequency = profile->initial_freq;
        devfreq->data = data;
        devfreq->nb.notifier_call = devfreq_notifier_call;
 
@@ -561,23 +565,22 @@ struct devfreq *devfreq_add_device(struct device *dev,
                mutex_lock(&devfreq->lock);
        }
 
-       devfreq->trans_table =  devm_kzalloc(dev, sizeof(unsigned int) *
-                                               devfreq->profile->max_state *
-                                               devfreq->profile->max_state,
-                                               GFP_KERNEL);
-       devfreq->time_in_state = devm_kzalloc(dev, sizeof(unsigned long) *
-                                               devfreq->profile->max_state,
-                                               GFP_KERNEL);
-       devfreq->last_stat_updated = jiffies;
-
        dev_set_name(&devfreq->dev, "%s", dev_name(dev));
        err = device_register(&devfreq->dev);
        if (err) {
-               put_device(&devfreq->dev);
                mutex_unlock(&devfreq->lock);
                goto err_out;
        }
 
+       devfreq->trans_table =  devm_kzalloc(&devfreq->dev, sizeof(unsigned int) *
+                                               devfreq->profile->max_state *
+                                               devfreq->profile->max_state,
+                                               GFP_KERNEL);
+       devfreq->time_in_state = devm_kzalloc(&devfreq->dev, sizeof(unsigned long) *
+                                               devfreq->profile->max_state,
+                                               GFP_KERNEL);
+       devfreq->last_stat_updated = jiffies;
+
        srcu_init_notifier_head(&devfreq->transition_notifier_list);
 
        mutex_unlock(&devfreq->lock);
@@ -603,7 +606,6 @@ struct devfreq *devfreq_add_device(struct device *dev,
 err_init:
        list_del(&devfreq->node);
        device_unregister(&devfreq->dev);
-       kfree(devfreq);
 err_out:
        return ERR_PTR(err);
 }
@@ -621,7 +623,6 @@ int devfreq_remove_device(struct devfreq *devfreq)
                return -EINVAL;
 
        device_unregister(&devfreq->dev);
-       put_device(&devfreq->dev);
 
        return 0;
 }
index 6b6a5f3..a584140 100644 (file)
@@ -220,9 +220,6 @@ static int exynos_nocp_parse_dt(struct platform_device *pdev,
 
        /* Maps the memory mapped IO to control nocp register */
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (IS_ERR(res))
-               return PTR_ERR(res);
-
        base = devm_ioremap_resource(dev, res);
        if (IS_ERR(base))
                return PTR_ERR(base);
index 4a2c07e..6355ab3 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/seq_file.h>
 #include <linux/poll.h>
 #include <linux/reservation.h>
+#include <linux/mm.h>
 
 #include <uapi/linux/dma-buf.h>
 
@@ -90,7 +91,7 @@ static int dma_buf_mmap_internal(struct file *file, struct vm_area_struct *vma)
        dmabuf = file->private_data;
 
        /* check for overflowing the buffer's size */
-       if (vma->vm_pgoff + ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) >
+       if (vma->vm_pgoff + vma_pages(vma) >
            dmabuf->size >> PAGE_SHIFT)
                return -EINVAL;
 
@@ -723,11 +724,11 @@ int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma,
                return -EINVAL;
 
        /* check for offset overflow */
-       if (pgoff + ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) < pgoff)
+       if (pgoff + vma_pages(vma) < pgoff)
                return -EOVERFLOW;
 
        /* check for overflowing the buffer's size */
-       if (pgoff + ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) >
+       if (pgoff + vma_pages(vma) >
            dmabuf->size >> PAGE_SHIFT)
                return -EINVAL;
 
index c0bd572..9566a62 100644 (file)
 #include <linux/reservation.h>
 #include <linux/export.h>
 
+/**
+ * DOC: Reservation Object Overview
+ *
+ * The reservation object provides a mechanism to manage shared and
+ * exclusive fences associated with a buffer.  A reservation object
+ * can have attached one exclusive fence (normally associated with
+ * write operations) or N shared fences (read operations).  The RCU
+ * mechanism is used to protect read access to fences from locked
+ * write-side updates.
+ */
+
 DEFINE_WW_CLASS(reservation_ww_class);
 EXPORT_SYMBOL(reservation_ww_class);
 
@@ -43,9 +54,17 @@ EXPORT_SYMBOL(reservation_seqcount_class);
 
 const char reservation_seqcount_string[] = "reservation_seqcount";
 EXPORT_SYMBOL(reservation_seqcount_string);
-/*
- * Reserve space to add a shared fence to a reservation_object,
- * must be called with obj->lock held.
+
+/**
+ * reservation_object_reserve_shared - Reserve space to add a shared
+ * fence to a reservation_object.
+ * @obj: reservation object
+ *
+ * Should be called before reservation_object_add_shared_fence().  Must
+ * be called with obj->lock held.
+ *
+ * RETURNS
+ * Zero for success, or -errno
  */
 int reservation_object_reserve_shared(struct reservation_object *obj)
 {
@@ -180,7 +199,11 @@ done:
                fence_put(old_fence);
 }
 
-/*
+/**
+ * reservation_object_add_shared_fence - Add a fence to a shared slot
+ * @obj: the reservation object
+ * @fence: the shared fence to add
+ *
  * Add a fence to a shared slot, obj->lock must be held, and
  * reservation_object_reserve_shared_fence has been called.
  */
@@ -200,6 +223,13 @@ void reservation_object_add_shared_fence(struct reservation_object *obj,
 }
 EXPORT_SYMBOL(reservation_object_add_shared_fence);
 
+/**
+ * reservation_object_add_excl_fence - Add an exclusive fence.
+ * @obj: the reservation object
+ * @fence: the shared fence to add
+ *
+ * Add a fence to the exclusive slot.  The obj->lock must be held.
+ */
 void reservation_object_add_excl_fence(struct reservation_object *obj,
                                       struct fence *fence)
 {
@@ -233,6 +263,18 @@ void reservation_object_add_excl_fence(struct reservation_object *obj,
 }
 EXPORT_SYMBOL(reservation_object_add_excl_fence);
 
+/**
+ * reservation_object_get_fences_rcu - Get an object's shared and exclusive
+ * fences without update side lock held
+ * @obj: the reservation object
+ * @pfence_excl: the returned exclusive fence (or NULL)
+ * @pshared_count: the number of shared fences returned
+ * @pshared: the array of shared fence ptrs returned (array is krealloc'd to
+ * the required size, and must be freed by caller)
+ *
+ * RETURNS
+ * Zero or -errno
+ */
 int reservation_object_get_fences_rcu(struct reservation_object *obj,
                                      struct fence **pfence_excl,
                                      unsigned *pshared_count,
@@ -319,6 +361,18 @@ unlock:
 }
 EXPORT_SYMBOL_GPL(reservation_object_get_fences_rcu);
 
+/**
+ * reservation_object_wait_timeout_rcu - Wait on reservation's objects
+ * shared and/or exclusive fences.
+ * @obj: the reservation object
+ * @wait_all: if true, wait on all fences, else wait on just exclusive fence
+ * @intr: if true, do interruptible wait
+ * @timeout: timeout value in jiffies or zero to return immediately
+ *
+ * RETURNS
+ * Returns -ERESTARTSYS if interrupted, 0 if the wait timed out, or
+ * greater than zer on success.
+ */
 long reservation_object_wait_timeout_rcu(struct reservation_object *obj,
                                         bool wait_all, bool intr,
                                         unsigned long timeout)
@@ -416,6 +470,16 @@ reservation_object_test_signaled_single(struct fence *passed_fence)
        return ret;
 }
 
+/**
+ * reservation_object_test_signaled_rcu - Test if a reservation object's
+ * fences have been signaled.
+ * @obj: the reservation object
+ * @test_all: if true, test all fences, otherwise only test the exclusive
+ * fence
+ *
+ * RETURNS
+ * true if all fences signaled, else false
+ */
 bool reservation_object_test_signaled_rcu(struct reservation_object *obj,
                                          bool test_all)
 {
index 8e304b1..75bd662 100644 (file)
@@ -242,7 +242,7 @@ struct at_xdmac_lld {
        u32             mbr_dus;        /* Destination Microblock Stride Register */
 };
 
-
+/* 64-bit alignment needed to update CNDA and CUBC registers in an atomic way. */
 struct at_xdmac_desc {
        struct at_xdmac_lld             lld;
        enum dma_transfer_direction     direction;
@@ -253,7 +253,7 @@ struct at_xdmac_desc {
        unsigned int                    xfer_size;
        struct list_head                descs_list;
        struct list_head                xfer_node;
-};
+} __aligned(sizeof(u64));
 
 static inline void __iomem *at_xdmac_chan_reg_base(struct at_xdmac *atxdmac, unsigned int chan_nb)
 {
@@ -1400,6 +1400,7 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
        u32                     cur_nda, check_nda, cur_ubc, mask, value;
        u8                      dwidth = 0;
        unsigned long           flags;
+       bool                    initd;
 
        ret = dma_cookie_status(chan, cookie, txstate);
        if (ret == DMA_COMPLETE)
@@ -1424,7 +1425,16 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
        residue = desc->xfer_size;
        /*
         * Flush FIFO: only relevant when the transfer is source peripheral
-        * synchronized.
+        * synchronized. Flush is needed before reading CUBC because data in
+        * the FIFO are not reported by CUBC. Reporting a residue of the
+        * transfer length while we have data in FIFO can cause issue.
+        * Usecase: atmel USART has a timeout which means I have received
+        * characters but there is no more character received for a while. On
+        * timeout, it requests the residue. If the data are in the DMA FIFO,
+        * we will return a residue of the transfer length. It means no data
+        * received. If an application is waiting for these data, it will hang
+        * since we won't have another USART timeout without receiving new
+        * data.
         */
        mask = AT_XDMAC_CC_TYPE | AT_XDMAC_CC_DSYNC;
        value = AT_XDMAC_CC_TYPE_PER_TRAN | AT_XDMAC_CC_DSYNC_PER2MEM;
@@ -1435,34 +1445,43 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
        }
 
        /*
-        * When processing the residue, we need to read two registers but we
-        * can't do it in an atomic way. AT_XDMAC_CNDA is used to find where
-        * we stand in the descriptor list and AT_XDMAC_CUBC is used
-        * to know how many data are remaining for the current descriptor.
-        * Since the dma channel is not paused to not loose data, between the
-        * AT_XDMAC_CNDA and AT_XDMAC_CUBC read, we may have change of
-        * descriptor.
-        * For that reason, after reading AT_XDMAC_CUBC, we check if we are
-        * still using the same descriptor by reading a second time
-        * AT_XDMAC_CNDA. If AT_XDMAC_CNDA has changed, it means we have to
-        * read again AT_XDMAC_CUBC.
+        * The easiest way to compute the residue should be to pause the DMA
+        * but doing this can lead to miss some data as some devices don't
+        * have FIFO.
+        * We need to read several registers because:
+        * - DMA is running therefore a descriptor change is possible while
+        * reading these registers
+        * - When the block transfer is done, the value of the CUBC register
+        * is set to its initial value until the fetch of the next descriptor.
+        * This value will corrupt the residue calculation so we have to skip
+        * it.
+        *
+        * INITD --------                    ------------
+        *              |____________________|
+        *       _______________________  _______________
+        * NDA       @desc2             \/   @desc3
+        *       _______________________/\_______________
+        *       __________  ___________  _______________
+        * CUBC       0    \/ MAX desc1 \/  MAX desc2
+        *       __________/\___________/\_______________
+        *
+        * Since descriptors are aligned on 64 bits, we can assume that
+        * the update of NDA and CUBC is atomic.
         * Memory barriers are used to ensure the read order of the registers.
-        * A max number of retries is set because unlikely it can never ends if
-        * we are transferring a lot of data with small buffers.
+        * A max number of retries is set because unlikely it could never ends.
         */
-       cur_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc;
-       rmb();
-       cur_ubc = at_xdmac_chan_read(atchan, AT_XDMAC_CUBC);
        for (retry = 0; retry < AT_XDMAC_RESIDUE_MAX_RETRIES; retry++) {
-               rmb();
                check_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc;
-
-               if (likely(cur_nda == check_nda))
-                       break;
-
-               cur_nda = check_nda;
+               rmb();
+               initd = !!(at_xdmac_chan_read(atchan, AT_XDMAC_CC) & AT_XDMAC_CC_INITD);
                rmb();
                cur_ubc = at_xdmac_chan_read(atchan, AT_XDMAC_CUBC);
+               rmb();
+               cur_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc;
+               rmb();
+
+               if ((check_nda == cur_nda) && initd)
+                       break;
        }
 
        if (unlikely(retry >= AT_XDMAC_RESIDUE_MAX_RETRIES)) {
@@ -1470,6 +1489,19 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
                goto spin_unlock;
        }
 
+       /*
+        * Flush FIFO: only relevant when the transfer is source peripheral
+        * synchronized. Another flush is needed here because CUBC is updated
+        * when the controller sends the data write command. It can lead to
+        * report data that are not written in the memory or the device. The
+        * FIFO flush ensures that data are really written.
+        */
+       if ((desc->lld.mbr_cfg & mask) == value) {
+               at_xdmac_write(atxdmac, AT_XDMAC_GSWF, atchan->mask);
+               while (!(at_xdmac_chan_read(atchan, AT_XDMAC_CIS) & AT_XDMAC_CIS_FIS))
+                       cpu_relax();
+       }
+
        /*
         * Remove size of all microblocks already transferred and the current
         * one. Then add the remaining size to transfer of the current
index 25d1dad..d0446a7 100644 (file)
@@ -703,8 +703,9 @@ static int mv_chan_memcpy_self_test(struct mv_xor_chan *mv_chan)
                goto free_resources;
        }
 
-       src_dma = dma_map_page(dma_chan->device->dev, virt_to_page(src), 0,
-                                PAGE_SIZE, DMA_TO_DEVICE);
+       src_dma = dma_map_page(dma_chan->device->dev, virt_to_page(src),
+                              (size_t)src & ~PAGE_MASK, PAGE_SIZE,
+                              DMA_TO_DEVICE);
        unmap->addr[0] = src_dma;
 
        ret = dma_mapping_error(dma_chan->device->dev, src_dma);
@@ -714,8 +715,9 @@ static int mv_chan_memcpy_self_test(struct mv_xor_chan *mv_chan)
        }
        unmap->to_cnt = 1;
 
-       dest_dma = dma_map_page(dma_chan->device->dev, virt_to_page(dest), 0,
-                                 PAGE_SIZE, DMA_FROM_DEVICE);
+       dest_dma = dma_map_page(dma_chan->device->dev, virt_to_page(dest),
+                               (size_t)dest & ~PAGE_MASK, PAGE_SIZE,
+                               DMA_FROM_DEVICE);
        unmap->addr[1] = dest_dma;
 
        ret = dma_mapping_error(dma_chan->device->dev, dest_dma);
index 6aa256b..c3ee3ad 100644 (file)
@@ -565,7 +565,8 @@ void edac_mc_reset_delay_period(unsigned long value)
        list_for_each(item, &mc_devices) {
                mci = list_entry(item, struct mem_ctl_info, link);
 
-               edac_mod_work(&mci->work, value);
+               if (mci->op_state == OP_RUNNING_POLL)
+                       edac_mod_work(&mci->work, value);
        }
        mutex_unlock(&mem_ctls_mutex);
 }
index b4d0bf6..6744d88 100644 (file)
@@ -239,8 +239,11 @@ static const u32 rir_offset[MAX_RIR_RANGES][MAX_RIR_WAY] = {
        { 0x1a0, 0x1a4, 0x1a8, 0x1ac, 0x1b0, 0x1b4, 0x1b8, 0x1bc },
 };
 
-#define RIR_RNK_TGT(reg)               GET_BITFIELD(reg, 16, 19)
-#define RIR_OFFSET(reg)                GET_BITFIELD(reg,  2, 14)
+#define RIR_RNK_TGT(type, reg) (((type) == BROADWELL) ? \
+       GET_BITFIELD(reg, 20, 23) : GET_BITFIELD(reg, 16, 19))
+
+#define RIR_OFFSET(type, reg) (((type) == HASWELL || (type) == BROADWELL) ? \
+       GET_BITFIELD(reg,  2, 15) : GET_BITFIELD(reg,  2, 14))
 
 /* Device 16, functions 2-7 */
 
@@ -326,6 +329,7 @@ struct pci_id_descr {
 struct pci_id_table {
        const struct pci_id_descr       *descr;
        int                             n_devs;
+       enum type                       type;
 };
 
 struct sbridge_dev {
@@ -394,9 +398,14 @@ static const struct pci_id_descr pci_dev_descr_sbridge[] = {
        { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_BR, 0)          },
 };
 
-#define PCI_ID_TABLE_ENTRY(A) { .descr=A, .n_devs = ARRAY_SIZE(A) }
+#define PCI_ID_TABLE_ENTRY(A, T) {     \
+       .descr = A,                     \
+       .n_devs = ARRAY_SIZE(A),        \
+       .type = T                       \
+}
+
 static const struct pci_id_table pci_dev_descr_sbridge_table[] = {
-       PCI_ID_TABLE_ENTRY(pci_dev_descr_sbridge),
+       PCI_ID_TABLE_ENTRY(pci_dev_descr_sbridge, SANDY_BRIDGE),
        {0,}                    /* 0 terminated list. */
 };
 
@@ -463,7 +472,7 @@ static const struct pci_id_descr pci_dev_descr_ibridge[] = {
 };
 
 static const struct pci_id_table pci_dev_descr_ibridge_table[] = {
-       PCI_ID_TABLE_ENTRY(pci_dev_descr_ibridge),
+       PCI_ID_TABLE_ENTRY(pci_dev_descr_ibridge, IVY_BRIDGE),
        {0,}                    /* 0 terminated list. */
 };
 
@@ -536,7 +545,7 @@ static const struct pci_id_descr pci_dev_descr_haswell[] = {
 };
 
 static const struct pci_id_table pci_dev_descr_haswell_table[] = {
-       PCI_ID_TABLE_ENTRY(pci_dev_descr_haswell),
+       PCI_ID_TABLE_ENTRY(pci_dev_descr_haswell, HASWELL),
        {0,}                    /* 0 terminated list. */
 };
 
@@ -580,7 +589,7 @@ static const struct pci_id_descr pci_dev_descr_knl[] = {
 };
 
 static const struct pci_id_table pci_dev_descr_knl_table[] = {
-       PCI_ID_TABLE_ENTRY(pci_dev_descr_knl),
+       PCI_ID_TABLE_ENTRY(pci_dev_descr_knl, KNIGHTS_LANDING),
        {0,}
 };
 
@@ -648,7 +657,7 @@ static const struct pci_id_descr pci_dev_descr_broadwell[] = {
 };
 
 static const struct pci_id_table pci_dev_descr_broadwell_table[] = {
-       PCI_ID_TABLE_ENTRY(pci_dev_descr_broadwell),
+       PCI_ID_TABLE_ENTRY(pci_dev_descr_broadwell, BROADWELL),
        {0,}                    /* 0 terminated list. */
 };
 
@@ -1894,14 +1903,14 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
                                pci_read_config_dword(pvt->pci_tad[i],
                                                      rir_offset[j][k],
                                                      &reg);
-                               tmp_mb = RIR_OFFSET(reg) << 6;
+                               tmp_mb = RIR_OFFSET(pvt->info.type, reg) << 6;
 
                                gb = div_u64_rem(tmp_mb, 1024, &mb);
                                edac_dbg(0, "CH#%d RIR#%d INTL#%d, offset %u.%03u GB (0x%016Lx), tgt: %d, reg=0x%08x\n",
                                         i, j, k,
                                         gb, (mb*1000)/1024,
                                         ((u64)tmp_mb) << 20L,
-                                        (u32)RIR_RNK_TGT(reg),
+                                        (u32)RIR_RNK_TGT(pvt->info.type, reg),
                                         reg);
                        }
                }
@@ -2234,7 +2243,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
        pci_read_config_dword(pvt->pci_tad[ch_add + base_ch],
                              rir_offset[n_rir][idx],
                              &reg);
-       *rank = RIR_RNK_TGT(reg);
+       *rank = RIR_RNK_TGT(pvt->info.type, reg);
 
        edac_dbg(0, "RIR#%d: channel address 0x%08Lx < 0x%08Lx, RIR interleave %d, index %d\n",
                 n_rir,
@@ -3357,12 +3366,12 @@ fail0:
 #define ICPU(model, table) \
        { X86_VENDOR_INTEL, 6, model, 0, (unsigned long)&table }
 
-/* Order here must match "enum type" */
 static const struct x86_cpu_id sbridge_cpuids[] = {
        ICPU(0x2d, pci_dev_descr_sbridge_table),        /* SANDY_BRIDGE */
        ICPU(0x3e, pci_dev_descr_ibridge_table),        /* IVY_BRIDGE */
        ICPU(0x3f, pci_dev_descr_haswell_table),        /* HASWELL */
        ICPU(0x4f, pci_dev_descr_broadwell_table),      /* BROADWELL */
+       ICPU(0x56, pci_dev_descr_broadwell_table),      /* BROADWELL-DE */
        ICPU(0x57, pci_dev_descr_knl_table),            /* KNIGHTS_LANDING */
        { }
 };
@@ -3398,7 +3407,7 @@ static int sbridge_probe(const struct x86_cpu_id *id)
                         mc, mc + 1, num_mc);
 
                sbridge_dev->mc = mc++;
-               rc = sbridge_register_mci(sbridge_dev, id - sbridge_cpuids);
+               rc = sbridge_register_mci(sbridge_dev, ptable->type);
                if (unlikely(rc < 0))
                        goto fail1;
        }
index 8b3226d..caff46c 100644 (file)
@@ -360,6 +360,8 @@ static int palmas_usb_probe(struct platform_device *pdev)
 
        palmas_enable_irq(palmas_usb);
        /* perform initial detection */
+       if (palmas_usb->enable_gpio_vbus_detection)
+               palmas_vbus_irq_handler(palmas_usb->gpio_vbus_irq, palmas_usb);
        palmas_gpio_id_detect(&palmas_usb->wq_detectid.work);
        device_set_wakeup_capable(&pdev->dev, true);
        return 0;
index a850cbc..c49d50e 100644 (file)
@@ -174,6 +174,7 @@ static __init void reserve_regions(void)
 {
        efi_memory_desc_t *md;
        u64 paddr, npages, size;
+       int resv;
 
        if (efi_enabled(EFI_DBG))
                pr_info("Processing EFI memory map:\n");
@@ -190,12 +191,14 @@ static __init void reserve_regions(void)
                paddr = md->phys_addr;
                npages = md->num_pages;
 
+               resv = is_reserve_region(md);
                if (efi_enabled(EFI_DBG)) {
                        char buf[64];
 
-                       pr_info("  0x%012llx-0x%012llx %s",
+                       pr_info("  0x%012llx-0x%012llx %s%s\n",
                                paddr, paddr + (npages << EFI_PAGE_SHIFT) - 1,
-                               efi_md_typeattr_format(buf, sizeof(buf), md));
+                               efi_md_typeattr_format(buf, sizeof(buf), md),
+                               resv ? "*" : "");
                }
 
                memrange_efi_to_native(&paddr, &npages);
@@ -204,14 +207,9 @@ static __init void reserve_regions(void)
                if (is_normal_ram(md))
                        early_init_dt_add_memory_arch(paddr, size);
 
-               if (is_reserve_region(md)) {
+               if (resv)
                        memblock_mark_nomap(paddr, size);
-                       if (efi_enabled(EFI_DBG))
-                               pr_cont("*");
-               }
 
-               if (efi_enabled(EFI_DBG))
-                       pr_cont("\n");
        }
 
        set_bit(EFI_MEMMAP, &efi.flags);
index 48da857..cebcb40 100644 (file)
@@ -33,6 +33,7 @@ config ARCH_REQUIRE_GPIOLIB
 
 menuconfig GPIOLIB
        bool "GPIO Support"
+       select ANON_INODES
        help
          This enables GPIO support through the generic GPIO library.
          You only need to enable this, if you also want to enable
@@ -530,7 +531,7 @@ menu "Port-mapped I/O GPIO drivers"
 
 config GPIO_104_DIO_48E
        tristate "ACCES 104-DIO-48E GPIO support"
-       depends on ISA
+       depends on ISA_BUS_API
        select GPIOLIB_IRQCHIP
        help
          Enables GPIO support for the ACCES 104-DIO-48E series (104-DIO-48E,
@@ -540,7 +541,7 @@ config GPIO_104_DIO_48E
 
 config GPIO_104_IDIO_16
        tristate "ACCES 104-IDIO-16 GPIO support"
-       depends on ISA
+       depends on ISA_BUS_API
        select GPIOLIB_IRQCHIP
        help
          Enables GPIO support for the ACCES 104-IDIO-16 family (104-IDIO-16,
@@ -551,7 +552,7 @@ config GPIO_104_IDIO_16
 
 config GPIO_104_IDI_48
        tristate "ACCES 104-IDI-48 GPIO support"
-       depends on ISA
+       depends on ISA_BUS_API
        select GPIOLIB_IRQCHIP
        help
          Enables GPIO support for the ACCES 104-IDI-48 family (104-IDI-48A,
@@ -627,7 +628,7 @@ config GPIO_TS5500
 
 config GPIO_WS16C48
        tristate "WinSystems WS16C48 GPIO support"
-       depends on ISA
+       depends on ISA_BUS_API
        select GPIOLIB_IRQCHIP
        help
          Enables GPIO support for the WinSystems WS16C48. The base port
index 1a647c0..fcf7769 100644 (file)
@@ -75,7 +75,7 @@ static int dio48e_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
 {
        struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip);
        const unsigned io_port = offset / 8;
-       const unsigned control_port = io_port / 2;
+       const unsigned int control_port = io_port / 3;
        const unsigned control_addr = dio48egpio->base + 3 + control_port*4;
        unsigned long flags;
        unsigned control;
@@ -115,7 +115,7 @@ static int dio48e_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
 {
        struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip);
        const unsigned io_port = offset / 8;
-       const unsigned control_port = io_port / 2;
+       const unsigned int control_port = io_port / 3;
        const unsigned mask = BIT(offset % 8);
        const unsigned control_addr = dio48egpio->base + 3 + control_port*4;
        const unsigned out_port = (io_port > 2) ? io_port + 1 : io_port;
index 6c75c83..2d2763e 100644 (file)
@@ -247,6 +247,7 @@ static int idi_48_probe(struct device *dev, unsigned int id)
        idi48gpio->irq = irq[id];
 
        spin_lock_init(&idi48gpio->lock);
+       spin_lock_init(&idi48gpio->ack_lock);
 
        dev_set_drvdata(dev, idi48gpio);
 
index 9aabc48..953e4b8 100644 (file)
@@ -547,11 +547,11 @@ static void bcm_kona_gpio_reset(struct bcm_kona_gpio *kona_gpio)
        /* disable interrupts and clear status */
        for (i = 0; i < kona_gpio->num_bank; i++) {
                /* Unlock the entire bank first */
-               bcm_kona_gpio_write_lock_regs(kona_gpio, i, UNLOCK_CODE);
+               bcm_kona_gpio_write_lock_regs(reg_base, i, UNLOCK_CODE);
                writel(0xffffffff, reg_base + GPIO_INT_MASK(i));
                writel(0xffffffff, reg_base + GPIO_INT_STATUS(i));
                /* Now re-lock the bank */
-               bcm_kona_gpio_write_lock_regs(kona_gpio, i, LOCK_CODE);
+               bcm_kona_gpio_write_lock_regs(reg_base, i, LOCK_CODE);
        }
 }
 
index d39014d..fc5f197 100644 (file)
@@ -29,7 +29,6 @@
 
 #include <mach/hardware.h>
 #include <mach/platform.h>
-#include <mach/irqs.h>
 
 #define LPC32XX_GPIO_P3_INP_STATE              _GPREG(0x000)
 #define LPC32XX_GPIO_P3_OUTP_SET               _GPREG(0x004)
@@ -371,61 +370,16 @@ static int lpc32xx_gpio_request(struct gpio_chip *chip, unsigned pin)
 
 static int lpc32xx_gpio_to_irq_p01(struct gpio_chip *chip, unsigned offset)
 {
-       return IRQ_LPC32XX_P0_P1_IRQ;
+       return -ENXIO;
 }
 
-static const char lpc32xx_gpio_to_irq_gpio_p3_table[] = {
-       IRQ_LPC32XX_GPIO_00,
-       IRQ_LPC32XX_GPIO_01,
-       IRQ_LPC32XX_GPIO_02,
-       IRQ_LPC32XX_GPIO_03,
-       IRQ_LPC32XX_GPIO_04,
-       IRQ_LPC32XX_GPIO_05,
-};
-
 static int lpc32xx_gpio_to_irq_gpio_p3(struct gpio_chip *chip, unsigned offset)
 {
-       if (offset < ARRAY_SIZE(lpc32xx_gpio_to_irq_gpio_p3_table))
-               return lpc32xx_gpio_to_irq_gpio_p3_table[offset];
        return -ENXIO;
 }
 
-static const char lpc32xx_gpio_to_irq_gpi_p3_table[] = {
-       IRQ_LPC32XX_GPI_00,
-       IRQ_LPC32XX_GPI_01,
-       IRQ_LPC32XX_GPI_02,
-       IRQ_LPC32XX_GPI_03,
-       IRQ_LPC32XX_GPI_04,
-       IRQ_LPC32XX_GPI_05,
-       IRQ_LPC32XX_GPI_06,
-       IRQ_LPC32XX_GPI_07,
-       IRQ_LPC32XX_GPI_08,
-       IRQ_LPC32XX_GPI_09,
-       -ENXIO, /* 10 */
-       -ENXIO, /* 11 */
-       -ENXIO, /* 12 */
-       -ENXIO, /* 13 */
-       -ENXIO, /* 14 */
-       -ENXIO, /* 15 */
-       -ENXIO, /* 16 */
-       -ENXIO, /* 17 */
-       -ENXIO, /* 18 */
-       IRQ_LPC32XX_GPI_19,
-       -ENXIO, /* 20 */
-       -ENXIO, /* 21 */
-       -ENXIO, /* 22 */
-       -ENXIO, /* 23 */
-       -ENXIO, /* 24 */
-       -ENXIO, /* 25 */
-       -ENXIO, /* 26 */
-       -ENXIO, /* 27 */
-       IRQ_LPC32XX_GPI_28,
-};
-
 static int lpc32xx_gpio_to_irq_gpi_p3(struct gpio_chip *chip, unsigned offset)
 {
-       if (offset < ARRAY_SIZE(lpc32xx_gpio_to_irq_gpi_p3_table))
-               return lpc32xx_gpio_to_irq_gpi_p3_table[offset];
        return -ENXIO;
 }
 
index 75c6355..e72794e 100644 (file)
@@ -709,7 +709,13 @@ static int zynq_gpio_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "input clock not found.\n");
                return PTR_ERR(gpio->clk);
        }
+       ret = clk_prepare_enable(gpio->clk);
+       if (ret) {
+               dev_err(&pdev->dev, "Unable to enable clock.\n");
+               return ret;
+       }
 
+       pm_runtime_set_active(&pdev->dev);
        pm_runtime_enable(&pdev->dev);
        ret = pm_runtime_get_sync(&pdev->dev);
        if (ret < 0)
@@ -747,6 +753,7 @@ err_pm_put:
        pm_runtime_put(&pdev->dev);
 err_pm_dis:
        pm_runtime_disable(&pdev->dev);
+       clk_disable_unprepare(gpio->clk);
 
        return ret;
 }
index d22dcc3..4aabddb 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/errno.h>
 #include <linux/module.h>
 #include <linux/io.h>
+#include <linux/io-mapping.h>
 #include <linux/gpio/consumer.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
index d407f90..570771e 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/cdev.h>
 #include <linux/fs.h>
 #include <linux/uaccess.h>
+#include <linux/compat.h>
 #include <uapi/linux/gpio.h>
 
 #include "gpiolib.h"
@@ -316,7 +317,7 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
        struct gpio_device *gdev = filp->private_data;
        struct gpio_chip *chip = gdev->chip;
-       int __user *ip = (int __user *)arg;
+       void __user *ip = (void __user *)arg;
 
        /* We fail any subsequent ioctl():s when the chip is gone */
        if (!chip)
@@ -388,6 +389,14 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
        return -EINVAL;
 }
 
+#ifdef CONFIG_COMPAT
+static long gpio_ioctl_compat(struct file *filp, unsigned int cmd,
+                             unsigned long arg)
+{
+       return gpio_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
+}
+#endif
+
 /**
  * gpio_chrdev_open() - open the chardev for ioctl operations
  * @inode: inode for this chardev
@@ -431,14 +440,15 @@ static const struct file_operations gpio_fileops = {
        .owner = THIS_MODULE,
        .llseek = noop_llseek,
        .unlocked_ioctl = gpio_ioctl,
-       .compat_ioctl = gpio_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = gpio_ioctl_compat,
+#endif
 };
 
 static void gpiodevice_release(struct device *dev)
 {
        struct gpio_device *gdev = dev_get_drvdata(dev);
 
-       cdev_del(&gdev->chrdev);
        list_del(&gdev->list);
        ida_simple_remove(&gpio_ida, gdev->id);
        kfree(gdev->label);
@@ -471,7 +481,6 @@ static int gpiochip_setup_dev(struct gpio_device *gdev)
 
        /* From this point, the .release() function cleans up gpio_device */
        gdev->dev.release = gpiodevice_release;
-       get_device(&gdev->dev);
        pr_debug("%s: registered GPIOs %d to %d on device: %s (%s)\n",
                 __func__, gdev->base, gdev->base + gdev->ngpio - 1,
                 dev_name(&gdev->dev), gdev->chip->label ? : "generic");
@@ -618,6 +627,8 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data)
                goto err_free_label;
        }
 
+       spin_unlock_irqrestore(&gpio_lock, flags);
+
        for (i = 0; i < chip->ngpio; i++) {
                struct gpio_desc *desc = &gdev->descs[i];
 
@@ -649,8 +660,6 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data)
                }
        }
 
-       spin_unlock_irqrestore(&gpio_lock, flags);
-
 #ifdef CONFIG_PINCTRL
        INIT_LIST_HEAD(&gdev->pin_ranges);
 #endif
@@ -759,6 +768,8 @@ void gpiochip_remove(struct gpio_chip *chip)
         * be removed, else it will be dangling until the last user is
         * gone.
         */
+       cdev_del(&gdev->chrdev);
+       device_del(&gdev->dev);
        put_device(&gdev->dev);
 }
 EXPORT_SYMBOL_GPL(gpiochip_remove);
@@ -858,7 +869,7 @@ struct gpio_chip *gpiochip_find(void *data,
 
        spin_lock_irqsave(&gpio_lock, flags);
        list_for_each_entry(gdev, &gpio_devices, list)
-               if (match(gdev->chip, data))
+               if (gdev->chip && match(gdev->chip, data))
                        break;
 
        /* No match? */
@@ -1356,11 +1367,18 @@ done:
 /*
  * This descriptor validation needs to be inserted verbatim into each
  * function taking a descriptor, so we need to use a preprocessor
- * macro to avoid endless duplication.
+ * macro to avoid endless duplication. If the desc is NULL it is an
+ * optional GPIO and calls should just bail out.
  */
 #define VALIDATE_DESC(desc) do { \
-       if (!desc || !desc->gdev) { \
-               pr_warn("%s: invalid GPIO\n", __func__); \
+       if (!desc) \
+               return 0; \
+       if (IS_ERR(desc)) {                                             \
+               pr_warn("%s: invalid GPIO (errorpointer)\n", __func__); \
+               return PTR_ERR(desc); \
+       } \
+       if (!desc->gdev) { \
+               pr_warn("%s: invalid GPIO (no device)\n", __func__); \
                return -EINVAL; \
        } \
        if ( !desc->gdev->chip ) { \
@@ -1370,8 +1388,14 @@ done:
        } } while (0)
 
 #define VALIDATE_DESC_VOID(desc) do { \
-       if (!desc || !desc->gdev) { \
-               pr_warn("%s: invalid GPIO\n", __func__); \
+       if (!desc) \
+               return; \
+       if (IS_ERR(desc)) {                                             \
+               pr_warn("%s: invalid GPIO (errorpointer)\n", __func__); \
+               return; \
+       } \
+       if (!desc->gdev) { \
+               pr_warn("%s: invalid GPIO (no device)\n", __func__); \
                return; \
        } \
        if (!desc->gdev->chip) { \
@@ -2040,7 +2064,14 @@ int gpiod_to_irq(const struct gpio_desc *desc)
        struct gpio_chip *chip;
        int offset;
 
-       VALIDATE_DESC(desc);
+       /*
+        * Cannot VALIDATE_DESC() here as gpiod_to_irq() consumer semantics
+        * requires this function to not return zero on an invalid descriptor
+        * but rather a negative error number.
+        */
+       if (!desc || IS_ERR(desc) || !desc->gdev || !desc->gdev->chip)
+               return -EINVAL;
+
        chip = desc->gdev->chip;
        offset = gpio_chip_hwgpio(desc);
        if (chip->to_irq) {
@@ -2066,17 +2097,30 @@ EXPORT_SYMBOL_GPL(gpiod_to_irq);
  */
 int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset)
 {
-       if (offset >= chip->ngpio)
-               return -EINVAL;
+       struct gpio_desc *desc;
+
+       desc = gpiochip_get_desc(chip, offset);
+       if (IS_ERR(desc))
+               return PTR_ERR(desc);
+
+       /* Flush direction if something changed behind our back */
+       if (chip->get_direction) {
+               int dir = chip->get_direction(chip, offset);
+
+               if (dir)
+                       clear_bit(FLAG_IS_OUT, &desc->flags);
+               else
+                       set_bit(FLAG_IS_OUT, &desc->flags);
+       }
 
-       if (test_bit(FLAG_IS_OUT, &chip->gpiodev->descs[offset].flags)) {
+       if (test_bit(FLAG_IS_OUT, &desc->flags)) {
                chip_err(chip,
                          "%s: tried to flag a GPIO set as output for IRQ\n",
                          __func__);
                return -EIO;
        }
 
-       set_bit(FLAG_USED_AS_IRQ, &chip->gpiodev->descs[offset].flags);
+       set_bit(FLAG_USED_AS_IRQ, &desc->flags);
        return 0;
 }
 EXPORT_SYMBOL_GPL(gpiochip_lock_as_irq);
index 992f00b..e055d5b 100644 (file)
@@ -1820,6 +1820,8 @@ struct amdgpu_asic_funcs {
        /* MM block clocks */
        int (*set_uvd_clocks)(struct amdgpu_device *adev, u32 vclk, u32 dclk);
        int (*set_vce_clocks)(struct amdgpu_device *adev, u32 evclk, u32 ecclk);
+       /* query virtual capabilities */
+       u32 (*get_virtual_caps)(struct amdgpu_device *adev);
 };
 
 /*
@@ -1914,8 +1916,12 @@ void amdgpu_cgs_destroy_device(struct cgs_device *cgs_device);
 
 
 /* GPU virtualization */
+#define AMDGPU_VIRT_CAPS_SRIOV_EN       (1 << 0)
+#define AMDGPU_VIRT_CAPS_IS_VF          (1 << 1)
 struct amdgpu_virtualization {
        bool supports_sr_iov;
+       bool is_virtual;
+       u32 caps;
 };
 
 /*
@@ -2204,6 +2210,7 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring)
 #define amdgpu_asic_get_xclk(adev) (adev)->asic_funcs->get_xclk((adev))
 #define amdgpu_asic_set_uvd_clocks(adev, v, d) (adev)->asic_funcs->set_uvd_clocks((adev), (v), (d))
 #define amdgpu_asic_set_vce_clocks(adev, ev, ec) (adev)->asic_funcs->set_vce_clocks((adev), (ev), (ec))
+#define amdgpu_asic_get_virtual_caps(adev) ((adev)->asic_funcs->get_virtual_caps((adev)))
 #define amdgpu_asic_get_gpu_clock_counter(adev) (adev)->asic_funcs->get_gpu_clock_counter((adev))
 #define amdgpu_asic_read_disabled_bios(adev) (adev)->asic_funcs->read_disabled_bios((adev))
 #define amdgpu_asic_read_bios_from_rom(adev, b, l) (adev)->asic_funcs->read_bios_from_rom((adev), (b), (l))
index 199f76b..cf6f49f 100644 (file)
@@ -696,6 +696,17 @@ static uint32_t fw_type_convert(struct cgs_device *cgs_device, uint32_t fw_type)
        return result;
 }
 
+static int amdgpu_cgs_rel_firmware(struct cgs_device *cgs_device, enum cgs_ucode_id type)
+{
+       CGS_FUNC_ADEV;
+       if ((CGS_UCODE_ID_SMU == type) || (CGS_UCODE_ID_SMU_SK == type)) {
+               release_firmware(adev->pm.fw);
+               return 0;
+       }
+       /* cannot release other firmware because they are not created by cgs */
+       return -EINVAL;
+}
+
 static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device,
                                        enum cgs_ucode_id type,
                                        struct cgs_firmware_info *info)
@@ -898,7 +909,7 @@ static int amdgpu_cgs_acpi_eval_object(struct cgs_device *cgs_device,
        struct cgs_acpi_method_argument *argument = NULL;
        uint32_t i, count;
        acpi_status status;
-       int result;
+       int result = 0;
        uint32_t func_no = 0xFFFFFFFF;
 
        handle = ACPI_HANDLE(&adev->pdev->dev);
@@ -1125,6 +1136,7 @@ static const struct cgs_ops amdgpu_cgs_ops = {
        amdgpu_cgs_pm_query_clock_limits,
        amdgpu_cgs_set_camera_voltages,
        amdgpu_cgs_get_firmware_info,
+       amdgpu_cgs_rel_firmware,
        amdgpu_cgs_set_powergating_state,
        amdgpu_cgs_set_clockgating_state,
        amdgpu_cgs_get_active_displays_info,
index bb8b149..6e92008 100644 (file)
@@ -827,8 +827,10 @@ static uint32_t cail_ioreg_read(struct card_info *info, uint32_t reg)
  */
 static void amdgpu_atombios_fini(struct amdgpu_device *adev)
 {
-       if (adev->mode_info.atom_context)
+       if (adev->mode_info.atom_context) {
                kfree(adev->mode_info.atom_context->scratch);
+               kfree(adev->mode_info.atom_context->iio);
+       }
        kfree(adev->mode_info.atom_context);
        adev->mode_info.atom_context = NULL;
        kfree(adev->mode_info.atom_card_info);
@@ -1325,6 +1327,11 @@ static int amdgpu_fini(struct amdgpu_device *adev)
                adev->ip_block_status[i].valid = false;
        }
 
+       for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
+               if (adev->ip_blocks[i].funcs->late_fini)
+                       adev->ip_blocks[i].funcs->late_fini((void *)adev);
+       }
+
        return 0;
 }
 
@@ -1378,6 +1385,15 @@ static int amdgpu_resume(struct amdgpu_device *adev)
        return 0;
 }
 
+static bool amdgpu_device_is_virtual(void)
+{
+#ifdef CONFIG_X86
+       return boot_cpu_has(X86_FEATURE_HYPERVISOR);
+#else
+       return false;
+#endif
+}
+
 /**
  * amdgpu_device_init - initialize the driver
  *
@@ -1512,9 +1528,14 @@ int amdgpu_device_init(struct amdgpu_device *adev,
        adev->virtualization.supports_sr_iov =
                amdgpu_atombios_has_gpu_virtualization_table(adev);
 
+       /* Check if we are executing in a virtualized environment */
+       adev->virtualization.is_virtual = amdgpu_device_is_virtual();
+       adev->virtualization.caps = amdgpu_asic_get_virtual_caps(adev);
+
        /* Post card if necessary */
        if (!amdgpu_card_posted(adev) ||
-           adev->virtualization.supports_sr_iov) {
+           (adev->virtualization.is_virtual &&
+            !(adev->virtualization.caps & AMDGPU_VIRT_CAPS_SRIOV_EN))) {
                if (!adev->bios) {
                        dev_err(adev->dev, "Card not posted and no BIOS - ignoring\n");
                        return -EINVAL;
index 40a2370..d851ea1 100644 (file)
@@ -447,7 +447,8 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
                        dev_info.max_memory_clock = adev->pm.default_mclk * 10;
                }
                dev_info.enabled_rb_pipes_mask = adev->gfx.config.backend_enable_mask;
-               dev_info.num_rb_pipes = adev->gfx.config.num_rbs;
+               dev_info.num_rb_pipes = adev->gfx.config.max_backends_per_se *
+                       adev->gfx.config.max_shader_engines;
                dev_info.num_hw_gfx_contexts = adev->gfx.config.max_hw_contexts;
                dev_info._pad = 0;
                dev_info.ids_flags = 0;
index 589b36e..0e13d80 100644 (file)
@@ -270,30 +270,28 @@ static ssize_t amdgpu_set_pp_force_state(struct device *dev,
        struct drm_device *ddev = dev_get_drvdata(dev);
        struct amdgpu_device *adev = ddev->dev_private;
        enum amd_pm_state_type state = 0;
-       long idx;
+       unsigned long idx;
        int ret;
 
        if (strlen(buf) == 1)
                adev->pp_force_state_enabled = false;
-       else {
-               ret = kstrtol(buf, 0, &idx);
+       else if (adev->pp_enabled) {
+               struct pp_states_info data;
 
-               if (ret) {
+               ret = kstrtoul(buf, 0, &idx);
+               if (ret || idx >= ARRAY_SIZE(data.states)) {
                        count = -EINVAL;
                        goto fail;
                }
 
-               if (adev->pp_enabled) {
-                       struct pp_states_info data;
-                       amdgpu_dpm_get_pp_num_states(adev, &data);
-                       state = data.states[idx];
-                       /* only set user selected power states */
-                       if (state != POWER_STATE_TYPE_INTERNAL_BOOT &&
-                               state != POWER_STATE_TYPE_DEFAULT) {
-                               amdgpu_dpm_dispatch_task(adev,
-                                               AMD_PP_EVENT_ENABLE_USER_STATE, &state, NULL);
-                               adev->pp_force_state_enabled = true;
-                       }
+               amdgpu_dpm_get_pp_num_states(adev, &data);
+               state = data.states[idx];
+               /* only set user selected power states */
+               if (state != POWER_STATE_TYPE_INTERNAL_BOOT &&
+                   state != POWER_STATE_TYPE_DEFAULT) {
+                       amdgpu_dpm_dispatch_task(adev,
+                                       AMD_PP_EVENT_ENABLE_USER_STATE, &state, NULL);
+                       adev->pp_force_state_enabled = true;
                }
        }
 fail:
index 6bd961f..8225655 100644 (file)
@@ -183,13 +183,6 @@ static int amdgpu_pp_sw_fini(void *handle)
        if (ret)
                return ret;
 
-#ifdef CONFIG_DRM_AMD_POWERPLAY
-       if (adev->pp_enabled) {
-               amdgpu_pm_sysfs_fini(adev);
-               amd_powerplay_fini(adev->powerplay.pp_handle);
-       }
-#endif
-
        return ret;
 }
 
@@ -223,6 +216,22 @@ static int amdgpu_pp_hw_fini(void *handle)
        return ret;
 }
 
+static void amdgpu_pp_late_fini(void *handle)
+{
+#ifdef CONFIG_DRM_AMD_POWERPLAY
+       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+       if (adev->pp_enabled) {
+               amdgpu_pm_sysfs_fini(adev);
+               amd_powerplay_fini(adev->powerplay.pp_handle);
+       }
+
+       if (adev->powerplay.ip_funcs->late_fini)
+               adev->powerplay.ip_funcs->late_fini(
+                         adev->powerplay.pp_handle);
+#endif
+}
+
 static int amdgpu_pp_suspend(void *handle)
 {
        int ret = 0;
@@ -311,6 +320,7 @@ const struct amd_ip_funcs amdgpu_pp_ip_funcs = {
        .sw_fini = amdgpu_pp_sw_fini,
        .hw_init = amdgpu_pp_hw_init,
        .hw_fini = amdgpu_pp_hw_fini,
+       .late_fini = amdgpu_pp_late_fini,
        .suspend = amdgpu_pp_suspend,
        .resume = amdgpu_pp_resume,
        .is_idle = amdgpu_pp_is_idle,
index 3b02272..870f949 100644 (file)
@@ -343,6 +343,7 @@ void amdgpu_ring_fini(struct amdgpu_ring *ring)
        ring->ring = NULL;
        ring->ring_obj = NULL;
 
+       amdgpu_wb_free(ring->adev, ring->cond_exe_offs);
        amdgpu_wb_free(ring->adev, ring->fence_offs);
        amdgpu_wb_free(ring->adev, ring->rptr_offs);
        amdgpu_wb_free(ring->adev, ring->wptr_offs);
index 8bf84ef..48618ee 100644 (file)
@@ -115,6 +115,7 @@ int amdgpu_sa_bo_manager_start(struct amdgpu_device *adev,
                return r;
        }
        r = amdgpu_bo_kmap(sa_manager->bo, &sa_manager->cpu_ptr);
+       memset(sa_manager->cpu_ptr, 0, sa_manager->size);
        amdgpu_bo_unreserve(sa_manager->bo);
        return r;
 }
index 01abfc2..e19520c 100644 (file)
@@ -253,19 +253,20 @@ int amdgpu_uvd_sw_fini(struct amdgpu_device *adev)
 {
        int r;
 
-       if (adev->uvd.vcpu_bo == NULL)
-               return 0;
+       kfree(adev->uvd.saved_bo);
 
        amd_sched_entity_fini(&adev->uvd.ring.sched, &adev->uvd.entity);
 
-       r = amdgpu_bo_reserve(adev->uvd.vcpu_bo, false);
-       if (!r) {
-               amdgpu_bo_kunmap(adev->uvd.vcpu_bo);
-               amdgpu_bo_unpin(adev->uvd.vcpu_bo);
-               amdgpu_bo_unreserve(adev->uvd.vcpu_bo);
-       }
+       if (adev->uvd.vcpu_bo) {
+               r = amdgpu_bo_reserve(adev->uvd.vcpu_bo, false);
+               if (!r) {
+                       amdgpu_bo_kunmap(adev->uvd.vcpu_bo);
+                       amdgpu_bo_unpin(adev->uvd.vcpu_bo);
+                       amdgpu_bo_unreserve(adev->uvd.vcpu_bo);
+               }
 
-       amdgpu_bo_unref(&adev->uvd.vcpu_bo);
+               amdgpu_bo_unref(&adev->uvd.vcpu_bo);
+       }
 
        amdgpu_ring_fini(&adev->uvd.ring);
 
index ea407db..5ec1f1e 100644 (file)
@@ -6221,6 +6221,9 @@ static int ci_dpm_sw_fini(void *handle)
        ci_dpm_fini(adev);
        mutex_unlock(&adev->pm.mutex);
 
+       release_firmware(adev->pm.fw);
+       adev->pm.fw = NULL;
+
        return 0;
 }
 
index 07bc795..9104318 100644 (file)
@@ -962,6 +962,12 @@ static bool cik_read_bios_from_rom(struct amdgpu_device *adev,
        return true;
 }
 
+static u32 cik_get_virtual_caps(struct amdgpu_device *adev)
+{
+       /* CIK does not support SR-IOV */
+       return 0;
+}
+
 static const struct amdgpu_allowed_register_entry cik_allowed_read_registers[] = {
        {mmGRBM_STATUS, false},
        {mmGB_ADDR_CONFIG, false},
@@ -2007,6 +2013,7 @@ static const struct amdgpu_asic_funcs cik_asic_funcs =
        .get_xclk = &cik_get_xclk,
        .set_uvd_clocks = &cik_set_uvd_clocks,
        .set_vce_clocks = &cik_set_vce_clocks,
+       .get_virtual_caps = &cik_get_virtual_caps,
        /* these should be moved to their own ip modules */
        .get_gpu_clock_counter = &gfx_v7_0_get_gpu_clock_counter,
        .wait_for_mc_idle = &gmc_v7_0_mc_wait_for_idle,
index 518dca4..9dc4e24 100644 (file)
@@ -66,6 +66,16 @@ MODULE_FIRMWARE("radeon/mullins_sdma1.bin");
 
 u32 amdgpu_cik_gpu_check_soft_reset(struct amdgpu_device *adev);
 
+
+static void cik_sdma_free_microcode(struct amdgpu_device *adev)
+{
+       int i;
+       for (i = 0; i < adev->sdma.num_instances; i++) {
+                       release_firmware(adev->sdma.instance[i].fw);
+                       adev->sdma.instance[i].fw = NULL;
+       }
+}
+
 /*
  * sDMA - System DMA
  * Starting with CIK, the GPU has new asynchronous
@@ -419,6 +429,8 @@ static int cik_sdma_gfx_resume(struct amdgpu_device *adev)
                /* Initialize the ring buffer's read and write pointers */
                WREG32(mmSDMA0_GFX_RB_RPTR + sdma_offsets[i], 0);
                WREG32(mmSDMA0_GFX_RB_WPTR + sdma_offsets[i], 0);
+               WREG32(mmSDMA0_GFX_IB_RPTR + sdma_offsets[i], 0);
+               WREG32(mmSDMA0_GFX_IB_OFFSET + sdma_offsets[i], 0);
 
                /* set the wb address whether it's enabled or not */
                WREG32(mmSDMA0_GFX_RB_RPTR_ADDR_HI + sdma_offsets[i],
@@ -446,7 +458,12 @@ static int cik_sdma_gfx_resume(struct amdgpu_device *adev)
                WREG32(mmSDMA0_GFX_IB_CNTL + sdma_offsets[i], ib_cntl);
 
                ring->ready = true;
+       }
+
+       cik_sdma_enable(adev, true);
 
+       for (i = 0; i < adev->sdma.num_instances; i++) {
+               ring = &adev->sdma.instance[i].ring;
                r = amdgpu_ring_test_ring(ring);
                if (r) {
                        ring->ready = false;
@@ -529,8 +546,8 @@ static int cik_sdma_start(struct amdgpu_device *adev)
        if (r)
                return r;
 
-       /* unhalt the MEs */
-       cik_sdma_enable(adev, true);
+       /* halt the engine before programing */
+       cik_sdma_enable(adev, false);
 
        /* start the gfx rings and rlc compute queues */
        r = cik_sdma_gfx_resume(adev);
@@ -998,6 +1015,7 @@ static int cik_sdma_sw_fini(void *handle)
        for (i = 0; i < adev->sdma.num_instances; i++)
                amdgpu_ring_fini(&adev->sdma.instance[i].ring);
 
+       cik_sdma_free_microcode(adev);
        return 0;
 }
 
index 245cabf..ed03b75 100644 (file)
@@ -72,6 +72,11 @@ static int fiji_dpm_sw_init(void *handle)
 
 static int fiji_dpm_sw_fini(void *handle)
 {
+       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+       release_firmware(adev->pm.fw);
+       adev->pm.fw = NULL;
+
        return 0;
 }
 
index 7f18a53..fc8ff4d 100644 (file)
@@ -991,6 +991,22 @@ out:
        return err;
 }
 
+static void gfx_v7_0_free_microcode(struct amdgpu_device *adev)
+{
+       release_firmware(adev->gfx.pfp_fw);
+       adev->gfx.pfp_fw = NULL;
+       release_firmware(adev->gfx.me_fw);
+       adev->gfx.me_fw = NULL;
+       release_firmware(adev->gfx.ce_fw);
+       adev->gfx.ce_fw = NULL;
+       release_firmware(adev->gfx.mec_fw);
+       adev->gfx.mec_fw = NULL;
+       release_firmware(adev->gfx.mec2_fw);
+       adev->gfx.mec2_fw = NULL;
+       release_firmware(adev->gfx.rlc_fw);
+       adev->gfx.rlc_fw = NULL;
+}
+
 /**
  * gfx_v7_0_tiling_mode_table_init - init the hw tiling table
  *
@@ -4489,6 +4505,7 @@ static int gfx_v7_0_sw_fini(void *handle)
        gfx_v7_0_cp_compute_fini(adev);
        gfx_v7_0_rlc_fini(adev);
        gfx_v7_0_mec_fini(adev);
+       gfx_v7_0_free_microcode(adev);
 
        return 0;
 }
@@ -4816,7 +4833,7 @@ static int gfx_v7_0_eop_irq(struct amdgpu_device *adev,
        case 2:
                for (i = 0; i < adev->gfx.num_compute_rings; i++) {
                        ring = &adev->gfx.compute_ring[i];
-                       if ((ring->me == me_id) & (ring->pipe == pipe_id))
+                       if ((ring->me == me_id) && (ring->pipe == pipe_id))
                                amdgpu_fence_process(ring);
                }
                break;
index f19bab6..1a5cbaf 100644 (file)
@@ -297,7 +297,8 @@ static const u32 polaris11_golden_common_all[] =
 static const u32 golden_settings_polaris10_a11[] =
 {
        mmATC_MISC_CG, 0x000c0fc0, 0x000c0200,
-       mmCB_HW_CONTROL, 0xfffdf3cf, 0x00006208,
+       mmCB_HW_CONTROL, 0xfffdf3cf, 0x00007208,
+       mmCB_HW_CONTROL_2, 0, 0x0f000000,
        mmCB_HW_CONTROL_3, 0x000001ff, 0x00000040,
        mmDB_DEBUG2, 0xf00fffff, 0x00000400,
        mmPA_SC_ENHANCE, 0xffffffff, 0x20000001,
@@ -836,6 +837,26 @@ err1:
        return r;
 }
 
+
+static void gfx_v8_0_free_microcode(struct amdgpu_device *adev) {
+       release_firmware(adev->gfx.pfp_fw);
+       adev->gfx.pfp_fw = NULL;
+       release_firmware(adev->gfx.me_fw);
+       adev->gfx.me_fw = NULL;
+       release_firmware(adev->gfx.ce_fw);
+       adev->gfx.ce_fw = NULL;
+       release_firmware(adev->gfx.rlc_fw);
+       adev->gfx.rlc_fw = NULL;
+       release_firmware(adev->gfx.mec_fw);
+       adev->gfx.mec_fw = NULL;
+       if ((adev->asic_type != CHIP_STONEY) &&
+           (adev->asic_type != CHIP_TOPAZ))
+               release_firmware(adev->gfx.mec2_fw);
+       adev->gfx.mec2_fw = NULL;
+
+       kfree(adev->gfx.rlc.register_list_format);
+}
+
 static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)
 {
        const char *chip_name;
@@ -1983,7 +2004,7 @@ static int gfx_v8_0_sw_fini(void *handle)
 
        gfx_v8_0_rlc_fini(adev);
 
-       kfree(adev->gfx.rlc.register_list_format);
+       gfx_v8_0_free_microcode(adev);
 
        return 0;
 }
@@ -3974,11 +3995,15 @@ static int gfx_v8_0_cp_gfx_start(struct amdgpu_device *adev)
                amdgpu_ring_write(ring, 0x3a00161a);
                amdgpu_ring_write(ring, 0x0000002e);
                break;
-       case CHIP_TOPAZ:
        case CHIP_CARRIZO:
                amdgpu_ring_write(ring, 0x00000002);
                amdgpu_ring_write(ring, 0x00000000);
                break;
+       case CHIP_TOPAZ:
+               amdgpu_ring_write(ring, adev->gfx.config.num_rbs == 1 ?
+                               0x00000000 : 0x00000002);
+               amdgpu_ring_write(ring, 0x00000000);
+               break;
        case CHIP_STONEY:
                amdgpu_ring_write(ring, 0x00000000);
                amdgpu_ring_write(ring, 0x00000000);
index 460bc8a..825ccd6 100644 (file)
@@ -72,6 +72,11 @@ static int iceland_dpm_sw_init(void *handle)
 
 static int iceland_dpm_sw_fini(void *handle)
 {
+       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+       release_firmware(adev->pm.fw);
+       adev->pm.fw = NULL;
+
        return 0;
 }
 
index f4c3130..b556bd0 100644 (file)
@@ -105,6 +105,15 @@ static void sdma_v2_4_init_golden_registers(struct amdgpu_device *adev)
        }
 }
 
+static void sdma_v2_4_free_microcode(struct amdgpu_device *adev)
+{
+       int i;
+       for (i = 0; i < adev->sdma.num_instances; i++) {
+               release_firmware(adev->sdma.instance[i].fw);
+               adev->sdma.instance[i].fw = NULL;
+       }
+}
+
 /**
  * sdma_v2_4_init_microcode - load ucode images from disk
  *
@@ -461,6 +470,8 @@ static int sdma_v2_4_gfx_resume(struct amdgpu_device *adev)
                /* Initialize the ring buffer's read and write pointers */
                WREG32(mmSDMA0_GFX_RB_RPTR + sdma_offsets[i], 0);
                WREG32(mmSDMA0_GFX_RB_WPTR + sdma_offsets[i], 0);
+               WREG32(mmSDMA0_GFX_IB_RPTR + sdma_offsets[i], 0);
+               WREG32(mmSDMA0_GFX_IB_OFFSET + sdma_offsets[i], 0);
 
                /* set the wb address whether it's enabled or not */
                WREG32(mmSDMA0_GFX_RB_RPTR_ADDR_HI + sdma_offsets[i],
@@ -489,7 +500,11 @@ static int sdma_v2_4_gfx_resume(struct amdgpu_device *adev)
                WREG32(mmSDMA0_GFX_IB_CNTL + sdma_offsets[i], ib_cntl);
 
                ring->ready = true;
+       }
 
+       sdma_v2_4_enable(adev, true);
+       for (i = 0; i < adev->sdma.num_instances; i++) {
+               ring = &adev->sdma.instance[i].ring;
                r = amdgpu_ring_test_ring(ring);
                if (r) {
                        ring->ready = false;
@@ -580,8 +595,8 @@ static int sdma_v2_4_start(struct amdgpu_device *adev)
                        return -EINVAL;
        }
 
-       /* unhalt the MEs */
-       sdma_v2_4_enable(adev, true);
+       /* halt the engine before programing */
+       sdma_v2_4_enable(adev, false);
 
        /* start the gfx rings and rlc compute queues */
        r = sdma_v2_4_gfx_resume(adev);
@@ -1012,6 +1027,7 @@ static int sdma_v2_4_sw_fini(void *handle)
        for (i = 0; i < adev->sdma.num_instances; i++)
                amdgpu_ring_fini(&adev->sdma.instance[i].ring);
 
+       sdma_v2_4_free_microcode(adev);
        return 0;
 }
 
index 31d99b0..532ea88 100644 (file)
@@ -236,6 +236,15 @@ static void sdma_v3_0_init_golden_registers(struct amdgpu_device *adev)
        }
 }
 
+static void sdma_v3_0_free_microcode(struct amdgpu_device *adev)
+{
+       int i;
+       for (i = 0; i < adev->sdma.num_instances; i++) {
+               release_firmware(adev->sdma.instance[i].fw);
+               adev->sdma.instance[i].fw = NULL;
+       }
+}
+
 /**
  * sdma_v3_0_init_microcode - load ucode images from disk
  *
@@ -672,6 +681,8 @@ static int sdma_v3_0_gfx_resume(struct amdgpu_device *adev)
                /* Initialize the ring buffer's read and write pointers */
                WREG32(mmSDMA0_GFX_RB_RPTR + sdma_offsets[i], 0);
                WREG32(mmSDMA0_GFX_RB_WPTR + sdma_offsets[i], 0);
+               WREG32(mmSDMA0_GFX_IB_RPTR + sdma_offsets[i], 0);
+               WREG32(mmSDMA0_GFX_IB_OFFSET + sdma_offsets[i], 0);
 
                /* set the wb address whether it's enabled or not */
                WREG32(mmSDMA0_GFX_RB_RPTR_ADDR_HI + sdma_offsets[i],
@@ -711,7 +722,15 @@ static int sdma_v3_0_gfx_resume(struct amdgpu_device *adev)
                WREG32(mmSDMA0_GFX_IB_CNTL + sdma_offsets[i], ib_cntl);
 
                ring->ready = true;
+       }
+
+       /* unhalt the MEs */
+       sdma_v3_0_enable(adev, true);
+       /* enable sdma ring preemption */
+       sdma_v3_0_ctx_switch_enable(adev, true);
 
+       for (i = 0; i < adev->sdma.num_instances; i++) {
+               ring = &adev->sdma.instance[i].ring;
                r = amdgpu_ring_test_ring(ring);
                if (r) {
                        ring->ready = false;
@@ -804,10 +823,9 @@ static int sdma_v3_0_start(struct amdgpu_device *adev)
                }
        }
 
-       /* unhalt the MEs */
-       sdma_v3_0_enable(adev, true);
-       /* enable sdma ring preemption */
-       sdma_v3_0_ctx_switch_enable(adev, true);
+       /* disble sdma engine before programing it */
+       sdma_v3_0_ctx_switch_enable(adev, false);
+       sdma_v3_0_enable(adev, false);
 
        /* start the gfx rings and rlc compute queues */
        r = sdma_v3_0_gfx_resume(adev);
@@ -1247,6 +1265,7 @@ static int sdma_v3_0_sw_fini(void *handle)
        for (i = 0; i < adev->sdma.num_instances; i++)
                amdgpu_ring_fini(&adev->sdma.instance[i].ring);
 
+       sdma_v3_0_free_microcode(adev);
        return 0;
 }
 
index b7615ce..f06f6f4 100644 (file)
@@ -71,6 +71,11 @@ static int tonga_dpm_sw_init(void *handle)
 
 static int tonga_dpm_sw_fini(void *handle)
 {
+       struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+       release_firmware(adev->pm.fw);
+       adev->pm.fw = NULL;
+
        return 0;
 }
 
index 2c88d0b..a65c960 100644 (file)
@@ -421,6 +421,20 @@ static bool vi_read_bios_from_rom(struct amdgpu_device *adev,
        return true;
 }
 
+static u32 vi_get_virtual_caps(struct amdgpu_device *adev)
+{
+       u32 caps = 0;
+       u32 reg = RREG32(mmBIF_IOV_FUNC_IDENTIFIER);
+
+       if (REG_GET_FIELD(reg, BIF_IOV_FUNC_IDENTIFIER, IOV_ENABLE))
+               caps |= AMDGPU_VIRT_CAPS_SRIOV_EN;
+
+       if (REG_GET_FIELD(reg, BIF_IOV_FUNC_IDENTIFIER, FUNC_IDENTIFIER))
+               caps |= AMDGPU_VIRT_CAPS_IS_VF;
+
+       return caps;
+}
+
 static const struct amdgpu_allowed_register_entry tonga_allowed_read_registers[] = {
        {mmGB_MACROTILE_MODE7, true},
 };
@@ -1118,6 +1132,7 @@ static const struct amdgpu_asic_funcs vi_asic_funcs =
        .get_xclk = &vi_get_xclk,
        .set_uvd_clocks = &vi_set_uvd_clocks,
        .set_vce_clocks = &vi_set_vce_clocks,
+       .get_virtual_caps = &vi_get_virtual_caps,
        /* these should be moved to their own ip modules */
        .get_gpu_clock_counter = &gfx_v8_0_get_gpu_clock_counter,
        .wait_for_mc_idle = &gmc_v8_0_mc_wait_for_idle,
index ac00579..7708d90 100644 (file)
@@ -242,13 +242,19 @@ static void kfd_process_notifier_release(struct mmu_notifier *mn,
        pqm_uninit(&p->pqm);
 
        /* Iterate over all process device data structure and check
-        * if we should reset all wavefronts */
-       list_for_each_entry(pdd, &p->per_device_data, per_device_list)
+        * if we should delete debug managers and reset all wavefronts
+        */
+       list_for_each_entry(pdd, &p->per_device_data, per_device_list) {
+               if ((pdd->dev->dbgmgr) &&
+                               (pdd->dev->dbgmgr->pasid == p->pasid))
+                       kfd_dbgmgr_destroy(pdd->dev->dbgmgr);
+
                if (pdd->reset_wavefronts) {
                        pr_warn("amdkfd: Resetting all wave fronts\n");
                        dbgdev_wave_reset_wavefronts(pdd->dev, p);
                        pdd->reset_wavefronts = false;
                }
+       }
 
        mutex_unlock(&p->mutex);
 
@@ -404,42 +410,52 @@ void kfd_unbind_process_from_device(struct kfd_dev *dev, unsigned int pasid)
 
        idx = srcu_read_lock(&kfd_processes_srcu);
 
+       /*
+        * Look for the process that matches the pasid. If there is no such
+        * process, we either released it in amdkfd's own notifier, or there
+        * is a bug. Unfortunately, there is no way to tell...
+        */
        hash_for_each_rcu(kfd_processes_table, i, p, kfd_processes)
-               if (p->pasid == pasid)
-                       break;
+               if (p->pasid == pasid) {
 
-       srcu_read_unlock(&kfd_processes_srcu, idx);
+                       srcu_read_unlock(&kfd_processes_srcu, idx);
 
-       BUG_ON(p->pasid != pasid);
+                       pr_debug("Unbinding process %d from IOMMU\n", pasid);
 
-       mutex_lock(&p->mutex);
+                       mutex_lock(&p->mutex);
 
-       if ((dev->dbgmgr) && (dev->dbgmgr->pasid == p->pasid))
-               kfd_dbgmgr_destroy(dev->dbgmgr);
+                       if ((dev->dbgmgr) && (dev->dbgmgr->pasid == p->pasid))
+                               kfd_dbgmgr_destroy(dev->dbgmgr);
 
-       pqm_uninit(&p->pqm);
+                       pqm_uninit(&p->pqm);
 
-       pdd = kfd_get_process_device_data(dev, p);
+                       pdd = kfd_get_process_device_data(dev, p);
 
-       if (!pdd) {
-               mutex_unlock(&p->mutex);
-               return;
-       }
+                       if (!pdd) {
+                               mutex_unlock(&p->mutex);
+                               return;
+                       }
 
-       if (pdd->reset_wavefronts) {
-               dbgdev_wave_reset_wavefronts(pdd->dev, p);
-               pdd->reset_wavefronts = false;
-       }
+                       if (pdd->reset_wavefronts) {
+                               dbgdev_wave_reset_wavefronts(pdd->dev, p);
+                               pdd->reset_wavefronts = false;
+                       }
 
-       /*
-        * Just mark pdd as unbound, because we still need it to call
-        * amd_iommu_unbind_pasid() in when the process exits.
-        * We don't call amd_iommu_unbind_pasid() here
-        * because the IOMMU called us.
-        */
-       pdd->bound = false;
+                       /*
+                        * Just mark pdd as unbound, because we still need it
+                        * to call amd_iommu_unbind_pasid() in when the
+                        * process exits.
+                        * We don't call amd_iommu_unbind_pasid() here
+                        * because the IOMMU called us.
+                        */
+                       pdd->bound = false;
 
-       mutex_unlock(&p->mutex);
+                       mutex_unlock(&p->mutex);
+
+                       return;
+               }
+
+       srcu_read_unlock(&kfd_processes_srcu, idx);
 }
 
 struct kfd_process_device *kfd_get_first_process_device_data(struct kfd_process *p)
index 74909e7..884c96f 100644 (file)
@@ -666,7 +666,7 @@ static ssize_t node_show(struct kobject *kobj, struct attribute *attr,
                        dev->node_props.simd_count);
 
        if (dev->mem_bank_count < dev->node_props.mem_banks_count) {
-               pr_warn("kfd: mem_banks_count truncated from %d to %d\n",
+               pr_info_once("kfd: mem_banks_count truncated from %d to %d\n",
                                dev->node_props.mem_banks_count,
                                dev->mem_bank_count);
                sysfs_show_32bit_prop(buffer, "mem_banks_count",
index 6080951..afce1ed 100644 (file)
@@ -157,6 +157,7 @@ struct amd_ip_funcs {
        int (*hw_init)(void *handle);
        /* tears down the hw state */
        int (*hw_fini)(void *handle);
+       void (*late_fini)(void *handle);
        /* handles IP specific hw/sw changes for suspend */
        int (*suspend)(void *handle);
        /* handles IP specific hw/sw changes for resume */
index 32f3e34..3493da5 100644 (file)
@@ -5538,6 +5538,78 @@ typedef struct  _ATOM_ASIC_PROFILING_INFO_V3_5
   ULONG  ulReserved[12];
 }ATOM_ASIC_PROFILING_INFO_V3_5;
 
+/* for Polars10/11 AVFS parameters */
+typedef struct  _ATOM_ASIC_PROFILING_INFO_V3_6
+{
+  ATOM_COMMON_TABLE_HEADER         asHeader;
+  ULONG  ulMaxVddc;
+  ULONG  ulMinVddc;
+  USHORT usLkgEuseIndex;
+  UCHAR  ucLkgEfuseBitLSB;
+  UCHAR  ucLkgEfuseLength;
+  ULONG  ulLkgEncodeLn_MaxDivMin;
+  ULONG  ulLkgEncodeMax;
+  ULONG  ulLkgEncodeMin;
+  EFUSE_LINEAR_FUNC_PARAM sRoFuse;
+  ULONG  ulEvvDefaultVddc;
+  ULONG  ulEvvNoCalcVddc;
+  ULONG  ulSpeed_Model;
+  ULONG  ulSM_A0;
+  ULONG  ulSM_A1;
+  ULONG  ulSM_A2;
+  ULONG  ulSM_A3;
+  ULONG  ulSM_A4;
+  ULONG  ulSM_A5;
+  ULONG  ulSM_A6;
+  ULONG  ulSM_A7;
+  UCHAR  ucSM_A0_sign;
+  UCHAR  ucSM_A1_sign;
+  UCHAR  ucSM_A2_sign;
+  UCHAR  ucSM_A3_sign;
+  UCHAR  ucSM_A4_sign;
+  UCHAR  ucSM_A5_sign;
+  UCHAR  ucSM_A6_sign;
+  UCHAR  ucSM_A7_sign;
+  ULONG  ulMargin_RO_a;
+  ULONG  ulMargin_RO_b;
+  ULONG  ulMargin_RO_c;
+  ULONG  ulMargin_fixed;
+  ULONG  ulMargin_Fmax_mean;
+  ULONG  ulMargin_plat_mean;
+  ULONG  ulMargin_Fmax_sigma;
+  ULONG  ulMargin_plat_sigma;
+  ULONG  ulMargin_DC_sigma;
+  ULONG  ulLoadLineSlop;
+  ULONG  ulaTDClimitPerDPM[8];
+  ULONG  ulaNoCalcVddcPerDPM[8];
+  ULONG  ulAVFS_meanNsigma_Acontant0;
+  ULONG  ulAVFS_meanNsigma_Acontant1;
+  ULONG  ulAVFS_meanNsigma_Acontant2;
+  USHORT usAVFS_meanNsigma_DC_tol_sigma;
+  USHORT usAVFS_meanNsigma_Platform_mean;
+  USHORT usAVFS_meanNsigma_Platform_sigma;
+  ULONG  ulGB_VDROOP_TABLE_CKSOFF_a0;
+  ULONG  ulGB_VDROOP_TABLE_CKSOFF_a1;
+  ULONG  ulGB_VDROOP_TABLE_CKSOFF_a2;
+  ULONG  ulGB_VDROOP_TABLE_CKSON_a0;
+  ULONG  ulGB_VDROOP_TABLE_CKSON_a1;
+  ULONG  ulGB_VDROOP_TABLE_CKSON_a2;
+  ULONG  ulAVFSGB_FUSE_TABLE_CKSOFF_m1;
+  USHORT usAVFSGB_FUSE_TABLE_CKSOFF_m2;
+  ULONG  ulAVFSGB_FUSE_TABLE_CKSOFF_b;
+  ULONG  ulAVFSGB_FUSE_TABLE_CKSON_m1;
+  USHORT usAVFSGB_FUSE_TABLE_CKSON_m2;
+  ULONG  ulAVFSGB_FUSE_TABLE_CKSON_b;
+  USHORT usMaxVoltage_0_25mv;
+  UCHAR  ucEnableGB_VDROOP_TABLE_CKSOFF;
+  UCHAR  ucEnableGB_VDROOP_TABLE_CKSON;
+  UCHAR  ucEnableGB_FUSE_TABLE_CKSOFF;
+  UCHAR  ucEnableGB_FUSE_TABLE_CKSON;
+  USHORT usPSM_Age_ComFactor;
+  UCHAR  ucEnableApplyAVFS_CKS_OFF_Voltage;
+  UCHAR  ucReserved;
+}ATOM_ASIC_PROFILING_INFO_V3_6;
+
 
 typedef struct _ATOM_SCLK_FCW_RANGE_ENTRY_V1{
   ULONG  ulMaxSclkFreq;
index a461e15..7464daf 100644 (file)
@@ -581,6 +581,9 @@ typedef int (*cgs_get_firmware_info)(struct cgs_device *cgs_device,
                                     enum cgs_ucode_id type,
                                     struct cgs_firmware_info *info);
 
+typedef int (*cgs_rel_firmware)(struct cgs_device *cgs_device,
+                                        enum cgs_ucode_id type);
+
 typedef int(*cgs_set_powergating_state)(struct cgs_device *cgs_device,
                                  enum amd_ip_block_type block_type,
                                  enum amd_powergating_state state);
@@ -645,6 +648,7 @@ struct cgs_ops {
        cgs_set_camera_voltages_t set_camera_voltages;
        /* Firmware Info */
        cgs_get_firmware_info get_firmware_info;
+       cgs_rel_firmware rel_firmware;
        /* cg pg interface*/
        cgs_set_powergating_state set_powergating_state;
        cgs_set_clockgating_state set_clockgating_state;
@@ -738,6 +742,8 @@ struct cgs_device
        CGS_CALL(set_camera_voltages,dev,mask,voltages)
 #define cgs_get_firmware_info(dev, type, info) \
        CGS_CALL(get_firmware_info, dev, type, info)
+#define cgs_rel_firmware(dev, type)    \
+       CGS_CALL(rel_firmware, dev, type)
 #define cgs_set_powergating_state(dev, block_type, state)      \
        CGS_CALL(set_powergating_state, dev, block_type, state)
 #define cgs_set_clockgating_state(dev, block_type, state)      \
index 8e345bf..e629f8a 100644 (file)
@@ -73,11 +73,14 @@ static int pp_sw_init(void *handle)
 
        ret = hwmgr->hwmgr_func->backend_init(hwmgr);
        if (ret)
-               goto err;
+               goto err1;
 
        pr_info("amdgpu: powerplay initialized\n");
 
        return 0;
+err1:
+       if (hwmgr->pptable_func->pptable_fini)
+               hwmgr->pptable_func->pptable_fini(hwmgr);
 err:
        pr_err("amdgpu: powerplay initialization failed\n");
        return ret;
@@ -100,6 +103,9 @@ static int pp_sw_fini(void *handle)
        if (hwmgr->hwmgr_func->backend_fini != NULL)
                ret = hwmgr->hwmgr_func->backend_fini(hwmgr);
 
+       if (hwmgr->pptable_func->pptable_fini)
+               hwmgr->pptable_func->pptable_fini(hwmgr);
+
        return ret;
 }
 
index 46410e3..fb88e4e 100644 (file)
@@ -58,9 +58,6 @@ static void pem_fini(struct pp_eventmgr *eventmgr)
        pem_unregister_interrupts(eventmgr);
 
        pem_handle_event(eventmgr, AMD_PP_EVENT_UNINITIALIZE, &event_data);
-
-       if (eventmgr != NULL)
-               kfree(eventmgr);
 }
 
 int eventmgr_init(struct pp_instance *handle)
index 24a16e4..92912ab 100644 (file)
@@ -633,6 +633,8 @@ static int fiji_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
        data->vddci_control = FIJI_VOLTAGE_CONTROL_NONE;
        data->mvdd_control = FIJI_VOLTAGE_CONTROL_NONE;
 
+       data->force_pcie_gen = PP_PCIEGenInvalid;
+
        if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr,
                        VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2))
                data->voltage_control = FIJI_VOLTAGE_CONTROL_BY_SVID2;
@@ -1830,7 +1832,7 @@ static uint16_t fiji_find_closest_vddci(struct pp_hwmgr *hwmgr, uint16_t vddci)
 
        PP_ASSERT_WITH_CODE(false,
                        "VDDCI is larger than max VDDCI in VDDCI Voltage Table!",
-                       return vddci_table->entries[i].value);
+                       return vddci_table->entries[i-1].value);
 }
 
 static int fiji_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr,
index fa208ad..efb77ed 100644 (file)
@@ -306,10 +306,14 @@ int phm_store_dal_configuration_data(struct pp_hwmgr *hwmgr,
 {
        PHM_FUNC_CHECK(hwmgr);
 
-       if (hwmgr->hwmgr_func->store_cc6_data == NULL)
+       if (display_config == NULL)
                return -EINVAL;
 
        hwmgr->display_config = *display_config;
+
+       if (hwmgr->hwmgr_func->store_cc6_data == NULL)
+               return -EINVAL;
+
        /* to do pass other display configuration in furture */
 
        if (hwmgr->hwmgr_func->store_cc6_data)
index 1c48917..20f20e0 100644 (file)
@@ -93,6 +93,13 @@ int hwmgr_fini(struct pp_hwmgr *hwmgr)
        if (hwmgr == NULL || hwmgr->ps == NULL)
                return -EINVAL;
 
+       /* do hwmgr finish*/
+       kfree(hwmgr->backend);
+
+       kfree(hwmgr->start_thermal_controller.function_list);
+
+       kfree(hwmgr->set_temperature_range.function_list);
+
        kfree(hwmgr->ps);
        kfree(hwmgr);
        return 0;
@@ -462,7 +469,7 @@ uint16_t phm_find_closest_vddci(struct pp_atomctrl_voltage_table *vddci_table, u
 
        PP_ASSERT_WITH_CODE(false,
                        "VDDCI is larger than max VDDCI in VDDCI Voltage Table!",
-                       return vddci_table->entries[i].value);
+                       return vddci_table->entries[i-1].value);
 }
 
 int phm_find_boot_level(void *table,
index 347fef1..2930a33 100644 (file)
@@ -39,6 +39,7 @@ struct phm_ppt_v1_clock_voltage_dependency_record {
        uint8_t phases;
        uint8_t cks_enable;
        uint8_t cks_voffset;
+       uint32_t sclk_offset;
 };
 
 typedef struct phm_ppt_v1_clock_voltage_dependency_record phm_ppt_v1_clock_voltage_dependency_record;
index aa6be03..64ee78f 100644 (file)
@@ -999,7 +999,7 @@ static int polaris10_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr,
                                vddci = phm_find_closest_vddci(&(data->vddci_voltage_table),
                                                (dep_table->entries[i].vddc -
                                                                (uint16_t)data->vddc_vddci_delta));
-                               *voltage |= (vddci * VOLTAGE_SCALE) <<  VDDCI_SHIFT;
+                               *voltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT;
                        }
 
                        if (POLARIS10_VOLTAGE_CONTROL_NONE == data->mvdd_control)
@@ -1296,7 +1296,6 @@ static int polaris10_populate_single_memory_level(struct pp_hwmgr *hwmgr,
        }
 
        mem_level->MclkFrequency = clock;
-       mem_level->StutterEnable = 0;
        mem_level->EnabledForThrottle = 1;
        mem_level->EnabledForActivity = 0;
        mem_level->UpHyst = 0;
@@ -1304,7 +1303,6 @@ static int polaris10_populate_single_memory_level(struct pp_hwmgr *hwmgr,
        mem_level->VoltageDownHyst = 0;
        mem_level->ActivityLevel = (uint16_t)data->mclk_activity_target;
        mem_level->StutterEnable = false;
-
        mem_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
 
        data->display_timing.num_existing_displays = info.display_count;
@@ -1363,7 +1361,7 @@ static int polaris10_populate_all_memory_levels(struct pp_hwmgr *hwmgr)
         * a higher state by default such that we are not effected by
         * up threshold or and MCLK DPM latency.
         */
-       levels[0].ActivityLevel = (uint16_t)data->mclk_dpm0_activity_target;
+       levels[0].ActivityLevel = 0x1f;
        CONVERT_FROM_HOST_TO_SMC_US(levels[0].ActivityLevel);
 
        data->smc_state_table.MemoryDpmLevelCount =
@@ -1761,12 +1759,9 @@ static int polaris10_populate_smc_initailial_state(struct pp_hwmgr *hwmgr)
 
 static int polaris10_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr)
 {
-       uint32_t ro, efuse, efuse2, clock_freq, volt_without_cks,
-                       volt_with_cks, value;
-       uint16_t clock_freq_u16;
+       uint32_t ro, efuse, volt_without_cks, volt_with_cks, value, max, min;
        struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
-       uint8_t type, i, j, cks_setting, stretch_amount, stretch_amount2,
-                       volt_offset = 0;
+       uint8_t i, stretch_amount, stretch_amount2, volt_offset = 0;
        struct phm_ppt_v1_information *table_info =
                        (struct phm_ppt_v1_information *)(hwmgr->pptable);
        struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table =
@@ -1778,50 +1773,38 @@ static int polaris10_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr)
         * if the part is SS or FF. if RO >= 1660MHz, part is FF.
         */
        efuse = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC,
-                       ixSMU_EFUSE_0 + (146 * 4));
-       efuse2 = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC,
-                       ixSMU_EFUSE_0 + (148 * 4));
+                       ixSMU_EFUSE_0 + (67 * 4));
        efuse &= 0xFF000000;
        efuse = efuse >> 24;
-       efuse2 &= 0xF;
-
-       if (efuse2 == 1)
-               ro = (2300 - 1350) * efuse / 255 + 1350;
-       else
-               ro = (2500 - 1000) * efuse / 255 + 1000;
 
-       if (ro >= 1660)
-               type = 0;
-       else
-               type = 1;
+       if (hwmgr->chip_id == CHIP_POLARIS10) {
+               min = 1000;
+               max = 2300;
+       } else {
+               min = 1100;
+               max = 2100;
+       }
 
-       /* Populate Stretch amount */
-       data->smc_state_table.ClockStretcherAmount = stretch_amount;
+       ro = efuse * (max -min)/255 + min;
 
        /* Populate Sclk_CKS_masterEn0_7 and Sclk_voltageOffset */
        for (i = 0; i < sclk_table->count; i++) {
                data->smc_state_table.Sclk_CKS_masterEn0_7 |=
                                sclk_table->entries[i].cks_enable << i;
-               volt_without_cks = (uint32_t)((14041 *
-                       (sclk_table->entries[i].clk/100) / 10000 + 3571 + 75 - ro) * 1000 /
-                       (4026 - (13924 * (sclk_table->entries[i].clk/100) / 10000)));
-               volt_with_cks = (uint32_t)((13946 *
-                       (sclk_table->entries[i].clk/100) / 10000 + 3320 + 45 - ro) * 1000 /
-                       (3664 - (11454 * (sclk_table->entries[i].clk/100) / 10000)));
+
+               volt_without_cks =  (uint32_t)(((ro - 40) * 1000 - 2753594 - sclk_table->entries[i].clk/100 * 136418 /1000) / \
+                                       (sclk_table->entries[i].clk/100 * 1132925 /10000 - 242418)/100);
+
+               volt_with_cks = (uint32_t)((ro * 1000 -2396351 - sclk_table->entries[i].clk/100 * 329021/1000) / \
+                               (sclk_table->entries[i].clk/10000 * 649434 /1000  - 18005)/10);
+
                if (volt_without_cks >= volt_with_cks)
                        volt_offset = (uint8_t)(((volt_without_cks - volt_with_cks +
                                        sclk_table->entries[i].cks_voffset) * 100 / 625) + 1);
+
                data->smc_state_table.Sclk_voltageOffset[i] = volt_offset;
        }
 
-       PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE,
-                       STRETCH_ENABLE, 0x0);
-       PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE,
-                       masterReset, 0x1);
-       /* PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, staticEnable, 0x1); */
-       PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE,
-                       masterReset, 0x0);
-
        /* Populate CKS Lookup Table */
        if (stretch_amount == 1 || stretch_amount == 2 || stretch_amount == 5)
                stretch_amount2 = 0;
@@ -1835,69 +1818,6 @@ static int polaris10_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr)
                                return -EINVAL);
        }
 
-       value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC,
-                       ixPWR_CKS_CNTL);
-       value &= 0xFFC2FF87;
-       data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].minFreq =
-                       polaris10_clock_stretcher_lookup_table[stretch_amount2][0];
-       data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].maxFreq =
-                       polaris10_clock_stretcher_lookup_table[stretch_amount2][1];
-       clock_freq_u16 = (uint16_t)(PP_SMC_TO_HOST_UL(data->smc_state_table.
-                       GraphicsLevel[data->smc_state_table.GraphicsDpmLevelCount - 1].SclkSetting.SclkFrequency) / 100);
-       if (polaris10_clock_stretcher_lookup_table[stretch_amount2][0] < clock_freq_u16
-       && polaris10_clock_stretcher_lookup_table[stretch_amount2][1] > clock_freq_u16) {
-               /* Program PWR_CKS_CNTL. CKS_USE_FOR_LOW_FREQ */
-               value |= (polaris10_clock_stretcher_lookup_table[stretch_amount2][3]) << 16;
-               /* Program PWR_CKS_CNTL. CKS_LDO_REFSEL */
-               value |= (polaris10_clock_stretcher_lookup_table[stretch_amount2][2]) << 18;
-               /* Program PWR_CKS_CNTL. CKS_STRETCH_AMOUNT */
-               value |= (polaris10_clock_stretch_amount_conversion
-                               [polaris10_clock_stretcher_lookup_table[stretch_amount2][3]]
-                                [stretch_amount]) << 3;
-       }
-       CONVERT_FROM_HOST_TO_SMC_US(data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].minFreq);
-       CONVERT_FROM_HOST_TO_SMC_US(data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].maxFreq);
-       data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].setting =
-                       polaris10_clock_stretcher_lookup_table[stretch_amount2][2] & 0x7F;
-       data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].setting |=
-                       (polaris10_clock_stretcher_lookup_table[stretch_amount2][3]) << 7;
-
-       cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
-                       ixPWR_CKS_CNTL, value);
-
-       /* Populate DDT Lookup Table */
-       for (i = 0; i < 4; i++) {
-               /* Assign the minimum and maximum VID stored
-                * in the last row of Clock Stretcher Voltage Table.
-                */
-               data->smc_state_table.ClockStretcherDataTable.ClockStretcherDataTableEntry[i].minVID =
-                               (uint8_t) polaris10_clock_stretcher_ddt_table[type][i][2];
-               data->smc_state_table.ClockStretcherDataTable.ClockStretcherDataTableEntry[i].maxVID =
-                               (uint8_t) polaris10_clock_stretcher_ddt_table[type][i][3];
-               /* Loop through each SCLK and check the frequency
-                * to see if it lies within the frequency for clock stretcher.
-                */
-               for (j = 0; j < data->smc_state_table.GraphicsDpmLevelCount; j++) {
-                       cks_setting = 0;
-                       clock_freq = PP_SMC_TO_HOST_UL(
-                                       data->smc_state_table.GraphicsLevel[j].SclkSetting.SclkFrequency);
-                       /* Check the allowed frequency against the sclk level[j].
-                        *  Sclk's endianness has already been converted,
-                        *  and it's in 10Khz unit,
-                        *  as opposed to Data table, which is in Mhz unit.
-                        */
-                       if (clock_freq >= (polaris10_clock_stretcher_ddt_table[type][i][0]) * 100) {
-                               cks_setting |= 0x2;
-                               if (clock_freq < (polaris10_clock_stretcher_ddt_table[type][i][1]) * 100)
-                                       cks_setting |= 0x1;
-                       }
-                       data->smc_state_table.ClockStretcherDataTable.ClockStretcherDataTableEntry[i].setting
-                                                       |= cks_setting << (j * 2);
-               }
-               CONVERT_FROM_HOST_TO_SMC_US(
-                       data->smc_state_table.ClockStretcherDataTable.ClockStretcherDataTableEntry[i].setting);
-       }
-
        value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL);
        value &= 0xFFFFFFFE;
        cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL, value);
@@ -1956,6 +1876,90 @@ static int polaris10_populate_vr_config(struct pp_hwmgr *hwmgr,
        return 0;
 }
 
+
+int polaris10_populate_avfs_parameters(struct pp_hwmgr *hwmgr)
+{
+       struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+       SMU74_Discrete_DpmTable  *table = &(data->smc_state_table);
+       int result = 0;
+       struct pp_atom_ctrl__avfs_parameters avfs_params = {0};
+       AVFS_meanNsigma_t AVFS_meanNsigma = { {0} };
+       AVFS_Sclk_Offset_t AVFS_SclkOffset = { {0} };
+       uint32_t tmp, i;
+       struct pp_smumgr *smumgr = hwmgr->smumgr;
+       struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend);
+
+       struct phm_ppt_v1_information *table_info =
+                       (struct phm_ppt_v1_information *)hwmgr->pptable;
+       struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table =
+                       table_info->vdd_dep_on_sclk;
+
+
+       if (smu_data->avfs.avfs_btc_status == AVFS_BTC_NOTSUPPORTED)
+               return result;
+
+       result = atomctrl_get_avfs_information(hwmgr, &avfs_params);
+
+       if (0 == result) {
+               table->BTCGB_VDROOP_TABLE[0].a0  = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a0);
+               table->BTCGB_VDROOP_TABLE[0].a1  = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a1);
+               table->BTCGB_VDROOP_TABLE[0].a2  = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a2);
+               table->BTCGB_VDROOP_TABLE[1].a0  = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a0);
+               table->BTCGB_VDROOP_TABLE[1].a1  = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a1);
+               table->BTCGB_VDROOP_TABLE[1].a2  = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a2);
+               table->AVFSGB_VDROOP_TABLE[0].m1 = PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSON_m1);
+               table->AVFSGB_VDROOP_TABLE[0].m2 = PP_HOST_TO_SMC_US(avfs_params.usAVFSGB_FUSE_TABLE_CKSON_m2);
+               table->AVFSGB_VDROOP_TABLE[0].b  = PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSON_b);
+               table->AVFSGB_VDROOP_TABLE[0].m1_shift = 24;
+               table->AVFSGB_VDROOP_TABLE[0].m2_shift  = 12;
+               table->AVFSGB_VDROOP_TABLE[1].m1 = PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_m1);
+               table->AVFSGB_VDROOP_TABLE[1].m2 = PP_HOST_TO_SMC_US(avfs_params.usAVFSGB_FUSE_TABLE_CKSOFF_m2);
+               table->AVFSGB_VDROOP_TABLE[1].b  = PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_b);
+               table->AVFSGB_VDROOP_TABLE[1].m1_shift = 24;
+               table->AVFSGB_VDROOP_TABLE[1].m2_shift  = 12;
+               table->MaxVoltage                = PP_HOST_TO_SMC_US(avfs_params.usMaxVoltage_0_25mv);
+               AVFS_meanNsigma.Aconstant[0]      = PP_HOST_TO_SMC_UL(avfs_params.ulAVFS_meanNsigma_Acontant0);
+               AVFS_meanNsigma.Aconstant[1]      = PP_HOST_TO_SMC_UL(avfs_params.ulAVFS_meanNsigma_Acontant1);
+               AVFS_meanNsigma.Aconstant[2]      = PP_HOST_TO_SMC_UL(avfs_params.ulAVFS_meanNsigma_Acontant2);
+               AVFS_meanNsigma.DC_tol_sigma      = PP_HOST_TO_SMC_US(avfs_params.usAVFS_meanNsigma_DC_tol_sigma);
+               AVFS_meanNsigma.Platform_mean     = PP_HOST_TO_SMC_US(avfs_params.usAVFS_meanNsigma_Platform_mean);
+               AVFS_meanNsigma.PSM_Age_CompFactor = PP_HOST_TO_SMC_US(avfs_params.usPSM_Age_ComFactor);
+               AVFS_meanNsigma.Platform_sigma     = PP_HOST_TO_SMC_US(avfs_params.usAVFS_meanNsigma_Platform_sigma);
+
+               for (i = 0; i < NUM_VFT_COLUMNS; i++) {
+                       AVFS_meanNsigma.Static_Voltage_Offset[i] = (uint8_t)(sclk_table->entries[i].cks_voffset * 100 / 625);
+                       AVFS_SclkOffset.Sclk_Offset[i] = PP_HOST_TO_SMC_US((uint16_t)(sclk_table->entries[i].sclk_offset) / 100);
+               }
+
+               result = polaris10_read_smc_sram_dword(smumgr,
+                               SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU74_Firmware_Header, AvfsMeanNSigma),
+                               &tmp, data->sram_end);
+
+               polaris10_copy_bytes_to_smc(smumgr,
+                                       tmp,
+                                       (uint8_t *)&AVFS_meanNsigma,
+                                       sizeof(AVFS_meanNsigma_t),
+                                       data->sram_end);
+
+               result = polaris10_read_smc_sram_dword(smumgr,
+                               SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU74_Firmware_Header, AvfsSclkOffsetTable),
+                               &tmp, data->sram_end);
+               polaris10_copy_bytes_to_smc(smumgr,
+                                       tmp,
+                                       (uint8_t *)&AVFS_SclkOffset,
+                                       sizeof(AVFS_Sclk_Offset_t),
+                                       data->sram_end);
+
+               data->avfs_vdroop_override_setting = (avfs_params.ucEnableGB_VDROOP_TABLE_CKSON << BTCGB0_Vdroop_Enable_SHIFT) |
+                                               (avfs_params.ucEnableGB_VDROOP_TABLE_CKSOFF << BTCGB1_Vdroop_Enable_SHIFT) |
+                                               (avfs_params.ucEnableGB_FUSE_TABLE_CKSON << AVFSGB0_Vdroop_Enable_SHIFT) |
+                                               (avfs_params.ucEnableGB_FUSE_TABLE_CKSOFF << AVFSGB1_Vdroop_Enable_SHIFT);
+               data->apply_avfs_cks_off_voltage = (avfs_params.ucEnableApplyAVFS_CKS_OFF_Voltage == 1) ? true : false;
+       }
+       return result;
+}
+
+
 /**
 * Initializes the SMC table and uploads it
 *
@@ -2056,6 +2060,10 @@ static int polaris10_init_smc_table(struct pp_hwmgr *hwmgr)
                                "Failed to populate Clock Stretcher Data Table!",
                                return result);
        }
+
+       result = polaris10_populate_avfs_parameters(hwmgr);
+       PP_ASSERT_WITH_CODE(0 == result, "Failed to populate AVFS Parameters!", return result;);
+
        table->CurrSclkPllRange = 0xff;
        table->GraphicsVoltageChangeEnable  = 1;
        table->GraphicsThermThrottleEnable  = 1;
@@ -2252,6 +2260,9 @@ static int polaris10_enable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr)
 static int polaris10_enable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
 {
        struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+       uint32_t soft_register_value = 0;
+       uint32_t handshake_disables_offset = data->soft_regs_start
+                               + offsetof(SMU74_SoftRegisters, HandshakeDisables);
 
        /* enable SCLK dpm */
        if (!data->sclk_dpm_key_disabled)
@@ -2262,6 +2273,12 @@ static int polaris10_enable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
 
        /* enable MCLK dpm */
        if (0 == data->mclk_dpm_key_disabled) {
+/* Disable UVD - SMU handshake for MCLK. */
+               soft_register_value = cgs_read_ind_register(hwmgr->device,
+                                       CGS_IND_REG__SMC, handshake_disables_offset);
+               soft_register_value |= SMU7_UVD_MCLK_HANDSHAKE_DISABLE;
+               cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+                               handshake_disables_offset, soft_register_value);
 
                PP_ASSERT_WITH_CODE(
                                (0 == smum_send_msg_to_smc(hwmgr->smumgr,
@@ -2269,7 +2286,6 @@ static int polaris10_enable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
                                "Failed to enable MCLK DPM during DPM Start Function!",
                                return -1);
 
-
                PHM_WRITE_FIELD(hwmgr->device, MC_SEQ_CNTL_3, CAC_EN, 0x1);
 
                cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC0_CNTL, 0x5);
@@ -2606,6 +2622,7 @@ int polaris10_set_features_platform_caps(struct pp_hwmgr *hwmgr)
 
        phm_cap_set(hwmgr->platform_descriptor.platformCaps,
                                                PHM_PlatformCaps_FanSpeedInTableIsRPM);
+
        if (hwmgr->chip_id == CHIP_POLARIS11)
                phm_cap_set(hwmgr->platform_descriptor.platformCaps,
                                        PHM_PlatformCaps_SPLLShutdownSupport);
@@ -2938,6 +2955,11 @@ int polaris10_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
        data->vddci_control = POLARIS10_VOLTAGE_CONTROL_NONE;
        data->mvdd_control = POLARIS10_VOLTAGE_CONTROL_NONE;
 
+       data->enable_tdc_limit_feature = true;
+       data->enable_pkg_pwr_tracking_feature = true;
+       data->force_pcie_gen = PP_PCIEGenInvalid;
+       data->mclk_stutter_mode_threshold = 40000;
+
        if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr,
                        VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2))
                data->voltage_control = POLARIS10_VOLTAGE_CONTROL_BY_SVID2;
@@ -2962,6 +2984,10 @@ int polaris10_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
                        data->vddci_control = POLARIS10_VOLTAGE_CONTROL_BY_SVID2;
        }
 
+       if (table_info->cac_dtp_table->usClockStretchAmount != 0)
+               phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+                                       PHM_PlatformCaps_ClockStretcher);
+
        polaris10_set_features_platform_caps(hwmgr);
 
        polaris10_init_dpm_defaults(hwmgr);
@@ -3520,10 +3546,11 @@ static int polaris10_get_pp_table_entry_callback_func(struct pp_hwmgr *hwmgr,
        ATOM_Tonga_State *state_entry = (ATOM_Tonga_State *)state;
        ATOM_Tonga_POWERPLAYTABLE *powerplay_table =
                        (ATOM_Tonga_POWERPLAYTABLE *)pp_table;
-       ATOM_Tonga_SCLK_Dependency_Table *sclk_dep_table =
-                       (ATOM_Tonga_SCLK_Dependency_Table *)
+       PPTable_Generic_SubTable_Header *sclk_dep_table =
+                       (PPTable_Generic_SubTable_Header *)
                        (((unsigned long)powerplay_table) +
                                le16_to_cpu(powerplay_table->usSclkDependencyTableOffset));
+
        ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table =
                        (ATOM_Tonga_MCLK_Dependency_Table *)
                        (((unsigned long)powerplay_table) +
@@ -3575,7 +3602,11 @@ static int polaris10_get_pp_table_entry_callback_func(struct pp_hwmgr *hwmgr,
        /* Performance levels are arranged from low to high. */
        performance_level->memory_clock = mclk_dep_table->entries
                        [state_entry->ucMemoryClockIndexLow].ulMclk;
-       performance_level->engine_clock = sclk_dep_table->entries
+       if (sclk_dep_table->ucRevId == 0)
+               performance_level->engine_clock = ((ATOM_Tonga_SCLK_Dependency_Table *)sclk_dep_table)->entries
+                       [state_entry->ucEngineClockIndexLow].ulSclk;
+       else if (sclk_dep_table->ucRevId == 1)
+               performance_level->engine_clock = ((ATOM_Polaris_SCLK_Dependency_Table *)sclk_dep_table)->entries
                        [state_entry->ucEngineClockIndexLow].ulSclk;
        performance_level->pcie_gen = get_pcie_gen_support(data->pcie_gen_cap,
                        state_entry->ucPCIEGenLow);
@@ -3586,8 +3617,14 @@ static int polaris10_get_pp_table_entry_callback_func(struct pp_hwmgr *hwmgr,
                        [polaris10_power_state->performance_level_count++]);
        performance_level->memory_clock = mclk_dep_table->entries
                        [state_entry->ucMemoryClockIndexHigh].ulMclk;
-       performance_level->engine_clock = sclk_dep_table->entries
+
+       if (sclk_dep_table->ucRevId == 0)
+               performance_level->engine_clock = ((ATOM_Tonga_SCLK_Dependency_Table *)sclk_dep_table)->entries
                        [state_entry->ucEngineClockIndexHigh].ulSclk;
+       else if (sclk_dep_table->ucRevId == 1)
+               performance_level->engine_clock = ((ATOM_Polaris_SCLK_Dependency_Table *)sclk_dep_table)->entries
+                       [state_entry->ucEngineClockIndexHigh].ulSclk;
+
        performance_level->pcie_gen = get_pcie_gen_support(data->pcie_gen_cap,
                        state_entry->ucPCIEGenHigh);
        performance_level->pcie_lane = get_pcie_lane_support(data->pcie_lane_cap,
@@ -3645,7 +3682,6 @@ static int polaris10_get_pp_table_entry(struct pp_hwmgr *hwmgr,
                switch (state->classification.ui_label) {
                case PP_StateUILabel_Performance:
                        data->use_pcie_performance_levels = true;
-
                        for (i = 0; i < ps->performance_level_count; i++) {
                                if (data->pcie_gen_performance.max <
                                                ps->performance_levels[i].pcie_gen)
@@ -3661,7 +3697,6 @@ static int polaris10_get_pp_table_entry(struct pp_hwmgr *hwmgr,
                                                ps->performance_levels[i].pcie_lane)
                                        data->pcie_lane_performance.max =
                                                        ps->performance_levels[i].pcie_lane;
-
                                if (data->pcie_lane_performance.min >
                                                ps->performance_levels[i].pcie_lane)
                                        data->pcie_lane_performance.min =
@@ -4187,12 +4222,9 @@ int polaris10_update_samu_dpm(struct pp_hwmgr *hwmgr, bool bgate)
 {
        struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
        uint32_t mm_boot_level_offset, mm_boot_level_value;
-       struct phm_ppt_v1_information *table_info =
-                       (struct phm_ppt_v1_information *)(hwmgr->pptable);
 
        if (!bgate) {
-               data->smc_state_table.SamuBootLevel =
-                               (uint8_t) (table_info->mm_dep_table->count - 1);
+               data->smc_state_table.SamuBootLevel = 0;
                mm_boot_level_offset = data->dpm_table_start +
                                offsetof(SMU74_Discrete_DpmTable, SamuBootLevel);
                mm_boot_level_offset /= 4;
index beedf35..d717789 100644 (file)
@@ -312,6 +312,9 @@ struct polaris10_hwmgr {
 
        /* soft pptable for re-uploading into smu */
        void *soft_pp_table;
+
+       uint32_t                              avfs_vdroop_override_setting;
+       bool                                  apply_avfs_cks_off_voltage;
 };
 
 /* To convert to Q8.8 format for firmware */
index 0b99ab3..ae96f14 100644 (file)
@@ -286,7 +286,7 @@ int polaris10_populate_pm_fuses(struct pp_hwmgr *hwmgr)
 
                if (polaris10_copy_bytes_to_smc(hwmgr->smumgr, pm_fuse_table_offset,
                                (uint8_t *)&data->power_tune_table,
-                               sizeof(struct SMU74_Discrete_PmFuses), data->sram_end))
+                               (sizeof(struct SMU74_Discrete_PmFuses) - 92), data->sram_end))
                        PP_ASSERT_WITH_CODE(false,
                                        "Attempt to download PmFuseTable Failed!",
                                        return -EINVAL);
index aba167f..b206632 100644 (file)
@@ -625,10 +625,14 @@ static int tf_polaris10_thermal_avfs_enable(struct pp_hwmgr *hwmgr,
        int ret;
        struct pp_smumgr *smumgr = (struct pp_smumgr *)(hwmgr->smumgr);
        struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend);
+       struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
 
-       if (smu_data->avfs.avfs_btc_status != AVFS_BTC_ENABLEAVFS)
+       if (smu_data->avfs.avfs_btc_status == AVFS_BTC_NOTSUPPORTED)
                return 0;
 
+       ret = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+                       PPSMC_MSG_SetGBDroopSettings, data->avfs_vdroop_override_setting);
+
        ret = (smum_send_msg_to_smc(smumgr, PPSMC_MSG_EnableAvfs) == 0) ?
                        0 : -1;
 
index 58742e0..a3c38bb 100644 (file)
@@ -44,6 +44,20 @@ bool acpi_atcs_functions_supported(void *device, uint32_t index)
        return result == 0 ? (output_buf.function_bits & (1 << (index - 1))) != 0 : false;
 }
 
+bool acpi_atcs_notify_pcie_device_ready(void *device)
+{
+       int32_t temp_buffer = 1;
+
+       return cgs_call_acpi_method(device, CGS_ACPI_METHOD_ATCS,
+                               ATCS_FUNCTION_PCIE_DEVICE_READY_NOTIFICATION,
+                                               &temp_buffer,
+                                               NULL,
+                                               0,
+                                               sizeof(temp_buffer),
+                                               0);
+}
+
+
 int acpi_pcie_perf_request(void *device, uint8_t perf_req, bool advertise)
 {
        struct atcs_pref_req_input atcs_input;
@@ -52,7 +66,7 @@ int acpi_pcie_perf_request(void *device, uint8_t perf_req, bool advertise)
        int result;
        struct cgs_system_info info = {0};
 
-       if (!acpi_atcs_functions_supported(device, ATCS_FUNCTION_PCIE_PERFORMANCE_REQUEST))
+       if( 0 != acpi_atcs_notify_pcie_device_ready(device))
                return -EINVAL;
 
        info.size = sizeof(struct cgs_system_info);
@@ -77,7 +91,7 @@ int acpi_pcie_perf_request(void *device, uint8_t perf_req, bool advertise)
                                                ATCS_FUNCTION_PCIE_PERFORMANCE_REQUEST,
                                                &atcs_input,
                                                &atcs_output,
-                                               0,
+                                               1,
                                                sizeof(atcs_input),
                                                sizeof(atcs_output));
                if (result != 0)
index da9f5f1..bf4e18f 100644 (file)
@@ -1302,3 +1302,46 @@ int atomctrl_get_smc_sclk_range_table(struct pp_hwmgr *hwmgr, struct pp_atom_ctr
 
        return 0;
 }
+
+int atomctrl_get_avfs_information(struct pp_hwmgr *hwmgr, struct pp_atom_ctrl__avfs_parameters *param)
+{
+       ATOM_ASIC_PROFILING_INFO_V3_6 *profile = NULL;
+
+       if (param == NULL)
+               return -EINVAL;
+
+       profile = (ATOM_ASIC_PROFILING_INFO_V3_6 *)
+                       cgs_atom_get_data_table(hwmgr->device,
+                                       GetIndexIntoMasterTable(DATA, ASIC_ProfilingInfo),
+                                       NULL, NULL, NULL);
+       if (!profile)
+               return -1;
+
+       param->ulAVFS_meanNsigma_Acontant0 = profile->ulAVFS_meanNsigma_Acontant0;
+       param->ulAVFS_meanNsigma_Acontant1 = profile->ulAVFS_meanNsigma_Acontant1;
+       param->ulAVFS_meanNsigma_Acontant2 = profile->ulAVFS_meanNsigma_Acontant2;
+       param->usAVFS_meanNsigma_DC_tol_sigma = profile->usAVFS_meanNsigma_DC_tol_sigma;
+       param->usAVFS_meanNsigma_Platform_mean = profile->usAVFS_meanNsigma_Platform_mean;
+       param->usAVFS_meanNsigma_Platform_sigma = profile->usAVFS_meanNsigma_Platform_sigma;
+       param->ulGB_VDROOP_TABLE_CKSOFF_a0 = profile->ulGB_VDROOP_TABLE_CKSOFF_a0;
+       param->ulGB_VDROOP_TABLE_CKSOFF_a1 = profile->ulGB_VDROOP_TABLE_CKSOFF_a1;
+       param->ulGB_VDROOP_TABLE_CKSOFF_a2 = profile->ulGB_VDROOP_TABLE_CKSOFF_a2;
+       param->ulGB_VDROOP_TABLE_CKSON_a0 = profile->ulGB_VDROOP_TABLE_CKSON_a0;
+       param->ulGB_VDROOP_TABLE_CKSON_a1 = profile->ulGB_VDROOP_TABLE_CKSON_a1;
+       param->ulGB_VDROOP_TABLE_CKSON_a2 = profile->ulGB_VDROOP_TABLE_CKSON_a2;
+       param->ulAVFSGB_FUSE_TABLE_CKSOFF_m1 = profile->ulAVFSGB_FUSE_TABLE_CKSOFF_m1;
+       param->usAVFSGB_FUSE_TABLE_CKSOFF_m2 = profile->usAVFSGB_FUSE_TABLE_CKSOFF_m2;
+       param->ulAVFSGB_FUSE_TABLE_CKSOFF_b = profile->ulAVFSGB_FUSE_TABLE_CKSOFF_b;
+       param->ulAVFSGB_FUSE_TABLE_CKSON_m1 = profile->ulAVFSGB_FUSE_TABLE_CKSON_m1;
+       param->usAVFSGB_FUSE_TABLE_CKSON_m2 = profile->usAVFSGB_FUSE_TABLE_CKSON_m2;
+       param->ulAVFSGB_FUSE_TABLE_CKSON_b = profile->ulAVFSGB_FUSE_TABLE_CKSON_b;
+       param->usMaxVoltage_0_25mv = profile->usMaxVoltage_0_25mv;
+       param->ucEnableGB_VDROOP_TABLE_CKSOFF = profile->ucEnableGB_VDROOP_TABLE_CKSOFF;
+       param->ucEnableGB_VDROOP_TABLE_CKSON = profile->ucEnableGB_VDROOP_TABLE_CKSON;
+       param->ucEnableGB_FUSE_TABLE_CKSOFF = profile->ucEnableGB_FUSE_TABLE_CKSOFF;
+       param->ucEnableGB_FUSE_TABLE_CKSON = profile->ucEnableGB_FUSE_TABLE_CKSON;
+       param->usPSM_Age_ComFactor = profile->usPSM_Age_ComFactor;
+       param->ucEnableApplyAVFS_CKS_OFF_Voltage = profile->ucEnableApplyAVFS_CKS_OFF_Voltage;
+
+       return 0;
+}
index d24ebb5..248c5db 100644 (file)
@@ -250,6 +250,35 @@ struct pp_atomctrl_gpio_pin_assignment {
 };
 typedef struct pp_atomctrl_gpio_pin_assignment pp_atomctrl_gpio_pin_assignment;
 
+struct pp_atom_ctrl__avfs_parameters {
+       uint32_t  ulAVFS_meanNsigma_Acontant0;
+       uint32_t  ulAVFS_meanNsigma_Acontant1;
+       uint32_t  ulAVFS_meanNsigma_Acontant2;
+       uint16_t usAVFS_meanNsigma_DC_tol_sigma;
+       uint16_t usAVFS_meanNsigma_Platform_mean;
+       uint16_t usAVFS_meanNsigma_Platform_sigma;
+       uint32_t  ulGB_VDROOP_TABLE_CKSOFF_a0;
+       uint32_t  ulGB_VDROOP_TABLE_CKSOFF_a1;
+       uint32_t  ulGB_VDROOP_TABLE_CKSOFF_a2;
+       uint32_t  ulGB_VDROOP_TABLE_CKSON_a0;
+       uint32_t  ulGB_VDROOP_TABLE_CKSON_a1;
+       uint32_t  ulGB_VDROOP_TABLE_CKSON_a2;
+       uint32_t  ulAVFSGB_FUSE_TABLE_CKSOFF_m1;
+       uint16_t  usAVFSGB_FUSE_TABLE_CKSOFF_m2;
+       uint32_t  ulAVFSGB_FUSE_TABLE_CKSOFF_b;
+       uint32_t  ulAVFSGB_FUSE_TABLE_CKSON_m1;
+       uint16_t  usAVFSGB_FUSE_TABLE_CKSON_m2;
+       uint32_t  ulAVFSGB_FUSE_TABLE_CKSON_b;
+       uint16_t  usMaxVoltage_0_25mv;
+       uint8_t  ucEnableGB_VDROOP_TABLE_CKSOFF;
+       uint8_t  ucEnableGB_VDROOP_TABLE_CKSON;
+       uint8_t  ucEnableGB_FUSE_TABLE_CKSOFF;
+       uint8_t  ucEnableGB_FUSE_TABLE_CKSON;
+       uint16_t usPSM_Age_ComFactor;
+       uint8_t  ucEnableApplyAVFS_CKS_OFF_Voltage;
+       uint8_t  ucReserved;
+};
+
 extern bool atomctrl_get_pp_assign_pin(struct pp_hwmgr *hwmgr, const uint32_t pinId, pp_atomctrl_gpio_pin_assignment *gpio_pin_assignment);
 extern int atomctrl_get_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type, uint32_t sclk, uint16_t virtual_voltage_Id, uint16_t *voltage);
 extern uint32_t atomctrl_get_mpll_reference_clock(struct pp_hwmgr *hwmgr);
@@ -278,5 +307,8 @@ extern int atomctrl_set_ac_timing_ai(struct pp_hwmgr *hwmgr, uint32_t memory_clo
 extern int atomctrl_get_voltage_evv_on_sclk_ai(struct pp_hwmgr *hwmgr, uint8_t voltage_type,
                                uint32_t sclk, uint16_t virtual_voltage_Id, uint16_t *voltage);
 extern int atomctrl_get_smc_sclk_range_table(struct pp_hwmgr *hwmgr, struct pp_atom_ctrl_sclk_range_table *table);
+
+extern int atomctrl_get_avfs_information(struct pp_hwmgr *hwmgr, struct pp_atom_ctrl__avfs_parameters *param);
+
 #endif
 
index 16fed48..233eb7f 100644 (file)
@@ -2847,27 +2847,6 @@ static int tonga_setup_default_dpm_tables(struct pp_hwmgr *hwmgr)
                }
        }
 
-       /* Initialize Vddc DPM table based on allow Vddc values.  And populate corresponding std values. */
-       for (i = 0; i < allowed_vdd_sclk_table->count; i++) {
-               data->dpm_table.vddc_table.dpm_levels[i].value = allowed_vdd_mclk_table->entries[i].vddc;
-               /* tonga_hwmgr->dpm_table.VddcTable.dpm_levels[i].param1 = stdVoltageTable->entries[i].Leakage; */
-               /* param1 is for corresponding std voltage */
-               data->dpm_table.vddc_table.dpm_levels[i].enabled = 1;
-       }
-       data->dpm_table.vddc_table.count = allowed_vdd_sclk_table->count;
-
-       if (NULL != allowed_vdd_mclk_table) {
-               /* Initialize Vddci DPM table based on allow Mclk values */
-               for (i = 0; i < allowed_vdd_mclk_table->count; i++) {
-                       data->dpm_table.vdd_ci_table.dpm_levels[i].value = allowed_vdd_mclk_table->entries[i].vddci;
-                       data->dpm_table.vdd_ci_table.dpm_levels[i].enabled = 1;
-                       data->dpm_table.mvdd_table.dpm_levels[i].value = allowed_vdd_mclk_table->entries[i].mvdd;
-                       data->dpm_table.mvdd_table.dpm_levels[i].enabled = 1;
-               }
-               data->dpm_table.vdd_ci_table.count = allowed_vdd_mclk_table->count;
-               data->dpm_table.mvdd_table.count = allowed_vdd_mclk_table->count;
-       }
-
        /* setup PCIE gen speed levels*/
        tonga_setup_default_pcie_tables(hwmgr);
 
@@ -4510,6 +4489,7 @@ int tonga_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
        data->vdd_ci_control = TONGA_VOLTAGE_CONTROL_NONE;
        data->vdd_gfx_control = TONGA_VOLTAGE_CONTROL_NONE;
        data->mvdd_control = TONGA_VOLTAGE_CONTROL_NONE;
+       data->force_pcie_gen = PP_PCIEGenInvalid;
 
        if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr,
                                VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2)) {
index 1b44f4e..f127198 100644 (file)
@@ -197,6 +197,22 @@ typedef struct _ATOM_Tonga_SCLK_Dependency_Table {
        ATOM_Tonga_SCLK_Dependency_Record entries[1];                            /* Dynamically allocate entries. */
 } ATOM_Tonga_SCLK_Dependency_Table;
 
+typedef struct _ATOM_Polaris_SCLK_Dependency_Record {
+       UCHAR  ucVddInd;                                                                                        /* Base voltage */
+       USHORT usVddcOffset;                                                                            /* Offset relative to base voltage */
+       ULONG ulSclk;
+       USHORT usEdcCurrent;
+       UCHAR  ucReliabilityTemperature;
+       UCHAR  ucCKSVOffsetandDisable;                  /* Bits 0~6: Voltage offset for CKS, Bit 7: Disable/enable for the SCLK level. */
+       ULONG  ulSclkOffset;
+} ATOM_Polaris_SCLK_Dependency_Record;
+
+typedef struct _ATOM_Polaris_SCLK_Dependency_Table {
+       UCHAR ucRevId;
+       UCHAR ucNumEntries;                                                     /* Number of entries. */
+       ATOM_Polaris_SCLK_Dependency_Record entries[1];                          /* Dynamically allocate entries. */
+} ATOM_Polaris_SCLK_Dependency_Table;
+
 typedef struct _ATOM_Tonga_PCIE_Record {
        UCHAR ucPCIEGenSpeed;
        UCHAR usPCIELaneWidth;
index 10e3630..671fdb4 100644 (file)
@@ -408,41 +408,78 @@ static int get_mclk_voltage_dependency_table(
 static int get_sclk_voltage_dependency_table(
                struct pp_hwmgr *hwmgr,
                phm_ppt_v1_clock_voltage_dependency_table **pp_tonga_sclk_dep_table,
-               const ATOM_Tonga_SCLK_Dependency_Table * sclk_dep_table
+               const PPTable_Generic_SubTable_Header *sclk_dep_table
                )
 {
        uint32_t table_size, i;
        phm_ppt_v1_clock_voltage_dependency_table *sclk_table;
 
-       PP_ASSERT_WITH_CODE((0 != sclk_dep_table->ucNumEntries),
-               "Invalid PowerPlay Table!", return -1);
+       if (sclk_dep_table->ucRevId < 1) {
+               const ATOM_Tonga_SCLK_Dependency_Table *tonga_table =
+                           (ATOM_Tonga_SCLK_Dependency_Table *)sclk_dep_table;
 
-       table_size = sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record)
-               * sclk_dep_table->ucNumEntries;
+               PP_ASSERT_WITH_CODE((0 != tonga_table->ucNumEntries),
+                       "Invalid PowerPlay Table!", return -1);
 
-       sclk_table = (phm_ppt_v1_clock_voltage_dependency_table *)
-               kzalloc(table_size, GFP_KERNEL);
+               table_size = sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record)
+                       * tonga_table->ucNumEntries;
 
-       if (NULL == sclk_table)
-               return -ENOMEM;
+               sclk_table = (phm_ppt_v1_clock_voltage_dependency_table *)
+                       kzalloc(table_size, GFP_KERNEL);
 
-       memset(sclk_table, 0x00, table_size);
-
-       sclk_table->count = (uint32_t)sclk_dep_table->ucNumEntries;
-
-       for (i = 0; i < sclk_dep_table->ucNumEntries; i++) {
-               sclk_table->entries[i].vddInd =
-                       sclk_dep_table->entries[i].ucVddInd;
-               sclk_table->entries[i].vdd_offset =
-                       sclk_dep_table->entries[i].usVddcOffset;
-               sclk_table->entries[i].clk =
-                       sclk_dep_table->entries[i].ulSclk;
-               sclk_table->entries[i].cks_enable =
-                       (((sclk_dep_table->entries[i].ucCKSVOffsetandDisable & 0x80) >> 7) == 0) ? 1 : 0;
-               sclk_table->entries[i].cks_voffset =
-                       (sclk_dep_table->entries[i].ucCKSVOffsetandDisable & 0x7F);
-       }
+               if (NULL == sclk_table)
+                       return -ENOMEM;
+
+               memset(sclk_table, 0x00, table_size);
+
+               sclk_table->count = (uint32_t)tonga_table->ucNumEntries;
+
+               for (i = 0; i < tonga_table->ucNumEntries; i++) {
+                       sclk_table->entries[i].vddInd =
+                               tonga_table->entries[i].ucVddInd;
+                       sclk_table->entries[i].vdd_offset =
+                               tonga_table->entries[i].usVddcOffset;
+                       sclk_table->entries[i].clk =
+                               tonga_table->entries[i].ulSclk;
+                       sclk_table->entries[i].cks_enable =
+                               (((tonga_table->entries[i].ucCKSVOffsetandDisable & 0x80) >> 7) == 0) ? 1 : 0;
+                       sclk_table->entries[i].cks_voffset =
+                               (tonga_table->entries[i].ucCKSVOffsetandDisable & 0x7F);
+               }
+       } else {
+               const ATOM_Polaris_SCLK_Dependency_Table *polaris_table =
+                           (ATOM_Polaris_SCLK_Dependency_Table *)sclk_dep_table;
+
+               PP_ASSERT_WITH_CODE((0 != polaris_table->ucNumEntries),
+                       "Invalid PowerPlay Table!", return -1);
+
+               table_size = sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record)
+                       * polaris_table->ucNumEntries;
+
+               sclk_table = (phm_ppt_v1_clock_voltage_dependency_table *)
+                       kzalloc(table_size, GFP_KERNEL);
 
+               if (NULL == sclk_table)
+                       return -ENOMEM;
+
+               memset(sclk_table, 0x00, table_size);
+
+               sclk_table->count = (uint32_t)polaris_table->ucNumEntries;
+
+               for (i = 0; i < polaris_table->ucNumEntries; i++) {
+                       sclk_table->entries[i].vddInd =
+                               polaris_table->entries[i].ucVddInd;
+                       sclk_table->entries[i].vdd_offset =
+                               polaris_table->entries[i].usVddcOffset;
+                       sclk_table->entries[i].clk =
+                               polaris_table->entries[i].ulSclk;
+                       sclk_table->entries[i].cks_enable =
+                               (((polaris_table->entries[i].ucCKSVOffsetandDisable & 0x80) >> 7) == 0) ? 1 : 0;
+                       sclk_table->entries[i].cks_voffset =
+                               (polaris_table->entries[i].ucCKSVOffsetandDisable & 0x7F);
+                       sclk_table->entries[i].sclk_offset = polaris_table->entries[i].ulSclkOffset;
+               }
+       }
        *pp_tonga_sclk_dep_table = sclk_table;
 
        return 0;
@@ -708,8 +745,8 @@ static int init_clock_voltage_dependency(
        const ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table =
                (const ATOM_Tonga_MCLK_Dependency_Table *)(((unsigned long) powerplay_table) +
                le16_to_cpu(powerplay_table->usMclkDependencyTableOffset));
-       const ATOM_Tonga_SCLK_Dependency_Table *sclk_dep_table =
-               (const ATOM_Tonga_SCLK_Dependency_Table *)(((unsigned long) powerplay_table) +
+       const PPTable_Generic_SubTable_Header *sclk_dep_table =
+               (const PPTable_Generic_SubTable_Header *)(((unsigned long) powerplay_table) +
                le16_to_cpu(powerplay_table->usSclkDependencyTableOffset));
        const ATOM_Tonga_Hard_Limit_Table *pHardLimits =
                (const ATOM_Tonga_Hard_Limit_Table *)(((unsigned long) powerplay_table) +
@@ -1040,48 +1077,44 @@ int tonga_pp_tables_uninitialize(struct pp_hwmgr *hwmgr)
        struct phm_ppt_v1_information *pp_table_information =
                (struct phm_ppt_v1_information *)(hwmgr->pptable);
 
-       if (NULL != hwmgr->soft_pp_table) {
-               kfree(hwmgr->soft_pp_table);
+       if (NULL != hwmgr->soft_pp_table)
                hwmgr->soft_pp_table = NULL;
-       }
 
-       if (NULL != pp_table_information->vdd_dep_on_sclk)
-               pp_table_information->vdd_dep_on_sclk = NULL;
+       kfree(pp_table_information->vdd_dep_on_sclk);
+       pp_table_information->vdd_dep_on_sclk = NULL;
 
-       if (NULL != pp_table_information->vdd_dep_on_mclk)
-               pp_table_information->vdd_dep_on_mclk = NULL;
+       kfree(pp_table_information->vdd_dep_on_mclk);
+       pp_table_information->vdd_dep_on_mclk = NULL;
 
-       if (NULL != pp_table_information->valid_mclk_values)
-               pp_table_information->valid_mclk_values = NULL;
+       kfree(pp_table_information->valid_mclk_values);
+       pp_table_information->valid_mclk_values = NULL;
 
-       if (NULL != pp_table_information->valid_sclk_values)
-               pp_table_information->valid_sclk_values = NULL;
+       kfree(pp_table_information->valid_sclk_values);
+       pp_table_information->valid_sclk_values = NULL;
 
-       if (NULL != pp_table_information->vddc_lookup_table)
-               pp_table_information->vddc_lookup_table = NULL;
+       kfree(pp_table_information->vddc_lookup_table);
+       pp_table_information->vddc_lookup_table = NULL;
 
-       if (NULL != pp_table_information->vddgfx_lookup_table)
-               pp_table_information->vddgfx_lookup_table = NULL;
+       kfree(pp_table_information->vddgfx_lookup_table);
+       pp_table_information->vddgfx_lookup_table = NULL;
 
-       if (NULL != pp_table_information->mm_dep_table)
-               pp_table_information->mm_dep_table = NULL;
+       kfree(pp_table_information->mm_dep_table);
+       pp_table_information->mm_dep_table = NULL;
 
-       if (NULL != pp_table_information->cac_dtp_table)
-               pp_table_information->cac_dtp_table = NULL;
+       kfree(pp_table_information->cac_dtp_table);
+       pp_table_information->cac_dtp_table = NULL;
 
-       if (NULL != hwmgr->dyn_state.cac_dtp_table)
-               hwmgr->dyn_state.cac_dtp_table = NULL;
+       kfree(hwmgr->dyn_state.cac_dtp_table);
+       hwmgr->dyn_state.cac_dtp_table = NULL;
 
-       if (NULL != pp_table_information->ppm_parameter_table)
-               pp_table_information->ppm_parameter_table = NULL;
+       kfree(pp_table_information->ppm_parameter_table);
+       pp_table_information->ppm_parameter_table = NULL;
 
-       if (NULL != pp_table_information->pcie_table)
-               pp_table_information->pcie_table = NULL;
+       kfree(pp_table_information->pcie_table);
+       pp_table_information->pcie_table = NULL;
 
-       if (NULL != hwmgr->pptable) {
-               kfree(hwmgr->pptable);
-               hwmgr->pptable = NULL;
-       }
+       kfree(hwmgr->pptable);
+       hwmgr->pptable = NULL;
 
        return result;
 }
index 0c6a413..d41d37a 100644 (file)
@@ -27,6 +27,7 @@
 
 #pragma pack(push, 1)
 
+#define PPSMC_MSG_SetGBDroopSettings          ((uint16_t) 0x305)
 
 #define PPSMC_SWSTATE_FLAG_DC                           0x01
 #define PPSMC_SWSTATE_FLAG_UVD                          0x02
index 3bd5e69..3df5de2 100644 (file)
@@ -26,3 +26,4 @@ extern bool acpi_atcs_functions_supported(void *device,
 extern int acpi_pcie_perf_request(void *device,
                                                uint8_t perf_req,
                                                bool advertise);
+extern bool acpi_atcs_notify_pcie_device_ready(void *device);
index 1a12d85..fd10a9f 100644 (file)
 #define SMU__NUM_LCLK_DPM_LEVELS 8
 #define SMU__NUM_PCIE_DPM_LEVELS 8
 
+#define EXP_M1  35
+#define EXP_M2  92821
+#define EXP_B   66629747
+
+#define EXP_M1_1  365
+#define EXP_M2_1  658700
+#define EXP_B_1   305506134
+
+#define EXP_M1_2  189
+#define EXP_M2_2  379692
+#define EXP_B_2   194609469
+
+#define EXP_M1_3  99
+#define EXP_M2_3  217915
+#define EXP_B_3   122255994
+
+#define EXP_M1_4  51
+#define EXP_M2_4  122643
+#define EXP_B_4   74893384
+
+#define EXP_M1_5  423
+#define EXP_M2_5  1103326
+#define EXP_B_5   728122621
+
 enum SID_OPTION {
        SID_OPTION_HI,
        SID_OPTION_LO,
@@ -548,20 +572,20 @@ struct SMU74_Firmware_Header {
        uint32_t CacConfigTable;
        uint32_t CacStatusTable;
 
-
        uint32_t mcRegisterTable;
 
-
        uint32_t mcArbDramTimingTable;
 
-
-
-
        uint32_t PmFuseTable;
        uint32_t Globals;
        uint32_t ClockStretcherTable;
        uint32_t VftTable;
-       uint32_t Reserved[21];
+       uint32_t Reserved1;
+       uint32_t AvfsTable;
+       uint32_t AvfsCksOffGbvTable;
+       uint32_t AvfsMeanNSigma;
+       uint32_t AvfsSclkOffsetTable;
+       uint32_t Reserved[16];
        uint32_t Signature;
 };
 
@@ -701,8 +725,6 @@ VR Config info is contained in dpmTable.VRConfig */
 struct SMU_ClockStretcherDataTableEntry {
        uint8_t minVID;
        uint8_t maxVID;
-
-
        uint16_t setting;
 };
 typedef struct SMU_ClockStretcherDataTableEntry SMU_ClockStretcherDataTableEntry;
@@ -769,6 +791,43 @@ struct VFT_TABLE_t {
 typedef struct VFT_TABLE_t VFT_TABLE_t;
 
 
+/* Total margin, root mean square of Fmax + DC + Platform */
+struct AVFS_Margin_t {
+       VFT_CELL_t Cell[NUM_VFT_COLUMNS];
+};
+typedef struct AVFS_Margin_t AVFS_Margin_t;
+
+#define BTCGB_VDROOP_TABLE_MAX_ENTRIES 2
+#define AVFSGB_VDROOP_TABLE_MAX_ENTRIES 2
+
+struct GB_VDROOP_TABLE_t {
+       int32_t a0;
+       int32_t a1;
+       int32_t a2;
+       uint32_t spare;
+};
+typedef struct GB_VDROOP_TABLE_t GB_VDROOP_TABLE_t;
+
+struct AVFS_CksOff_Gbv_t {
+       VFT_CELL_t Cell[NUM_VFT_COLUMNS];
+};
+typedef struct AVFS_CksOff_Gbv_t AVFS_CksOff_Gbv_t;
+
+struct AVFS_meanNsigma_t {
+       uint32_t Aconstant[3];
+       uint16_t DC_tol_sigma;
+       uint16_t Platform_mean;
+       uint16_t Platform_sigma;
+       uint16_t PSM_Age_CompFactor;
+       uint8_t  Static_Voltage_Offset[NUM_VFT_COLUMNS];
+};
+typedef struct AVFS_meanNsigma_t AVFS_meanNsigma_t;
+
+struct AVFS_Sclk_Offset_t {
+       uint16_t Sclk_Offset[8];
+};
+typedef struct AVFS_Sclk_Offset_t AVFS_Sclk_Offset_t;
+
 #endif
 
 
index 0dfe823..b85ff54 100644 (file)
@@ -223,6 +223,16 @@ struct SMU74_Discrete_StateInfo {
 
 typedef struct SMU74_Discrete_StateInfo SMU74_Discrete_StateInfo;
 
+struct SMU_QuadraticCoeffs {
+       int32_t m1;
+       uint32_t b;
+
+       int16_t m2;
+       uint8_t m1_shift;
+       uint8_t m2_shift;
+};
+typedef struct SMU_QuadraticCoeffs SMU_QuadraticCoeffs;
+
 struct SMU74_Discrete_DpmTable {
 
        SMU74_PIDController                  GraphicsPIDController;
@@ -258,7 +268,14 @@ struct SMU74_Discrete_DpmTable {
        uint8_t                             ThermOutPolarity;
        uint8_t                             ThermOutMode;
        uint8_t                             BootPhases;
-       uint32_t                            Reserved[4];
+
+       uint8_t                             VRHotLevel;
+       uint8_t                             Reserved1[3];
+       uint16_t                            FanStartTemperature;
+       uint16_t                            FanStopTemperature;
+       uint16_t                            MaxVoltage;
+       uint16_t                            Reserved2;
+       uint32_t                            Reserved[1];
 
        SMU74_Discrete_GraphicsLevel        GraphicsLevel[SMU74_MAX_LEVELS_GRAPHICS];
        SMU74_Discrete_MemoryLevel          MemoryACPILevel;
@@ -347,6 +364,8 @@ struct SMU74_Discrete_DpmTable {
 
        uint32_t                            CurrSclkPllRange;
        sclkFcwRange_t                      SclkFcwRangeTable[NUM_SCLK_RANGE];
+       GB_VDROOP_TABLE_t                   BTCGB_VDROOP_TABLE[BTCGB_VDROOP_TABLE_MAX_ENTRIES];
+       SMU_QuadraticCoeffs                 AVFSGB_VDROOP_TABLE[AVFSGB_VDROOP_TABLE_MAX_ENTRIES];
 };
 
 typedef struct SMU74_Discrete_DpmTable SMU74_Discrete_DpmTable;
@@ -550,16 +569,6 @@ struct SMU7_AcpiScoreboard {
 
 typedef struct SMU7_AcpiScoreboard SMU7_AcpiScoreboard;
 
-struct SMU_QuadraticCoeffs {
-       int32_t m1;
-       uint32_t b;
-
-       int16_t m2;
-       uint8_t m1_shift;
-       uint8_t m2_shift;
-};
-typedef struct SMU_QuadraticCoeffs SMU_QuadraticCoeffs;
-
 struct SMU74_Discrete_PmFuses {
        uint8_t BapmVddCVidHiSidd[8];
        uint8_t BapmVddCVidLoSidd[8];
@@ -821,6 +830,17 @@ typedef struct SMU7_GfxCuPgScoreboard SMU7_GfxCuPgScoreboard;
 #define DB_PCC_SHIFT 26 
 #define DB_EDC_SHIFT 27
 
+#define BTCGB0_Vdroop_Enable_MASK  0x1
+#define BTCGB1_Vdroop_Enable_MASK  0x2
+#define AVFSGB0_Vdroop_Enable_MASK 0x4
+#define AVFSGB1_Vdroop_Enable_MASK 0x8
+
+#define BTCGB0_Vdroop_Enable_SHIFT  0
+#define BTCGB1_Vdroop_Enable_SHIFT  1
+#define AVFSGB0_Vdroop_Enable_SHIFT 2
+#define AVFSGB1_Vdroop_Enable_SHIFT 3
+
+
 #pragma pack(pop)
 
 
index 673a75c..8e52a2e 100644 (file)
@@ -1006,10 +1006,16 @@ static int fiji_smu_init(struct pp_smumgr *smumgr)
 
 static int fiji_smu_fini(struct pp_smumgr *smumgr)
 {
+       struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend);
+
+       smu_free_memory(smumgr->device, (void *)priv->header_buffer.handle);
+
        if (smumgr->backend) {
                kfree(smumgr->backend);
                smumgr->backend = NULL;
        }
+
+       cgs_rel_firmware(smumgr->device, CGS_UCODE_ID_SMU);
        return 0;
 }
 
index de618ea..5dba7c5 100644 (file)
 static const SMU74_Discrete_GraphicsLevel avfs_graphics_level_polaris10[8] = {
        /*  Min      pcie   DeepSleep Activity  CgSpll      CgSpll    CcPwr  CcPwr  Sclk         Enabled      Enabled                       Voltage    Power */
        /* Voltage, DpmLevel, DivId,  Level,  FuncCntl3,  FuncCntl4,  DynRm, DynRm1 Did, Padding,ForActivity, ForThrottle, UpHyst, DownHyst, DownHyst, Throttle */
-       { 0x3c0fd047, 0x00, 0x03, 0x1e00, 0x00200410, 0x87020000, 0, 0, 0x16, 0, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, { 0x30750000, 0, 0, 0, 0, 0, 0, 0 } },
-       { 0xa00fd047, 0x01, 0x04, 0x1e00, 0x00800510, 0x87020000, 0, 0, 0x16, 0, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, { 0x409c0000, 0, 0, 0, 0, 0, 0, 0 } },
-       { 0x0410d047, 0x01, 0x00, 0x1e00, 0x00600410, 0x87020000, 0, 0, 0x0e, 0, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, { 0x50c30000, 0, 0, 0, 0, 0, 0, 0 } },
-       { 0x6810d047, 0x01, 0x00, 0x1e00, 0x00800410, 0x87020000, 0, 0, 0x0c, 0, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, { 0x60ea0000, 0, 0, 0, 0, 0, 0, 0 } },
-       { 0xcc10d047, 0x01, 0x00, 0x1e00, 0x00e00410, 0x87020000, 0, 0, 0x0c, 0, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, { 0xe8fd0000, 0, 0, 0, 0, 0, 0, 0 } },
-       { 0x3011d047, 0x01, 0x00, 0x1e00, 0x00400510, 0x87020000, 0, 0, 0x0c, 0, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, { 0x70110100, 0, 0, 0, 0, 0, 0, 0 } },
-       { 0x9411d047, 0x01, 0x00, 0x1e00, 0x00a00510, 0x87020000, 0, 0, 0x0c, 0, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, { 0xf8240100, 0, 0, 0, 0, 0, 0, 0 } },
-       { 0xf811d047, 0x01, 0x00, 0x1e00, 0x00000610, 0x87020000, 0, 0, 0x0c, 0, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, { 0x80380100, 0, 0, 0, 0, 0, 0, 0 } }
+       { 0x100ea446, 0x00, 0x03, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0x30750000, 0x3000, 0, 0x2600, 0, 0, 0x0004, 0x8f02, 0xffff, 0x2f00, 0x300e, 0x2700 } },
+       { 0x400ea446, 0x01, 0x04, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0x409c0000, 0x2000, 0, 0x1e00, 1, 1, 0x0004, 0x8300, 0xffff, 0x1f00, 0xcb5e, 0x1a00 } },
+       { 0x740ea446, 0x01, 0x00, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0x50c30000, 0x2800, 0, 0x2000, 1, 1, 0x0004, 0x0c02, 0xffff, 0x2700, 0x6433, 0x2100 } },
+       { 0xa40ea446, 0x01, 0x00, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0x60ea0000, 0x3000, 0, 0x2600, 1, 1, 0x0004, 0x8f02, 0xffff, 0x2f00, 0x300e, 0x2700 } },
+       { 0xd80ea446, 0x01, 0x00, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0x70110100, 0x3800, 0, 0x2c00, 1, 1, 0x0004, 0x1203, 0xffff, 0x3600, 0xc9e2, 0x2e00 } },
+       { 0x3c0fa446, 0x01, 0x00, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0x80380100, 0x2000, 0, 0x1e00, 2, 1, 0x0004, 0x8300, 0xffff, 0x1f00, 0xcb5e, 0x1a00 } },
+       { 0x6c0fa446, 0x01, 0x00, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0x905f0100, 0x2400, 0, 0x1e00, 2, 1, 0x0004, 0x8901, 0xffff, 0x2300, 0x314c, 0x1d00 } },
+       { 0xa00fa446, 0x01, 0x00, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0xa0860100, 0x2800, 0, 0x2000, 2, 1, 0x0004, 0x0c02, 0xffff, 0x2700, 0x6433, 0x2100 } }
 };
 
 static const SMU74_Discrete_MemoryLevel avfs_memory_level_polaris10 =
-       {0x50140000, 0x50140000, 0x00320000, 0x00, 0x00,
-        0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x0000, 0x00, 0x00};
+       {0x100ea446, 0, 0x30750000, 0x01, 0x01, 0x01, 0x00, 0x00, 0x64, 0x00, 0x00, 0x1f00, 0x00, 0x00};
 
 /**
 * Set the address for reading/writing the SMC SRAM space.
@@ -219,6 +218,18 @@ bool polaris10_is_smc_ram_running(struct pp_smumgr *smumgr)
        && (0x20100 <= cgs_read_ind_register(smumgr->device, CGS_IND_REG__SMC, ixSMC_PC_C)));
 }
 
+static bool polaris10_is_hw_avfs_present(struct pp_smumgr *smumgr)
+{
+       uint32_t efuse;
+
+       efuse = cgs_read_ind_register(smumgr->device, CGS_IND_REG__SMC, ixSMU_EFUSE_0 + (49*4));
+       efuse &= 0x00000001;
+       if (efuse)
+               return true;
+
+       return false;
+}
+
 /**
 * Send a message to the SMC, and wait for its response.
 *
@@ -228,21 +239,27 @@ bool polaris10_is_smc_ram_running(struct pp_smumgr *smumgr)
 */
 int polaris10_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg)
 {
+       int ret;
+
        if (!polaris10_is_smc_ram_running(smumgr))
                return -1;
 
+
        SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0);
 
-       if (1 != SMUM_READ_FIELD(smumgr->device, SMC_RESP_0, SMC_RESP))
-               printk("Failed to send Previous Message.\n");
+       ret = SMUM_READ_FIELD(smumgr->device, SMC_RESP_0, SMC_RESP);
 
+       if (ret != 1)
+               printk("\n failed to send pre message %x ret is %d \n",  msg, ret);
 
        cgs_write_register(smumgr->device, mmSMC_MESSAGE_0, msg);
 
        SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0);
 
-       if (1 != SMUM_READ_FIELD(smumgr->device, SMC_RESP_0, SMC_RESP))
-               printk("Failed to send Message.\n");
+       ret = SMUM_READ_FIELD(smumgr->device, SMC_RESP_0, SMC_RESP);
+
+       if (ret != 1)
+               printk("\n failed to send message %x ret is %d \n",  msg, ret);
 
        return 0;
 }
@@ -469,6 +486,7 @@ int polaris10_smu_fini(struct pp_smumgr *smumgr)
                kfree(smumgr->backend);
                smumgr->backend = NULL;
        }
+       cgs_rel_firmware(smumgr->device, CGS_UCODE_ID_SMU);
        return 0;
 }
 
@@ -952,6 +970,11 @@ static int polaris10_smu_init(struct pp_smumgr *smumgr)
                (cgs_handle_t)smu_data->smu_buffer.handle);
                return -1;);
 
+       if (polaris10_is_hw_avfs_present(smumgr))
+               smu_data->avfs.avfs_btc_status = AVFS_BTC_BOOT;
+       else
+               smu_data->avfs.avfs_btc_status = AVFS_BTC_NOTSUPPORTED;
+
        return 0;
 }
 
index c483baf..0728c1e 100644 (file)
@@ -81,6 +81,7 @@ int smum_init(struct amd_pp_init *pp_init, struct pp_instance *handle)
 
 int smum_fini(struct pp_smumgr *smumgr)
 {
+       kfree(smumgr->device);
        kfree(smumgr);
        return 0;
 }
index 32820b6..b22722e 100644 (file)
@@ -328,10 +328,17 @@ int tonga_write_smc_sram_dword(struct pp_smumgr *smumgr,
 
 static int tonga_smu_fini(struct pp_smumgr *smumgr)
 {
+       struct tonga_smumgr *priv = (struct tonga_smumgr *)(smumgr->backend);
+
+       smu_free_memory(smumgr->device, (void *)priv->smu_buffer.handle);
+       smu_free_memory(smumgr->device, (void *)priv->header_buffer.handle);
+
        if (smumgr->backend != NULL) {
                kfree(smumgr->backend);
                smumgr->backend = NULL;
        }
+
+       cgs_rel_firmware(smumgr->device, CGS_UCODE_ID_SMU);
        return 0;
 }
 
index fef1b04..0813c2f 100644 (file)
  *
  */
 
+static void hdlcd_crtc_cleanup(struct drm_crtc *crtc)
+{
+       struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
+
+       /* stop the controller on cleanup */
+       hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 0);
+       drm_crtc_cleanup(crtc);
+}
+
 static const struct drm_crtc_funcs hdlcd_crtc_funcs = {
-       .destroy = drm_crtc_cleanup,
+       .destroy = hdlcd_crtc_cleanup,
        .set_config = drm_atomic_helper_set_config,
        .page_flip = drm_atomic_helper_page_flip,
        .reset = drm_atomic_helper_crtc_reset,
@@ -97,7 +106,7 @@ static void hdlcd_crtc_mode_set_nofb(struct drm_crtc *crtc)
        struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
        struct drm_display_mode *m = &crtc->state->adjusted_mode;
        struct videomode vm;
-       unsigned int polarities, line_length, err;
+       unsigned int polarities, err;
 
        vm.vfront_porch = m->crtc_vsync_start - m->crtc_vdisplay;
        vm.vback_porch = m->crtc_vtotal - m->crtc_vsync_end;
@@ -113,23 +122,18 @@ static void hdlcd_crtc_mode_set_nofb(struct drm_crtc *crtc)
        if (m->flags & DRM_MODE_FLAG_PVSYNC)
                polarities |= HDLCD_POLARITY_VSYNC;
 
-       line_length = crtc->primary->state->fb->pitches[0];
-
        /* Allow max number of outstanding requests and largest burst size */
        hdlcd_write(hdlcd, HDLCD_REG_BUS_OPTIONS,
                    HDLCD_BUS_MAX_OUTSTAND | HDLCD_BUS_BURST_16);
 
-       hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, line_length);
-       hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_PITCH, line_length);
-       hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_COUNT, m->crtc_vdisplay - 1);
        hdlcd_write(hdlcd, HDLCD_REG_V_DATA, m->crtc_vdisplay - 1);
        hdlcd_write(hdlcd, HDLCD_REG_V_BACK_PORCH, vm.vback_porch - 1);
        hdlcd_write(hdlcd, HDLCD_REG_V_FRONT_PORCH, vm.vfront_porch - 1);
        hdlcd_write(hdlcd, HDLCD_REG_V_SYNC, vm.vsync_len - 1);
+       hdlcd_write(hdlcd, HDLCD_REG_H_DATA, m->crtc_hdisplay - 1);
        hdlcd_write(hdlcd, HDLCD_REG_H_BACK_PORCH, vm.hback_porch - 1);
        hdlcd_write(hdlcd, HDLCD_REG_H_FRONT_PORCH, vm.hfront_porch - 1);
        hdlcd_write(hdlcd, HDLCD_REG_H_SYNC, vm.hsync_len - 1);
-       hdlcd_write(hdlcd, HDLCD_REG_H_DATA, m->crtc_hdisplay - 1);
        hdlcd_write(hdlcd, HDLCD_REG_POLARITIES, polarities);
 
        err = hdlcd_set_pxl_fmt(crtc);
@@ -144,20 +148,19 @@ static void hdlcd_crtc_enable(struct drm_crtc *crtc)
        struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
 
        clk_prepare_enable(hdlcd->clk);
+       hdlcd_crtc_mode_set_nofb(crtc);
        hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 1);
-       drm_crtc_vblank_on(crtc);
 }
 
 static void hdlcd_crtc_disable(struct drm_crtc *crtc)
 {
        struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
 
-       if (!crtc->primary->fb)
+       if (!crtc->state->active)
                return;
 
-       clk_disable_unprepare(hdlcd->clk);
        hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 0);
-       drm_crtc_vblank_off(crtc);
+       clk_disable_unprepare(hdlcd->clk);
 }
 
 static int hdlcd_crtc_atomic_check(struct drm_crtc *crtc,
@@ -179,20 +182,17 @@ static int hdlcd_crtc_atomic_check(struct drm_crtc *crtc,
 static void hdlcd_crtc_atomic_begin(struct drm_crtc *crtc,
                                    struct drm_crtc_state *state)
 {
-       struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
-       unsigned long flags;
-
-       if (crtc->state->event) {
-               struct drm_pending_vblank_event *event = crtc->state->event;
+       struct drm_pending_vblank_event *event = crtc->state->event;
 
+       if (event) {
                crtc->state->event = NULL;
-               event->pipe = drm_crtc_index(crtc);
-
-               WARN_ON(drm_crtc_vblank_get(crtc) != 0);
 
-               spin_lock_irqsave(&crtc->dev->event_lock, flags);
-               list_add_tail(&event->base.link, &hdlcd->event_list);
-               spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+               spin_lock_irq(&crtc->dev->event_lock);
+               if (drm_crtc_vblank_get(crtc) == 0)
+                       drm_crtc_arm_vblank_event(crtc, event);
+               else
+                       drm_crtc_send_vblank_event(crtc, event);
+               spin_unlock_irq(&crtc->dev->event_lock);
        }
 }
 
@@ -225,6 +225,15 @@ static const struct drm_crtc_helper_funcs hdlcd_crtc_helper_funcs = {
 static int hdlcd_plane_atomic_check(struct drm_plane *plane,
                                    struct drm_plane_state *state)
 {
+       u32 src_w, src_h;
+
+       src_w = state->src_w >> 16;
+       src_h = state->src_h >> 16;
+
+       /* we can't do any scaling of the plane source */
+       if ((src_w != state->crtc_w) || (src_h != state->crtc_h))
+               return -EINVAL;
+
        return 0;
 }
 
@@ -233,20 +242,31 @@ static void hdlcd_plane_atomic_update(struct drm_plane *plane,
 {
        struct hdlcd_drm_private *hdlcd;
        struct drm_gem_cma_object *gem;
+       unsigned int depth, bpp;
+       u32 src_w, src_h, dest_w, dest_h;
        dma_addr_t scanout_start;
 
-       if (!plane->state->crtc || !plane->state->fb)
+       if (!plane->state->fb)
                return;
 
-       hdlcd = crtc_to_hdlcd_priv(plane->state->crtc);
+       drm_fb_get_bpp_depth(plane->state->fb->pixel_format, &depth, &bpp);
+       src_w = plane->state->src_w >> 16;
+       src_h = plane->state->src_h >> 16;
+       dest_w = plane->state->crtc_w;
+       dest_h = plane->state->crtc_h;
        gem = drm_fb_cma_get_gem_obj(plane->state->fb, 0);
-       scanout_start = gem->paddr;
+       scanout_start = gem->paddr + plane->state->fb->offsets[0] +
+               plane->state->crtc_y * plane->state->fb->pitches[0] +
+               plane->state->crtc_x * bpp / 8;
+
+       hdlcd = plane->dev->dev_private;
+       hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, plane->state->fb->pitches[0]);
+       hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_PITCH, plane->state->fb->pitches[0]);
+       hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_COUNT, dest_h - 1);
        hdlcd_write(hdlcd, HDLCD_REG_FB_BASE, scanout_start);
 }
 
 static const struct drm_plane_helper_funcs hdlcd_plane_helper_funcs = {
-       .prepare_fb = NULL,
-       .cleanup_fb = NULL,
        .atomic_check = hdlcd_plane_atomic_check,
        .atomic_update = hdlcd_plane_atomic_update,
 };
@@ -294,16 +314,6 @@ static struct drm_plane *hdlcd_plane_init(struct drm_device *drm)
        return plane;
 }
 
-void hdlcd_crtc_suspend(struct drm_crtc *crtc)
-{
-       hdlcd_crtc_disable(crtc);
-}
-
-void hdlcd_crtc_resume(struct drm_crtc *crtc)
-{
-       hdlcd_crtc_enable(crtc);
-}
-
 int hdlcd_setup_crtc(struct drm_device *drm)
 {
        struct hdlcd_drm_private *hdlcd = drm->dev_private;
index b987c63..a6ca36f 100644 (file)
@@ -49,8 +49,6 @@ static int hdlcd_load(struct drm_device *drm, unsigned long flags)
        atomic_set(&hdlcd->dma_end_count, 0);
 #endif
 
-       INIT_LIST_HEAD(&hdlcd->event_list);
-
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        hdlcd->mmio = devm_ioremap_resource(drm->dev, res);
        if (IS_ERR(hdlcd->mmio)) {
@@ -84,11 +82,7 @@ static int hdlcd_load(struct drm_device *drm, unsigned long flags)
                goto setup_fail;
        }
 
-       pm_runtime_enable(drm->dev);
-
-       pm_runtime_get_sync(drm->dev);
        ret = drm_irq_install(drm, platform_get_irq(pdev, 0));
-       pm_runtime_put_sync(drm->dev);
        if (ret < 0) {
                DRM_ERROR("failed to install IRQ handler\n");
                goto irq_fail;
@@ -164,24 +158,9 @@ static irqreturn_t hdlcd_irq(int irq, void *arg)
                atomic_inc(&hdlcd->vsync_count);
 
 #endif
-       if (irq_status & HDLCD_INTERRUPT_VSYNC) {
-               bool events_sent = false;
-               unsigned long flags;
-               struct drm_pending_vblank_event *e, *t;
-
+       if (irq_status & HDLCD_INTERRUPT_VSYNC)
                drm_crtc_handle_vblank(&hdlcd->crtc);
 
-               spin_lock_irqsave(&drm->event_lock, flags);
-               list_for_each_entry_safe(e, t, &hdlcd->event_list, base.link) {
-                       list_del(&e->base.link);
-                       drm_crtc_send_vblank_event(&hdlcd->crtc, e);
-                       events_sent = true;
-               }
-               if (events_sent)
-                       drm_crtc_vblank_put(&hdlcd->crtc);
-               spin_unlock_irqrestore(&drm->event_lock, flags);
-       }
-
        /* acknowledge interrupt(s) */
        hdlcd_write(hdlcd, HDLCD_REG_INT_CLEAR, irq_status);
 
@@ -275,6 +254,7 @@ static int hdlcd_show_pxlclock(struct seq_file *m, void *arg)
 static struct drm_info_list hdlcd_debugfs_list[] = {
        { "interrupt_count", hdlcd_show_underrun_count, 0 },
        { "clocks", hdlcd_show_pxlclock, 0 },
+       { "fb", drm_fb_cma_debugfs_show, 0 },
 };
 
 static int hdlcd_debugfs_init(struct drm_minor *minor)
@@ -357,6 +337,8 @@ static int hdlcd_drm_bind(struct device *dev)
                return -ENOMEM;
 
        drm->dev_private = hdlcd;
+       dev_set_drvdata(dev, drm);
+
        hdlcd_setup_mode_config(drm);
        ret = hdlcd_load(drm, 0);
        if (ret)
@@ -366,14 +348,18 @@ static int hdlcd_drm_bind(struct device *dev)
        if (ret)
                goto err_unload;
 
-       dev_set_drvdata(dev, drm);
-
        ret = component_bind_all(dev, drm);
        if (ret) {
                DRM_ERROR("Failed to bind all components\n");
                goto err_unregister;
        }
 
+       ret = pm_runtime_set_active(dev);
+       if (ret)
+               goto err_pm_active;
+
+       pm_runtime_enable(dev);
+
        ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
        if (ret < 0) {
                DRM_ERROR("failed to initialise vblank\n");
@@ -399,16 +385,16 @@ err_fbdev:
        drm_mode_config_cleanup(drm);
        drm_vblank_cleanup(drm);
 err_vblank:
+       pm_runtime_disable(drm->dev);
+err_pm_active:
        component_unbind_all(dev, drm);
 err_unregister:
        drm_dev_unregister(drm);
 err_unload:
-       pm_runtime_get_sync(drm->dev);
        drm_irq_uninstall(drm);
-       pm_runtime_put_sync(drm->dev);
-       pm_runtime_disable(drm->dev);
        of_reserved_mem_device_release(drm->dev);
 err_free:
+       dev_set_drvdata(dev, NULL);
        drm_dev_unref(drm);
 
        return ret;
@@ -495,30 +481,34 @@ MODULE_DEVICE_TABLE(of, hdlcd_of_match);
 static int __maybe_unused hdlcd_pm_suspend(struct device *dev)
 {
        struct drm_device *drm = dev_get_drvdata(dev);
-       struct drm_crtc *crtc;
+       struct hdlcd_drm_private *hdlcd = drm ? drm->dev_private : NULL;
 
-       if (pm_runtime_suspended(dev))
+       if (!hdlcd)
                return 0;
 
-       drm_modeset_lock_all(drm);
-       list_for_each_entry(crtc, &drm->mode_config.crtc_list, head)
-               hdlcd_crtc_suspend(crtc);
-       drm_modeset_unlock_all(drm);
+       drm_kms_helper_poll_disable(drm);
+
+       hdlcd->state = drm_atomic_helper_suspend(drm);
+       if (IS_ERR(hdlcd->state)) {
+               drm_kms_helper_poll_enable(drm);
+               return PTR_ERR(hdlcd->state);
+       }
+
        return 0;
 }
 
 static int __maybe_unused hdlcd_pm_resume(struct device *dev)
 {
        struct drm_device *drm = dev_get_drvdata(dev);
-       struct drm_crtc *crtc;
+       struct hdlcd_drm_private *hdlcd = drm ? drm->dev_private : NULL;
 
-       if (!pm_runtime_suspended(dev))
+       if (!hdlcd)
                return 0;
 
-       drm_modeset_lock_all(drm);
-       list_for_each_entry(crtc, &drm->mode_config.crtc_list, head)
-               hdlcd_crtc_resume(crtc);
-       drm_modeset_unlock_all(drm);
+       drm_atomic_helper_resume(drm, hdlcd->state);
+       drm_kms_helper_poll_enable(drm);
+       pm_runtime_set_active(dev);
+
        return 0;
 }
 
index aa23478..e3950a0 100644 (file)
@@ -9,10 +9,9 @@ struct hdlcd_drm_private {
        void __iomem                    *mmio;
        struct clk                      *clk;
        struct drm_fbdev_cma            *fbdev;
-       struct drm_framebuffer          *fb;
-       struct list_head                event_list;
        struct drm_crtc                 crtc;
        struct drm_plane                *plane;
+       struct drm_atomic_state         *state;
 #ifdef CONFIG_DEBUG_FS
        atomic_t buffer_underrun_count;
        atomic_t bus_error_count;
@@ -36,7 +35,5 @@ static inline u32 hdlcd_read(struct hdlcd_drm_private *hdlcd, unsigned int reg)
 
 int hdlcd_setup_crtc(struct drm_device *dev);
 void hdlcd_set_scanout(struct hdlcd_drm_private *hdlcd);
-void hdlcd_crtc_suspend(struct drm_crtc *crtc);
-void hdlcd_crtc_resume(struct drm_crtc *crtc);
 
 #endif /* __HDLCD_DRV_H__ */
index cf23a75..bd12231 100644 (file)
@@ -391,12 +391,11 @@ void atmel_hlcdc_crtc_reset(struct drm_crtc *crtc)
 {
        struct atmel_hlcdc_crtc_state *state;
 
-       if (crtc->state && crtc->state->mode_blob)
-               drm_property_unreference_blob(crtc->state->mode_blob);
-
        if (crtc->state) {
+               __drm_atomic_helper_crtc_destroy_state(crtc->state);
                state = drm_crtc_state_to_atmel_hlcdc_crtc_state(crtc->state);
                kfree(state);
+               crtc->state = NULL;
        }
 
        state = kzalloc(sizeof(*state), GFP_KERNEL);
@@ -415,8 +414,9 @@ atmel_hlcdc_crtc_duplicate_state(struct drm_crtc *crtc)
                return NULL;
 
        state = kmalloc(sizeof(*state), GFP_KERNEL);
-       if (state)
-               __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base);
+       if (!state)
+               return NULL;
+       __drm_atomic_helper_crtc_duplicate_state(crtc, &state->base);
 
        cur = drm_crtc_state_to_atmel_hlcdc_crtc_state(crtc->state);
        state->output_mode = cur->output_mode;
index 39802c0..3d34fc4 100644 (file)
@@ -266,9 +266,10 @@ int atmel_hlcdc_create_outputs(struct drm_device *dev)
                if (!ret)
                        ret = atmel_hlcdc_check_endpoint(dev, &ep);
 
-               of_node_put(ep_np);
-               if (ret)
+               if (ret) {
+                       of_node_put(ep_np);
                        return ret;
+               }
        }
 
        for_each_endpoint_of_node(dev->dev->of_node, ep_np) {
@@ -276,9 +277,10 @@ int atmel_hlcdc_create_outputs(struct drm_device *dev)
                if (!ret)
                        ret = atmel_hlcdc_attach_endpoint(dev, &ep);
 
-               of_node_put(ep_np);
-               if (ret)
+               if (ret) {
+                       of_node_put(ep_np);
                        return ret;
+               }
        }
 
        return 0;
index aef3ca8..016c191 100644 (file)
@@ -339,6 +339,8 @@ atmel_hlcdc_plane_update_pos_and_size(struct atmel_hlcdc_plane *plane,
 
                atmel_hlcdc_layer_update_cfg(&plane->layer, 13, 0xffffffff,
                                             factor_reg);
+       } else {
+               atmel_hlcdc_layer_update_cfg(&plane->layer, 13, 0xffffffff, 0);
        }
 }
 
index 3ff1ed7..9bb99e2 100644 (file)
@@ -351,6 +351,8 @@ int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
        drm_property_unreference_blob(state->mode_blob);
        state->mode_blob = NULL;
 
+       memset(&state->mode, 0, sizeof(state->mode));
+
        if (blob) {
                if (blob->length != sizeof(struct drm_mode_modeinfo) ||
                    drm_mode_convert_umode(&state->mode,
@@ -363,7 +365,6 @@ int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
                DRM_DEBUG_ATOMIC("Set [MODE:%s] for CRTC state %p\n",
                                 state->mode.name, state);
        } else {
-               memset(&state->mode, 0, sizeof(state->mode));
                state->enable = false;
                DRM_DEBUG_ATOMIC("Set [NOMODE] for CRTC state %p\n",
                                 state);
@@ -1295,14 +1296,39 @@ EXPORT_SYMBOL(drm_atomic_add_affected_planes);
  */
 void drm_atomic_legacy_backoff(struct drm_atomic_state *state)
 {
+       struct drm_device *dev = state->dev;
+       unsigned crtc_mask = 0;
+       struct drm_crtc *crtc;
        int ret;
+       bool global = false;
+
+       drm_for_each_crtc(crtc, dev) {
+               if (crtc->acquire_ctx != state->acquire_ctx)
+                       continue;
+
+               crtc_mask |= drm_crtc_mask(crtc);
+               crtc->acquire_ctx = NULL;
+       }
+
+       if (WARN_ON(dev->mode_config.acquire_ctx == state->acquire_ctx)) {
+               global = true;
+
+               dev->mode_config.acquire_ctx = NULL;
+       }
 
 retry:
        drm_modeset_backoff(state->acquire_ctx);
 
-       ret = drm_modeset_lock_all_ctx(state->dev, state->acquire_ctx);
+       ret = drm_modeset_lock_all_ctx(dev, state->acquire_ctx);
        if (ret)
                goto retry;
+
+       drm_for_each_crtc(crtc, dev)
+               if (drm_crtc_mask(crtc) & crtc_mask)
+                       crtc->acquire_ctx = state->acquire_ctx;
+
+       if (global)
+               dev->mode_config.acquire_ctx = state->acquire_ctx;
 }
 EXPORT_SYMBOL(drm_atomic_legacy_backoff);
 
index d2a6d95..0e3cc66 100644 (file)
@@ -2821,8 +2821,6 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
                        goto out;
                }
 
-               drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
-
                /*
                 * Check whether the primary plane supports the fb pixel format.
                 * Drivers not implementing the universal planes API use a
@@ -4841,7 +4839,8 @@ bool drm_property_change_valid_get(struct drm_property *property,
                if (value == 0)
                        return true;
 
-               return _object_find(property->dev, value, property->values[0]) != NULL;
+               *ref = _object_find(property->dev, value, property->values[0]);
+               return *ref != NULL;
        }
 
        for (i = 0; i < property->num_values; i++)
index a6e4243..26feb2f 100644 (file)
@@ -528,11 +528,11 @@ drm_crtc_helper_disable(struct drm_crtc *crtc)
 int drm_crtc_helper_set_config(struct drm_mode_set *set)
 {
        struct drm_device *dev;
-       struct drm_crtc *new_crtc;
-       struct drm_encoder *save_encoders, *new_encoder, *encoder;
+       struct drm_crtc **save_encoder_crtcs, *new_crtc;
+       struct drm_encoder **save_connector_encoders, *new_encoder, *encoder;
        bool mode_changed = false; /* if true do a full mode set */
        bool fb_changed = false; /* if true and !mode_changed just do a flip */
-       struct drm_connector *save_connectors, *connector;
+       struct drm_connector *connector;
        int count = 0, ro, fail = 0;
        const struct drm_crtc_helper_funcs *crtc_funcs;
        struct drm_mode_set save_set;
@@ -574,15 +574,15 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
         * Allocate space for the backup of all (non-pointer) encoder and
         * connector data.
         */
-       save_encoders = kzalloc(dev->mode_config.num_encoder *
-                               sizeof(struct drm_encoder), GFP_KERNEL);
-       if (!save_encoders)
+       save_encoder_crtcs = kzalloc(dev->mode_config.num_encoder *
+                               sizeof(struct drm_crtc *), GFP_KERNEL);
+       if (!save_encoder_crtcs)
                return -ENOMEM;
 
-       save_connectors = kzalloc(dev->mode_config.num_connector *
-                               sizeof(struct drm_connector), GFP_KERNEL);
-       if (!save_connectors) {
-               kfree(save_encoders);
+       save_connector_encoders = kzalloc(dev->mode_config.num_connector *
+                               sizeof(struct drm_encoder *), GFP_KERNEL);
+       if (!save_connector_encoders) {
+               kfree(save_encoder_crtcs);
                return -ENOMEM;
        }
 
@@ -593,12 +593,12 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
         */
        count = 0;
        drm_for_each_encoder(encoder, dev) {
-               save_encoders[count++] = *encoder;
+               save_encoder_crtcs[count++] = encoder->crtc;
        }
 
        count = 0;
        drm_for_each_connector(connector, dev) {
-               save_connectors[count++] = *connector;
+               save_connector_encoders[count++] = connector->encoder;
        }
 
        save_set.crtc = set->crtc;
@@ -631,8 +631,12 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
                mode_changed = true;
        }
 
-       /* take a reference on all connectors in set */
+       /* take a reference on all unbound connectors in set, reuse the
+        * already taken reference for bound connectors
+        */
        for (ro = 0; ro < set->num_connectors; ro++) {
+               if (set->connectors[ro]->encoder)
+                       continue;
                drm_connector_reference(set->connectors[ro]);
        }
 
@@ -754,30 +758,28 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
                }
        }
 
-       /* after fail drop reference on all connectors in save set */
-       count = 0;
-       drm_for_each_connector(connector, dev) {
-               drm_connector_unreference(&save_connectors[count++]);
-       }
-
-       kfree(save_connectors);
-       kfree(save_encoders);
+       kfree(save_connector_encoders);
+       kfree(save_encoder_crtcs);
        return 0;
 
 fail:
        /* Restore all previous data. */
        count = 0;
        drm_for_each_encoder(encoder, dev) {
-               *encoder = save_encoders[count++];
+               encoder->crtc = save_encoder_crtcs[count++];
        }
 
        count = 0;
        drm_for_each_connector(connector, dev) {
-               *connector = save_connectors[count++];
+               connector->encoder = save_connector_encoders[count++];
        }
 
-       /* after fail drop reference on all connectors in set */
+       /* after fail drop reference on all unbound connectors in set, let
+        * bound connectors keep their reference
+        */
        for (ro = 0; ro < set->num_connectors; ro++) {
+               if (set->connectors[ro]->encoder)
+                       continue;
                drm_connector_unreference(set->connectors[ro]);
        }
 
@@ -787,8 +789,8 @@ fail:
                                      save_set.y, save_set.fb))
                DRM_ERROR("failed to restore config after modeset failure\n");
 
-       kfree(save_connectors);
-       kfree(save_encoders);
+       kfree(save_connector_encoders);
+       kfree(save_encoder_crtcs);
        return ret;
 }
 EXPORT_SYMBOL(drm_crtc_helper_set_config);
index a13edf5..6537908 100644 (file)
@@ -2927,11 +2927,9 @@ static void drm_dp_destroy_connector_work(struct work_struct *work)
                drm_dp_port_teardown_pdt(port, port->pdt);
 
                if (!port->input && port->vcpi.vcpi > 0) {
-                       if (mgr->mst_state) {
-                               drm_dp_mst_reset_vcpi_slots(mgr, port);
-                               drm_dp_update_payload_part1(mgr);
-                               drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi);
-                       }
+                       drm_dp_mst_reset_vcpi_slots(mgr, port);
+                       drm_dp_update_payload_part1(mgr);
+                       drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi);
                }
 
                kref_put(&port->kref, drm_dp_free_mst_port);
index 172cafe..5075fae 100644 (file)
@@ -445,7 +445,7 @@ err_cma_destroy:
 err_fb_info_destroy:
        drm_fb_helper_release_fbi(helper);
 err_gem_free_object:
-       dev->driver->gem_free_object(&obj->base);
+       drm_gem_object_unreference_unlocked(&obj->base);
        return ret;
 }
 EXPORT_SYMBOL(drm_fbdev_cma_create_with_funcs);
index e1ab008..1d6c335 100644 (file)
@@ -121,7 +121,7 @@ struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm,
        return cma_obj;
 
 error:
-       drm->driver->gem_free_object(&cma_obj->base);
+       drm_gem_object_unreference_unlocked(&cma_obj->base);
        return ERR_PTR(ret);
 }
 EXPORT_SYMBOL_GPL(drm_gem_cma_create);
@@ -162,18 +162,12 @@ drm_gem_cma_create_with_handle(struct drm_file *file_priv,
         * and handle has the id what user can see.
         */
        ret = drm_gem_handle_create(file_priv, gem_obj, handle);
-       if (ret)
-               goto err_handle_create;
-
        /* drop reference from allocate - handle holds it now. */
        drm_gem_object_unreference_unlocked(gem_obj);
+       if (ret)
+               return ERR_PTR(ret);
 
        return cma_obj;
-
-err_handle_create:
-       drm->driver->gem_free_object(gem_obj);
-
-       return ERR_PTR(ret);
 }
 
 /**
index 7def3d5..e5e6f50 100644 (file)
@@ -1518,6 +1518,8 @@ int drm_mode_convert_umode(struct drm_display_mode *out,
        if (out->status != MODE_OK)
                goto out;
 
+       drm_mode_set_crtcinfo(out, CRTC_INTERLACE_HALVE_V);
+
        ret = 0;
 
 out:
index 522cfd4..16353ee 100644 (file)
@@ -225,6 +225,7 @@ struct iommu_domain *etnaviv_iommu_domain_alloc(struct etnaviv_gpu *gpu)
 
        etnaviv_domain->domain.type = __IOMMU_DOMAIN_PAGING;
        etnaviv_domain->domain.ops = &etnaviv_iommu_ops.ops;
+       etnaviv_domain->domain.pgsize_bitmap = SZ_4K;
        etnaviv_domain->domain.geometry.aperture_start = GPU_MEM_START;
        etnaviv_domain->domain.geometry.aperture_end = GPU_MEM_START + PT_ENTRIES * SZ_4K - 1;
 
index f6223f9..7f9901b 100644 (file)
@@ -31,7 +31,6 @@
 #include "exynos_drm_plane.h"
 #include "exynos_drm_drv.h"
 #include "exynos_drm_fb.h"
-#include "exynos_drm_fbdev.h"
 #include "exynos_drm_iommu.h"
 
 /*
index 468498e..4c1fb3f 100644 (file)
@@ -34,7 +34,7 @@
 
 struct exynos_dp_device {
        struct drm_encoder         encoder;
-       struct drm_connector       connector;
+       struct drm_connector       *connector;
        struct drm_bridge          *ptn_bridge;
        struct drm_device          *drm_dev;
        struct device              *dev;
@@ -70,7 +70,7 @@ static int exynos_dp_poweroff(struct analogix_dp_plat_data *plat_data)
 static int exynos_dp_get_modes(struct analogix_dp_plat_data *plat_data)
 {
        struct exynos_dp_device *dp = to_dp(plat_data);
-       struct drm_connector *connector = &dp->connector;
+       struct drm_connector *connector = dp->connector;
        struct drm_display_mode *mode;
        int num_modes = 0;
 
@@ -103,6 +103,7 @@ static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data,
        int ret;
 
        drm_connector_register(connector);
+       dp->connector = connector;
 
        /* Pre-empt DP connector creation if there's a bridge */
        if (dp->ptn_bridge) {
index 011211e..edbd98f 100644 (file)
@@ -15,7 +15,6 @@
 #include <drm/drmP.h>
 #include "exynos_drm_drv.h"
 #include "exynos_drm_crtc.h"
-#include "exynos_drm_fbdev.h"
 
 static LIST_HEAD(exynos_drm_subdrv_list);
 
index 3efe1aa..d472164 100644 (file)
@@ -30,7 +30,6 @@
 
 #include "exynos_drm_drv.h"
 #include "exynos_drm_fb.h"
-#include "exynos_drm_fbdev.h"
 #include "exynos_drm_crtc.h"
 #include "exynos_drm_plane.h"
 #include "exynos_drm_iommu.h"
@@ -120,7 +119,6 @@ static struct fimd_driver_data s3c64xx_fimd_driver_data = {
        .timing_base = 0x0,
        .has_clksel = 1,
        .has_limited_fmt = 1,
-       .has_hw_trigger = 1,
 };
 
 static struct fimd_driver_data exynos3_fimd_driver_data = {
@@ -171,14 +169,11 @@ static struct fimd_driver_data exynos5420_fimd_driver_data = {
        .lcdblk_vt_shift = 24,
        .lcdblk_bypass_shift = 15,
        .lcdblk_mic_bypass_shift = 11,
-       .trg_type = I80_HW_TRG,
        .has_shadowcon = 1,
        .has_vidoutcon = 1,
        .has_vtsel = 1,
        .has_mic_bypass = 1,
        .has_dp_clk = 1,
-       .has_hw_trigger = 1,
-       .has_trigger_per_te = 1,
 };
 
 struct fimd_context {
index 4935523..8564c3d 100644 (file)
 
 /* registers for base address */
 #define G2D_SRC_BASE_ADDR              0x0304
-#define G2D_SRC_STRIDE_REG             0x0308
+#define G2D_SRC_STRIDE                 0x0308
 #define G2D_SRC_COLOR_MODE             0x030C
 #define G2D_SRC_LEFT_TOP               0x0310
 #define G2D_SRC_RIGHT_BOTTOM           0x0314
 #define G2D_SRC_PLANE2_BASE_ADDR       0x0318
 #define G2D_DST_BASE_ADDR              0x0404
-#define G2D_DST_STRIDE_REG             0x0408
+#define G2D_DST_STRIDE                 0x0408
 #define G2D_DST_COLOR_MODE             0x040C
 #define G2D_DST_LEFT_TOP               0x0410
 #define G2D_DST_RIGHT_BOTTOM           0x0414
@@ -563,7 +563,7 @@ static enum g2d_reg_type g2d_get_reg_type(int reg_offset)
 
        switch (reg_offset) {
        case G2D_SRC_BASE_ADDR:
-       case G2D_SRC_STRIDE_REG:
+       case G2D_SRC_STRIDE:
        case G2D_SRC_COLOR_MODE:
        case G2D_SRC_LEFT_TOP:
        case G2D_SRC_RIGHT_BOTTOM:
@@ -573,7 +573,7 @@ static enum g2d_reg_type g2d_get_reg_type(int reg_offset)
                reg_type = REG_TYPE_SRC_PLANE2;
                break;
        case G2D_DST_BASE_ADDR:
-       case G2D_DST_STRIDE_REG:
+       case G2D_DST_STRIDE:
        case G2D_DST_COLOR_MODE:
        case G2D_DST_LEFT_TOP:
        case G2D_DST_RIGHT_BOTTOM:
@@ -968,8 +968,8 @@ static int g2d_check_reg_offset(struct device *dev,
                        } else
                                buf_info->types[reg_type] = BUF_TYPE_GEM;
                        break;
-               case G2D_SRC_STRIDE_REG:
-               case G2D_DST_STRIDE_REG:
+               case G2D_SRC_STRIDE:
+               case G2D_DST_STRIDE:
                        if (for_addr)
                                goto err;
 
index 55f1d37..77f12c0 100644 (file)
@@ -242,7 +242,7 @@ exynos_drm_plane_check_size(const struct exynos_drm_plane_config *config,
            state->v_ratio == (1 << 15))
                height_ok = true;
 
-       if (width_ok & height_ok)
+       if (width_ok && height_ok)
                return 0;
 
        DRM_DEBUG_KMS("scaling mode is not supported");
index 0ec1ad9..dc723f7 100644 (file)
@@ -42,9 +42,10 @@ static const struct regmap_config fsl_dcu_regmap_config = {
        .reg_bits = 32,
        .reg_stride = 4,
        .val_bits = 32,
-       .cache_type = REGCACHE_RBTREE,
+       .cache_type = REGCACHE_FLAT,
 
        .volatile_reg = fsl_dcu_drm_is_volatile_reg,
+       .max_register = 0x11fc,
 };
 
 static int fsl_dcu_drm_irq_init(struct drm_device *dev)
index 5faacc6..7c334e9 100644 (file)
@@ -3481,6 +3481,7 @@ int intel_bios_init(struct drm_i915_private *dev_priv);
 bool intel_bios_is_valid_vbt(const void *buf, size_t size);
 bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv);
 bool intel_bios_is_lvds_present(struct drm_i915_private *dev_priv, u8 *i2c_pin);
+bool intel_bios_is_port_present(struct drm_i915_private *dev_priv, enum port port);
 bool intel_bios_is_port_edp(struct drm_i915_private *dev_priv, enum port port);
 bool intel_bios_is_port_dp_dual_mode(struct drm_i915_private *dev_priv, enum port port);
 bool intel_bios_is_dsi_present(struct drm_i915_private *dev_priv, enum port *port);
index b235b6e..b9022fa 100644 (file)
@@ -139,6 +139,11 @@ fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
        else
                panel_fixed_mode->flags |= DRM_MODE_FLAG_NVSYNC;
 
+       panel_fixed_mode->width_mm = (dvo_timing->himage_hi << 8) |
+               dvo_timing->himage_lo;
+       panel_fixed_mode->height_mm = (dvo_timing->vimage_hi << 8) |
+               dvo_timing->vimage_lo;
+
        /* Some VBTs have bogus h/vtotal values */
        if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal)
                panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1;
@@ -1187,7 +1192,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
        }
        if (bdb->version < 106) {
                expected_size = 22;
-       } else if (bdb->version < 109) {
+       } else if (bdb->version < 111) {
                expected_size = 27;
        } else if (bdb->version < 195) {
                BUILD_BUG_ON(sizeof(struct old_child_dev_config) != 33);
@@ -1545,6 +1550,45 @@ bool intel_bios_is_lvds_present(struct drm_i915_private *dev_priv, u8 *i2c_pin)
        return false;
 }
 
+/**
+ * intel_bios_is_port_present - is the specified digital port present
+ * @dev_priv:  i915 device instance
+ * @port:      port to check
+ *
+ * Return true if the device in %port is present.
+ */
+bool intel_bios_is_port_present(struct drm_i915_private *dev_priv, enum port port)
+{
+       static const struct {
+               u16 dp, hdmi;
+       } port_mapping[] = {
+               [PORT_B] = { DVO_PORT_DPB, DVO_PORT_HDMIB, },
+               [PORT_C] = { DVO_PORT_DPC, DVO_PORT_HDMIC, },
+               [PORT_D] = { DVO_PORT_DPD, DVO_PORT_HDMID, },
+               [PORT_E] = { DVO_PORT_DPE, DVO_PORT_HDMIE, },
+       };
+       int i;
+
+       /* FIXME maybe deal with port A as well? */
+       if (WARN_ON(port == PORT_A) || port >= ARRAY_SIZE(port_mapping))
+               return false;
+
+       if (!dev_priv->vbt.child_dev_num)
+               return false;
+
+       for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
+               const union child_device_config *p_child =
+                       &dev_priv->vbt.child_dev[i];
+               if ((p_child->common.dvo_port == port_mapping[port].dp ||
+                    p_child->common.dvo_port == port_mapping[port].hdmi) &&
+                   (p_child->common.device_type & (DEVICE_TYPE_TMDS_DVI_SIGNALING |
+                                                   DEVICE_TYPE_DISPLAYPORT_OUTPUT)))
+                       return true;
+       }
+
+       return false;
+}
+
 /**
  * intel_bios_is_port_edp - is the device in given port eDP
  * @dev_priv:  i915 device instance
index 2113f40..56a1637 100644 (file)
@@ -8275,12 +8275,14 @@ static void ironlake_init_pch_refclk(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_encoder *encoder;
+       int i;
        u32 val, final;
        bool has_lvds = false;
        bool has_cpu_edp = false;
        bool has_panel = false;
        bool has_ck505 = false;
        bool can_ssc = false;
+       bool using_ssc_source = false;
 
        /* We need to take the global config into account */
        for_each_intel_encoder(dev, encoder) {
@@ -8307,8 +8309,22 @@ static void ironlake_init_pch_refclk(struct drm_device *dev)
                can_ssc = true;
        }
 
-       DRM_DEBUG_KMS("has_panel %d has_lvds %d has_ck505 %d\n",
-                     has_panel, has_lvds, has_ck505);
+       /* Check if any DPLLs are using the SSC source */
+       for (i = 0; i < dev_priv->num_shared_dpll; i++) {
+               u32 temp = I915_READ(PCH_DPLL(i));
+
+               if (!(temp & DPLL_VCO_ENABLE))
+                       continue;
+
+               if ((temp & PLL_REF_INPUT_MASK) ==
+                   PLLB_REF_INPUT_SPREADSPECTRUMIN) {
+                       using_ssc_source = true;
+                       break;
+               }
+       }
+
+       DRM_DEBUG_KMS("has_panel %d has_lvds %d has_ck505 %d using_ssc_source %d\n",
+                     has_panel, has_lvds, has_ck505, using_ssc_source);
 
        /* Ironlake: try to setup display ref clock before DPLL
         * enabling. This is only under driver's control after
@@ -8345,9 +8361,9 @@ static void ironlake_init_pch_refclk(struct drm_device *dev)
                                final |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
                } else
                        final |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
-       } else {
-               final |= DREF_SSC_SOURCE_DISABLE;
-               final |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
+       } else if (using_ssc_source) {
+               final |= DREF_SSC_SOURCE_ENABLE;
+               final |= DREF_SSC1_ENABLE;
        }
 
        if (final == val)
@@ -8393,7 +8409,7 @@ static void ironlake_init_pch_refclk(struct drm_device *dev)
                POSTING_READ(PCH_DREF_CONTROL);
                udelay(200);
        } else {
-               DRM_DEBUG_KMS("Disabling SSC entirely\n");
+               DRM_DEBUG_KMS("Disabling CPU source output\n");
 
                val &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
 
@@ -8404,16 +8420,20 @@ static void ironlake_init_pch_refclk(struct drm_device *dev)
                POSTING_READ(PCH_DREF_CONTROL);
                udelay(200);
 
-               /* Turn off the SSC source */
-               val &= ~DREF_SSC_SOURCE_MASK;
-               val |= DREF_SSC_SOURCE_DISABLE;
+               if (!using_ssc_source) {
+                       DRM_DEBUG_KMS("Disabling SSC source\n");
 
-               /* Turn off SSC1 */
-               val &= ~DREF_SSC1_ENABLE;
+                       /* Turn off the SSC source */
+                       val &= ~DREF_SSC_SOURCE_MASK;
+                       val |= DREF_SSC_SOURCE_DISABLE;
 
-               I915_WRITE(PCH_DREF_CONTROL, val);
-               POSTING_READ(PCH_DREF_CONTROL);
-               udelay(200);
+                       /* Turn off SSC1 */
+                       val &= ~DREF_SSC1_ENABLE;
+
+                       I915_WRITE(PCH_DREF_CONTROL, val);
+                       POSTING_READ(PCH_DREF_CONTROL);
+                       udelay(200);
+               }
        }
 
        BUG_ON(val != final);
@@ -14554,6 +14574,8 @@ static void intel_setup_outputs(struct drm_device *dev)
                if (I915_READ(PCH_DP_D) & DP_DETECTED)
                        intel_dp_init(dev, PCH_DP_D, PORT_D);
        } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+               bool has_edp, has_port;
+
                /*
                 * The DP_DETECTED bit is the latched state of the DDC
                 * SDA pin at boot. However since eDP doesn't require DDC
@@ -14562,27 +14584,37 @@ static void intel_setup_outputs(struct drm_device *dev)
                 * Thus we can't rely on the DP_DETECTED bit alone to detect
                 * eDP ports. Consult the VBT as well as DP_DETECTED to
                 * detect eDP ports.
+                *
+                * Sadly the straps seem to be missing sometimes even for HDMI
+                * ports (eg. on Voyo V3 - CHT x7-Z8700), so check both strap
+                * and VBT for the presence of the port. Additionally we can't
+                * trust the port type the VBT declares as we've seen at least
+                * HDMI ports that the VBT claim are DP or eDP.
                 */
-               if (I915_READ(VLV_HDMIB) & SDVO_DETECTED &&
-                   !intel_dp_is_edp(dev, PORT_B))
+               has_edp = intel_dp_is_edp(dev, PORT_B);
+               has_port = intel_bios_is_port_present(dev_priv, PORT_B);
+               if (I915_READ(VLV_DP_B) & DP_DETECTED || has_port)
+                       has_edp &= intel_dp_init(dev, VLV_DP_B, PORT_B);
+               if ((I915_READ(VLV_HDMIB) & SDVO_DETECTED || has_port) && !has_edp)
                        intel_hdmi_init(dev, VLV_HDMIB, PORT_B);
-               if (I915_READ(VLV_DP_B) & DP_DETECTED ||
-                   intel_dp_is_edp(dev, PORT_B))
-                       intel_dp_init(dev, VLV_DP_B, PORT_B);
 
-               if (I915_READ(VLV_HDMIC) & SDVO_DETECTED &&
-                   !intel_dp_is_edp(dev, PORT_C))
+               has_edp = intel_dp_is_edp(dev, PORT_C);
+               has_port = intel_bios_is_port_present(dev_priv, PORT_C);
+               if (I915_READ(VLV_DP_C) & DP_DETECTED || has_port)
+                       has_edp &= intel_dp_init(dev, VLV_DP_C, PORT_C);
+               if ((I915_READ(VLV_HDMIC) & SDVO_DETECTED || has_port) && !has_edp)
                        intel_hdmi_init(dev, VLV_HDMIC, PORT_C);
-               if (I915_READ(VLV_DP_C) & DP_DETECTED ||
-                   intel_dp_is_edp(dev, PORT_C))
-                       intel_dp_init(dev, VLV_DP_C, PORT_C);
 
                if (IS_CHERRYVIEW(dev)) {
-                       /* eDP not supported on port D, so don't check VBT */
-                       if (I915_READ(CHV_HDMID) & SDVO_DETECTED)
-                               intel_hdmi_init(dev, CHV_HDMID, PORT_D);
-                       if (I915_READ(CHV_DP_D) & DP_DETECTED)
+                       /*
+                        * eDP not supported on port D,
+                        * so no need to worry about it
+                        */
+                       has_port = intel_bios_is_port_present(dev_priv, PORT_D);
+                       if (I915_READ(CHV_DP_D) & DP_DETECTED || has_port)
                                intel_dp_init(dev, CHV_DP_D, PORT_D);
+                       if (I915_READ(CHV_HDMID) & SDVO_DETECTED || has_port)
+                               intel_hdmi_init(dev, CHV_HDMID, PORT_D);
                }
 
                intel_dsi_init(dev);
index f192f58..79cf2d5 100644 (file)
@@ -4977,9 +4977,6 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
        intel_display_power_get(dev_priv, power_domain);
 
        if (long_hpd) {
-               /* indicate that we need to restart link training */
-               intel_dp->train_set_valid = false;
-
                intel_dp_long_pulse(intel_dp->attached_connector);
                if (intel_dp->is_mst)
                        ret = IRQ_HANDLED;
@@ -5725,8 +5722,11 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
        if (!fixed_mode && dev_priv->vbt.lfp_lvds_vbt_mode) {
                fixed_mode = drm_mode_duplicate(dev,
                                        dev_priv->vbt.lfp_lvds_vbt_mode);
-               if (fixed_mode)
+               if (fixed_mode) {
                        fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
+                       connector->display_info.width_mm = fixed_mode->width_mm;
+                       connector->display_info.height_mm = fixed_mode->height_mm;
+               }
        }
        mutex_unlock(&dev->mode_config.mutex);
 
@@ -5923,9 +5923,9 @@ fail:
        return false;
 }
 
-void
-intel_dp_init(struct drm_device *dev,
-             i915_reg_t output_reg, enum port port)
+bool intel_dp_init(struct drm_device *dev,
+                  i915_reg_t output_reg,
+                  enum port port)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_digital_port *intel_dig_port;
@@ -5935,7 +5935,7 @@ intel_dp_init(struct drm_device *dev,
 
        intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL);
        if (!intel_dig_port)
-               return;
+               return false;
 
        intel_connector = intel_connector_alloc();
        if (!intel_connector)
@@ -5992,7 +5992,7 @@ intel_dp_init(struct drm_device *dev,
        if (!intel_dp_init_connector(intel_dig_port, intel_connector))
                goto err_init_connector;
 
-       return;
+       return true;
 
 err_init_connector:
        drm_encoder_cleanup(encoder);
@@ -6000,8 +6000,7 @@ err_encoder_init:
        kfree(intel_connector);
 err_connector_alloc:
        kfree(intel_dig_port);
-
-       return;
+       return false;
 }
 
 void intel_dp_mst_suspend(struct drm_device *dev)
index 0b8eefc..60fb39c 100644 (file)
@@ -85,8 +85,7 @@ static bool
 intel_dp_reset_link_train(struct intel_dp *intel_dp,
                        uint8_t dp_train_pat)
 {
-       if (!intel_dp->train_set_valid)
-               memset(intel_dp->train_set, 0, sizeof(intel_dp->train_set));
+       memset(intel_dp->train_set, 0, sizeof(intel_dp->train_set));
        intel_dp_set_signal_levels(intel_dp);
        return intel_dp_set_link_train(intel_dp, dp_train_pat);
 }
@@ -161,23 +160,6 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp)
                        break;
                }
 
-               /*
-                * if we used previously trained voltage and pre-emphasis values
-                * and we don't get clock recovery, reset link training values
-                */
-               if (intel_dp->train_set_valid) {
-                       DRM_DEBUG_KMS("clock recovery not ok, reset");
-                       /* clear the flag as we are not reusing train set */
-                       intel_dp->train_set_valid = false;
-                       if (!intel_dp_reset_link_train(intel_dp,
-                                                      DP_TRAINING_PATTERN_1 |
-                                                      DP_LINK_SCRAMBLING_DISABLE)) {
-                               DRM_ERROR("failed to enable link training\n");
-                               return;
-                       }
-                       continue;
-               }
-
                /* Check to see if we've tried the max voltage */
                for (i = 0; i < intel_dp->lane_count; i++)
                        if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
@@ -284,7 +266,6 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp)
                /* Make sure clock is still ok */
                if (!drm_dp_clock_recovery_ok(link_status,
                                              intel_dp->lane_count)) {
-                       intel_dp->train_set_valid = false;
                        intel_dp_link_training_clock_recovery(intel_dp);
                        intel_dp_set_link_train(intel_dp,
                                                training_pattern |
@@ -301,7 +282,6 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp)
 
                /* Try 5 times, then try clock recovery if that fails */
                if (tries > 5) {
-                       intel_dp->train_set_valid = false;
                        intel_dp_link_training_clock_recovery(intel_dp);
                        intel_dp_set_link_train(intel_dp,
                                                training_pattern |
@@ -322,10 +302,8 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp)
 
        intel_dp_set_idle_link_train(intel_dp);
 
-       if (channel_eq) {
-               intel_dp->train_set_valid = true;
+       if (channel_eq)
                DRM_DEBUG_KMS("Channel EQ done. DP Training successful\n");
-       }
 }
 
 void intel_dp_stop_link_train(struct intel_dp *intel_dp)
index 3ac7059..baf6f55 100644 (file)
@@ -366,6 +366,9 @@ ibx_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
                                             DPLL_ID_PCH_PLL_B);
        }
 
+       if (!pll)
+               return NULL;
+
        /* reference the pll */
        intel_reference_shared_dpll(pll, crtc_state);
 
index a28b4aa..f7f0f01 100644 (file)
@@ -863,8 +863,6 @@ struct intel_dp {
        /* This is called before a link training is starterd */
        void (*prepare_link_retrain)(struct intel_dp *intel_dp);
 
-       bool train_set_valid;
-
        /* Displayport compliance testing */
        unsigned long compliance_test_type;
        unsigned long compliance_test_data;
@@ -1284,7 +1282,7 @@ void intel_csr_ucode_suspend(struct drm_i915_private *);
 void intel_csr_ucode_resume(struct drm_i915_private *);
 
 /* intel_dp.c */
-void intel_dp_init(struct drm_device *dev, i915_reg_t output_reg, enum port port);
+bool intel_dp_init(struct drm_device *dev, i915_reg_t output_reg, enum port port);
 bool intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
                             struct intel_connector *intel_connector);
 void intel_dp_set_link_params(struct intel_dp *intel_dp,
index 366ad6c..4756ef6 100644 (file)
@@ -1545,6 +1545,9 @@ void intel_dsi_init(struct drm_device *dev)
                goto err;
        }
 
+       connector->display_info.width_mm = fixed_mode->width_mm;
+       connector->display_info.height_mm = fixed_mode->height_mm;
+
        intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
 
        intel_dsi_add_properties(intel_connector);
index d5a7cfe..647127f 100644 (file)
@@ -824,8 +824,7 @@ static bool intel_fbc_can_choose(struct intel_crtc *crtc)
 {
        struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
        struct intel_fbc *fbc = &dev_priv->fbc;
-       bool enable_by_default = IS_HASWELL(dev_priv) ||
-                                IS_BROADWELL(dev_priv);
+       bool enable_by_default = IS_BROADWELL(dev_priv);
 
        if (intel_vgpu_active(dev_priv->dev)) {
                fbc->no_fbc_reason = "VGPU is active";
index 2c3bd9c..a884470 100644 (file)
@@ -2142,6 +2142,9 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
        enum port port = intel_dig_port->port;
        uint8_t alternate_ddc_pin;
 
+       DRM_DEBUG_KMS("Adding HDMI connector on port %c\n",
+                     port_name(port));
+
        if (WARN(intel_dig_port->max_lanes < 4,
                 "Not enough lanes (%d) for HDMI on port %c\n",
                 intel_dig_port->max_lanes, port_name(port)))
index bc53c0d..96281e6 100644 (file)
@@ -1082,6 +1082,8 @@ void intel_lvds_init(struct drm_device *dev)
                fixed_mode = drm_mode_duplicate(dev, dev_priv->vbt.lfp_lvds_vbt_mode);
                if (fixed_mode) {
                        fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
+                       connector->display_info.width_mm = fixed_mode->width_mm;
+                       connector->display_info.height_mm = fixed_mode->height_mm;
                        goto out;
                }
        }
index c15051d..44fb0b3 100644 (file)
@@ -403,9 +403,10 @@ struct lvds_dvo_timing {
        u8 vsync_off:4;
        u8 rsvd0:6;
        u8 hsync_off_hi:2;
-       u8 h_image;
-       u8 v_image;
-       u8 max_hv;
+       u8 himage_lo;
+       u8 vimage_lo;
+       u8 vimage_hi:4;
+       u8 himage_hi:4;
        u8 h_border;
        u8 v_border;
        u8 rsvd1:3;
index 1f14b60..8265665 100644 (file)
@@ -97,8 +97,8 @@ static struct imx_drm_crtc *imx_drm_find_crtc(struct drm_crtc *crtc)
        return NULL;
 }
 
-int imx_drm_set_bus_format_pins(struct drm_encoder *encoder, u32 bus_format,
-               int hsync_pin, int vsync_pin)
+int imx_drm_set_bus_config(struct drm_encoder *encoder, u32 bus_format,
+               int hsync_pin, int vsync_pin, u32 bus_flags)
 {
        struct imx_drm_crtc_helper_funcs *helper;
        struct imx_drm_crtc *imx_crtc;
@@ -110,14 +110,17 @@ int imx_drm_set_bus_format_pins(struct drm_encoder *encoder, u32 bus_format,
        helper = &imx_crtc->imx_drm_helper_funcs;
        if (helper->set_interface_pix_fmt)
                return helper->set_interface_pix_fmt(encoder->crtc,
-                                       bus_format, hsync_pin, vsync_pin);
+                                       bus_format, hsync_pin, vsync_pin,
+                                       bus_flags);
        return 0;
 }
-EXPORT_SYMBOL_GPL(imx_drm_set_bus_format_pins);
+EXPORT_SYMBOL_GPL(imx_drm_set_bus_config);
 
 int imx_drm_set_bus_format(struct drm_encoder *encoder, u32 bus_format)
 {
-       return imx_drm_set_bus_format_pins(encoder, bus_format, 2, 3);
+       return imx_drm_set_bus_config(encoder, bus_format, 2, 3,
+                                     DRM_BUS_FLAG_DE_HIGH |
+                                     DRM_BUS_FLAG_PIXDATA_NEGEDGE);
 }
 EXPORT_SYMBOL_GPL(imx_drm_set_bus_format);
 
index b0241b9..74320a1 100644 (file)
@@ -19,7 +19,8 @@ struct imx_drm_crtc_helper_funcs {
        int (*enable_vblank)(struct drm_crtc *crtc);
        void (*disable_vblank)(struct drm_crtc *crtc);
        int (*set_interface_pix_fmt)(struct drm_crtc *crtc,
-                       u32 bus_format, int hsync_pin, int vsync_pin);
+                       u32 bus_format, int hsync_pin, int vsync_pin,
+                       u32 bus_flags);
        const struct drm_crtc_helper_funcs *crtc_helper_funcs;
        const struct drm_crtc_funcs *crtc_funcs;
 };
@@ -41,8 +42,8 @@ void imx_drm_mode_config_init(struct drm_device *drm);
 
 struct drm_gem_cma_object *imx_drm_fb_get_obj(struct drm_framebuffer *fb);
 
-int imx_drm_set_bus_format_pins(struct drm_encoder *encoder,
-               u32 bus_format, int hsync_pin, int vsync_pin);
+int imx_drm_set_bus_config(struct drm_encoder *encoder, u32 bus_format,
+               int hsync_pin, int vsync_pin, u32 bus_flags);
 int imx_drm_set_bus_format(struct drm_encoder *encoder,
                u32 bus_format);
 
index a58eee5..beff793 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
 #include <linux/of_device.h>
 #include <linux/of_graph.h>
+#include <video/of_display_timing.h>
 #include <video/of_videomode.h>
 #include <linux/regmap.h>
 #include <linux/videodev2.h>
@@ -59,6 +60,7 @@ struct imx_ldb_channel {
        struct drm_encoder encoder;
        struct drm_panel *panel;
        struct device_node *child;
+       struct i2c_adapter *ddc;
        int chno;
        void *edid;
        int edid_len;
@@ -107,6 +109,9 @@ static int imx_ldb_connector_get_modes(struct drm_connector *connector)
                        return num_modes;
        }
 
+       if (!imx_ldb_ch->edid && imx_ldb_ch->ddc)
+               imx_ldb_ch->edid = drm_get_edid(connector, imx_ldb_ch->ddc);
+
        if (imx_ldb_ch->edid) {
                drm_mode_connector_update_edid_property(connector,
                                                        imx_ldb_ch->edid);
@@ -553,7 +558,8 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
 
        for_each_child_of_node(np, child) {
                struct imx_ldb_channel *channel;
-               struct device_node *port;
+               struct device_node *ddc_node;
+               struct device_node *ep;
 
                ret = of_property_read_u32(child, "reg", &i);
                if (ret || i < 0 || i > 1)
@@ -576,33 +582,54 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
                 * The output port is port@4 with an external 4-port mux or
                 * port@2 with the internal 2-port mux.
                 */
-               port = of_graph_get_port_by_id(child, imx_ldb->lvds_mux ? 4 : 2);
-               if (port) {
-                       struct device_node *endpoint, *remote;
-
-                       endpoint = of_get_child_by_name(port, "endpoint");
-                       if (endpoint) {
-                               remote = of_graph_get_remote_port_parent(endpoint);
-                               if (remote)
-                                       channel->panel = of_drm_find_panel(remote);
-                               else
-                                       return -EPROBE_DEFER;
-                               if (!channel->panel) {
-                                       dev_err(dev, "panel not found: %s\n",
-                                               remote->full_name);
-                                       return -EPROBE_DEFER;
-                               }
+               ep = of_graph_get_endpoint_by_regs(child,
+                                                  imx_ldb->lvds_mux ? 4 : 2,
+                                                  -1);
+               if (ep) {
+                       struct device_node *remote;
+
+                       remote = of_graph_get_remote_port_parent(ep);
+                       of_node_put(ep);
+                       if (remote)
+                               channel->panel = of_drm_find_panel(remote);
+                       else
+                               return -EPROBE_DEFER;
+                       of_node_put(remote);
+                       if (!channel->panel) {
+                               dev_err(dev, "panel not found: %s\n",
+                                       remote->full_name);
+                               return -EPROBE_DEFER;
                        }
                }
 
-               edidp = of_get_property(child, "edid", &channel->edid_len);
-               if (edidp) {
-                       channel->edid = kmemdup(edidp, channel->edid_len,
-                                               GFP_KERNEL);
-               } else if (!channel->panel) {
-                       ret = of_get_drm_display_mode(child, &channel->mode, 0);
-                       if (!ret)
-                               channel->mode_valid = 1;
+               ddc_node = of_parse_phandle(child, "ddc-i2c-bus", 0);
+               if (ddc_node) {
+                       channel->ddc = of_find_i2c_adapter_by_node(ddc_node);
+                       of_node_put(ddc_node);
+                       if (!channel->ddc) {
+                               dev_warn(dev, "failed to get ddc i2c adapter\n");
+                               return -EPROBE_DEFER;
+                       }
+               }
+
+               if (!channel->ddc) {
+                       /* if no DDC available, fallback to hardcoded EDID */
+                       dev_dbg(dev, "no ddc available\n");
+
+                       edidp = of_get_property(child, "edid",
+                                               &channel->edid_len);
+                       if (edidp) {
+                               channel->edid = kmemdup(edidp,
+                                                       channel->edid_len,
+                                                       GFP_KERNEL);
+                       } else if (!channel->panel) {
+                               /* fallback to display-timings node */
+                               ret = of_get_drm_display_mode(child,
+                                                             &channel->mode,
+                                                             OF_USE_NATIVE_MODE);
+                               if (!ret)
+                                       channel->mode_valid = 1;
+                       }
                }
 
                channel->bus_format = of_get_bus_format(dev, child);
@@ -647,6 +674,7 @@ static void imx_ldb_unbind(struct device *dev, struct device *master,
                channel->encoder.funcs->destroy(&channel->encoder);
 
                kfree(channel->edid);
+               i2c_put_adapter(channel->ddc);
        }
 }
 
index ae7a9fb..baf7881 100644 (file)
@@ -294,8 +294,10 @@ static void imx_tve_encoder_prepare(struct drm_encoder *encoder)
 
        switch (tve->mode) {
        case TVE_MODE_VGA:
-               imx_drm_set_bus_format_pins(encoder, MEDIA_BUS_FMT_GBR888_1X24,
-                                           tve->hsync_pin, tve->vsync_pin);
+               imx_drm_set_bus_config(encoder, MEDIA_BUS_FMT_GBR888_1X24,
+                                      tve->hsync_pin, tve->vsync_pin,
+                                      DRM_BUS_FLAG_DE_HIGH |
+                                      DRM_BUS_FLAG_PIXDATA_NEGEDGE);
                break;
        case TVE_MODE_TVOUT:
                imx_drm_set_bus_format(encoder, MEDIA_BUS_FMT_YUV8_1X24);
index b2c30b8..fc04041 100644 (file)
@@ -66,6 +66,7 @@ struct ipu_crtc {
        struct ipu_flip_work    *flip_work;
        int                     irq;
        u32                     bus_format;
+       u32                     bus_flags;
        int                     di_hsync_pin;
        int                     di_vsync_pin;
 };
@@ -271,8 +272,10 @@ static int ipu_crtc_mode_set(struct drm_crtc *crtc,
        else
                sig_cfg.clkflags = 0;
 
-       sig_cfg.enable_pol = 1;
-       sig_cfg.clk_pol = 0;
+       sig_cfg.enable_pol = !(ipu_crtc->bus_flags & DRM_BUS_FLAG_DE_LOW);
+       /* Default to driving pixel data on negative clock edges */
+       sig_cfg.clk_pol = !!(ipu_crtc->bus_flags &
+                            DRM_BUS_FLAG_PIXDATA_POSEDGE);
        sig_cfg.bus_format = ipu_crtc->bus_format;
        sig_cfg.v_to_h_sync = 0;
        sig_cfg.hsync_pin = ipu_crtc->di_hsync_pin;
@@ -396,11 +399,12 @@ static void ipu_disable_vblank(struct drm_crtc *crtc)
 }
 
 static int ipu_set_interface_pix_fmt(struct drm_crtc *crtc,
-               u32 bus_format, int hsync_pin, int vsync_pin)
+               u32 bus_format, int hsync_pin, int vsync_pin, u32 bus_flags)
 {
        struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
 
        ipu_crtc->bus_format = bus_format;
+       ipu_crtc->bus_flags = bus_flags;
        ipu_crtc->di_hsync_pin = hsync_pin;
        ipu_crtc->di_vsync_pin = vsync_pin;
 
index 681ec6e..a4bb441 100644 (file)
@@ -38,6 +38,8 @@ static const uint32_t ipu_plane_formats[] = {
        DRM_FORMAT_RGBX8888,
        DRM_FORMAT_BGRA8888,
        DRM_FORMAT_BGRA8888,
+       DRM_FORMAT_UYVY,
+       DRM_FORMAT_VYUY,
        DRM_FORMAT_YUYV,
        DRM_FORMAT_YVYU,
        DRM_FORMAT_YUV420,
@@ -428,7 +430,6 @@ static int ipu_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
        if (crtc != plane->crtc)
                dev_dbg(plane->dev->dev, "crtc change: %p -> %p\n",
                                plane->crtc, crtc);
-       plane->crtc = crtc;
 
        if (!ipu_plane->enabled)
                ipu_plane_enable(ipu_plane);
@@ -461,7 +462,7 @@ static void ipu_plane_destroy(struct drm_plane *plane)
        kfree(ipu_plane);
 }
 
-static struct drm_plane_funcs ipu_plane_funcs = {
+static const struct drm_plane_funcs ipu_plane_funcs = {
        .update_plane   = ipu_update_plane,
        .disable_plane  = ipu_disable_plane,
        .destroy        = ipu_plane_destroy,
index 363e2c7..2d1fd02 100644 (file)
@@ -35,7 +35,6 @@ struct imx_parallel_display {
        void *edid;
        int edid_len;
        u32 bus_format;
-       int mode_valid;
        struct drm_display_mode mode;
        struct drm_panel *panel;
 };
@@ -68,17 +67,6 @@ static int imx_pd_connector_get_modes(struct drm_connector *connector)
                num_modes = drm_add_edid_modes(connector, imxpd->edid);
        }
 
-       if (imxpd->mode_valid) {
-               struct drm_display_mode *mode = drm_mode_create(connector->dev);
-
-               if (!mode)
-                       return -EINVAL;
-               drm_mode_copy(mode, &imxpd->mode);
-               mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
-               drm_mode_probed_add(connector, mode);
-               num_modes++;
-       }
-
        if (np) {
                struct drm_display_mode *mode = drm_mode_create(connector->dev);
 
@@ -115,8 +103,8 @@ static void imx_pd_encoder_dpms(struct drm_encoder *encoder, int mode)
 static void imx_pd_encoder_prepare(struct drm_encoder *encoder)
 {
        struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
-
-       imx_drm_set_bus_format(encoder, imxpd->bus_format);
+       imx_drm_set_bus_config(encoder, imxpd->bus_format, 2, 3,
+                              imxpd->connector.display_info.bus_flags);
 }
 
 static void imx_pd_encoder_commit(struct drm_encoder *encoder)
@@ -203,7 +191,7 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data)
 {
        struct drm_device *drm = data;
        struct device_node *np = dev->of_node;
-       struct device_node *port;
+       struct device_node *ep;
        const u8 *edidp;
        struct imx_parallel_display *imxpd;
        int ret;
@@ -230,18 +218,18 @@ static int imx_pd_bind(struct device *dev, struct device *master, void *data)
        }
 
        /* port@1 is the output port */
-       port = of_graph_get_port_by_id(np, 1);
-       if (port) {
-               struct device_node *endpoint, *remote;
-
-               endpoint = of_get_child_by_name(port, "endpoint");
-               if (endpoint) {
-                       remote = of_graph_get_remote_port_parent(endpoint);
-                       if (remote)
-                               imxpd->panel = of_drm_find_panel(remote);
-                       if (!imxpd->panel)
-                               return -EPROBE_DEFER;
+       ep = of_graph_get_endpoint_by_regs(np, 1, -1);
+       if (ep) {
+               struct device_node *remote;
+
+               remote = of_graph_get_remote_port_parent(ep);
+               of_node_put(ep);
+               if (remote) {
+                       imxpd->panel = of_drm_find_panel(remote);
+                       of_node_put(remote);
                }
+               if (!imxpd->panel)
+                       return -EPROBE_DEFER;
        }
 
        imxpd->dev = dev;
index d05ca79..0186e50 100644 (file)
@@ -432,11 +432,6 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi,
        unsigned long pll_rate;
        unsigned int factor;
 
-       if (!dpi) {
-               dev_err(dpi->dev, "invalid argument\n");
-               return -EINVAL;
-       }
-
        pix_rate = 1000UL * mode->clock;
        if (mode->clock <= 74000)
                factor = 8 * 3;
index 2d808e5..7695591 100644 (file)
@@ -695,10 +695,8 @@ static void mtk_dsi_destroy_conn_enc(struct mtk_dsi *dsi)
 {
        drm_encoder_cleanup(&dsi->encoder);
        /* Skip connector cleanup if creation was delegated to the bridge */
-       if (dsi->conn.dev) {
-               drm_connector_unregister(&dsi->conn);
+       if (dsi->conn.dev)
                drm_connector_cleanup(&dsi->conn);
-       }
 }
 
 static void mtk_dsi_ddp_start(struct mtk_ddp_comp *comp)
index 14e64e0..d347dca 100644 (file)
@@ -182,7 +182,7 @@ static int mga_g200se_set_plls(struct mga_device *mdev, long clock)
                        }
                }
 
-               fvv = pllreffreq * testn / testm;
+               fvv = pllreffreq * (n + 1) / (m + 1);
                fvv = (fvv - 800000) / 50000;
 
                if (fvv > 15)
@@ -202,6 +202,14 @@ static int mga_g200se_set_plls(struct mga_device *mdev, long clock)
        WREG_DAC(MGA1064_PIX_PLLC_M, m);
        WREG_DAC(MGA1064_PIX_PLLC_N, n);
        WREG_DAC(MGA1064_PIX_PLLC_P, p);
+
+       if (mdev->unique_rev_id >= 0x04) {
+               WREG_DAC(0x1a, 0x09);
+               msleep(20);
+               WREG_DAC(0x1a, 0x01);
+
+       }
+
        return 0;
 }
 
index fbe304e..2aec27d 100644 (file)
@@ -408,7 +408,7 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
        }
 
        adreno_gpu->memptrs = msm_gem_vaddr(adreno_gpu->memptrs_bo);
-       if (!adreno_gpu->memptrs) {
+       if (IS_ERR(adreno_gpu->memptrs)) {
                dev_err(drm->dev, "could not vmap memptrs\n");
                return -ENOMEM;
        }
index d9759bf..c6cf837 100644 (file)
@@ -159,6 +159,10 @@ static int msm_fbdev_create(struct drm_fb_helper *helper,
        dev->mode_config.fb_base = paddr;
 
        fbi->screen_base = msm_gem_vaddr_locked(fbdev->bo);
+       if (IS_ERR(fbi->screen_base)) {
+               ret = PTR_ERR(fbi->screen_base);
+               goto fail_unlock;
+       }
        fbi->screen_size = fbdev->bo->size;
        fbi->fix.smem_start = paddr;
        fbi->fix.smem_len = fbdev->bo->size;
index 7daf405..69836f5 100644 (file)
@@ -398,6 +398,8 @@ void *msm_gem_vaddr_locked(struct drm_gem_object *obj)
                        return ERR_CAST(pages);
                msm_obj->vaddr = vmap(pages, obj->size >> PAGE_SHIFT,
                                VM_MAP, pgprot_writecombine(PAGE_KERNEL));
+               if (msm_obj->vaddr == NULL)
+                       return ERR_PTR(-ENOMEM);
        }
        return msm_obj->vaddr;
 }
index b89ca51..eb4bb8b 100644 (file)
@@ -40,12 +40,14 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev,
 
        submit->dev = dev;
        submit->gpu = gpu;
+       submit->fence = NULL;
        submit->pid = get_pid(task_pid(current));
 
        /* initially, until copy_from_user() and bo lookup succeeds: */
        submit->nr_bos = 0;
        submit->nr_cmds = 0;
 
+       INIT_LIST_HEAD(&submit->node);
        INIT_LIST_HEAD(&submit->bo_list);
        ww_acquire_init(&submit->ticket, &reservation_ww_class);
 
@@ -75,6 +77,11 @@ static int submit_lookup_objects(struct msm_gem_submit *submit,
                void __user *userptr =
                        u64_to_user_ptr(args->bos + (i * sizeof(submit_bo)));
 
+               /* make sure we don't have garbage flags, in case we hit
+                * error path before flags is initialized:
+                */
+               submit->bos[i].flags = 0;
+
                ret = copy_from_user(&submit_bo, userptr, sizeof(submit_bo));
                if (ret) {
                        ret = -EFAULT;
index b48f73a..0857710 100644 (file)
@@ -312,6 +312,9 @@ void msm_rd_dump_submit(struct msm_gem_submit *submit)
                struct msm_gem_object *obj = submit->bos[idx].obj;
                const char *buf = msm_gem_vaddr_locked(&obj->base);
 
+               if (IS_ERR(buf))
+                       continue;
+
                buf += iova - submit->bos[idx].iova;
 
                rd_write_section(rd, RD_GPUADDR,
index 1f14b90..42f5359 100644 (file)
@@ -40,6 +40,10 @@ struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int size)
        }
 
        ring->start = msm_gem_vaddr_locked(ring->bo);
+       if (IS_ERR(ring->start)) {
+               ret = PTR_ERR(ring->start);
+               goto fail;
+       }
        ring->end   = ring->start + (size / 4);
        ring->cur   = ring->start;
 
index c612dc1..126a85c 100644 (file)
@@ -16,9 +16,9 @@ enum nvkm_devidx {
        NVKM_SUBDEV_MC,
        NVKM_SUBDEV_BUS,
        NVKM_SUBDEV_TIMER,
+       NVKM_SUBDEV_INSTMEM,
        NVKM_SUBDEV_FB,
        NVKM_SUBDEV_LTC,
-       NVKM_SUBDEV_INSTMEM,
        NVKM_SUBDEV_MMU,
        NVKM_SUBDEV_BAR,
        NVKM_SUBDEV_PMU,
index db10c11..c5a6ebd 100644 (file)
@@ -25,7 +25,8 @@ u16 nvbios_outp_match(struct nvkm_bios *, u16 type, u16 mask,
                      u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_outp *);
 
 struct nvbios_ocfg {
-       u16 match;
+       u8  proto;
+       u8  flags;
        u16 clkcmp[2];
 };
 
@@ -33,7 +34,7 @@ u16 nvbios_ocfg_entry(struct nvkm_bios *, u16 outp, u8 idx,
                      u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
 u16 nvbios_ocfg_parse(struct nvkm_bios *, u16 outp, u8 idx,
                      u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_ocfg *);
-u16 nvbios_ocfg_match(struct nvkm_bios *, u16 outp, u16 type,
+u16 nvbios_ocfg_match(struct nvkm_bios *, u16 outp, u8 proto, u8 flags,
                      u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_ocfg *);
 u16 nvbios_oclk_match(struct nvkm_bios *, u16 cmp, u32 khz);
 #endif
index 57aaf98..d1f248f 100644 (file)
@@ -552,6 +552,8 @@ nouveau_fbcon_init(struct drm_device *dev)
        if (ret)
                goto fini;
 
+       if (fbcon->helper.fbdev)
+               fbcon->helper.fbdev->pixmap.buf_align = 4;
        return 0;
 
 fini:
index 0f3e4bb..7d9248b 100644 (file)
@@ -82,7 +82,6 @@ nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
        uint32_t fg;
        uint32_t bg;
        uint32_t dsize;
-       uint32_t width;
        uint32_t *data = (uint32_t *)image->data;
        int ret;
 
@@ -93,9 +92,6 @@ nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
        if (ret)
                return ret;
 
-       width = ALIGN(image->width, 8);
-       dsize = ALIGN(width * image->height, 32) >> 5;
-
        if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
            info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
                fg = ((uint32_t *) info->pseudo_palette)[image->fg_color];
@@ -111,10 +107,11 @@ nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
                         ((image->dx + image->width) & 0xffff));
        OUT_RING(chan, bg);
        OUT_RING(chan, fg);
-       OUT_RING(chan, (image->height << 16) | width);
+       OUT_RING(chan, (image->height << 16) | image->width);
        OUT_RING(chan, (image->height << 16) | image->width);
        OUT_RING(chan, (image->dy << 16) | (image->dx & 0xffff));
 
+       dsize = ALIGN(image->width * image->height, 32) >> 5;
        while (dsize) {
                int iter_len = dsize > 128 ? 128 : dsize;
 
index 33d9ee0..1aeb698 100644 (file)
@@ -95,7 +95,7 @@ nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
        struct nouveau_fbdev *nfbdev = info->par;
        struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
        struct nouveau_channel *chan = drm->channel;
-       uint32_t width, dwords, *data = (uint32_t *)image->data;
+       uint32_t dwords, *data = (uint32_t *)image->data;
        uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel));
        uint32_t *palette = info->pseudo_palette;
        int ret;
@@ -107,9 +107,6 @@ nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
        if (ret)
                return ret;
 
-       width = ALIGN(image->width, 32);
-       dwords = (width * image->height) >> 5;
-
        BEGIN_NV04(chan, NvSub2D, 0x0814, 2);
        if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
            info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
@@ -128,6 +125,7 @@ nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
        OUT_RING(chan, 0);
        OUT_RING(chan, image->dy);
 
+       dwords = ALIGN(image->width * image->height, 32) >> 5;
        while (dwords) {
                int push = dwords > 2047 ? 2047 : dwords;
 
index a091335..839f4c8 100644 (file)
@@ -95,7 +95,7 @@ nvc0_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
        struct nouveau_fbdev *nfbdev = info->par;
        struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
        struct nouveau_channel *chan = drm->channel;
-       uint32_t width, dwords, *data = (uint32_t *)image->data;
+       uint32_t dwords, *data = (uint32_t *)image->data;
        uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel));
        uint32_t *palette = info->pseudo_palette;
        int ret;
@@ -107,9 +107,6 @@ nvc0_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
        if (ret)
                return ret;
 
-       width = ALIGN(image->width, 32);
-       dwords = (width * image->height) >> 5;
-
        BEGIN_NVC0(chan, NvSub2D, 0x0814, 2);
        if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
            info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
@@ -128,6 +125,7 @@ nvc0_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
        OUT_RING  (chan, 0);
        OUT_RING  (chan, image->dy);
 
+       dwords = ALIGN(image->width * image->height, 32) >> 5;
        while (dwords) {
                int push = dwords > 2047 ? 2047 : dwords;
 
index 18fab39..62ad030 100644 (file)
@@ -1614,7 +1614,7 @@ nvkm_device_pci_func = {
        .fini = nvkm_device_pci_fini,
        .resource_addr = nvkm_device_pci_resource_addr,
        .resource_size = nvkm_device_pci_resource_size,
-       .cpu_coherent = !IS_ENABLED(CONFIG_ARM) && !IS_ENABLED(CONFIG_ARM64),
+       .cpu_coherent = !IS_ENABLED(CONFIG_ARM),
 };
 
 int
index a74c5dd..e2a64ed 100644 (file)
@@ -18,6 +18,7 @@ nvkm-y += nvkm/engine/disp/piornv50.o
 nvkm-y += nvkm/engine/disp/sornv50.o
 nvkm-y += nvkm/engine/disp/sorg94.o
 nvkm-y += nvkm/engine/disp/sorgf119.o
+nvkm-y += nvkm/engine/disp/sorgm107.o
 nvkm-y += nvkm/engine/disp/sorgm200.o
 nvkm-y += nvkm/engine/disp/dport.o
 
index f031466..5dd3438 100644 (file)
@@ -76,6 +76,7 @@ exec_lookup(struct nv50_disp *disp, int head, int or, u32 ctrl,
        mask |= 0x0001 << or;
        mask |= 0x0100 << head;
 
+
        list_for_each_entry(outp, &disp->base.outp, head) {
                if ((outp->info.hasht & 0xff) == type &&
                    (outp->info.hashm & mask) == mask) {
@@ -155,25 +156,21 @@ exec_clkcmp(struct nv50_disp *disp, int head, int id, u32 pclk, u32 *conf)
        if (!outp)
                return NULL;
 
+       *conf = (ctrl & 0x00000f00) >> 8;
        switch (outp->info.type) {
        case DCB_OUTPUT_TMDS:
-               *conf = (ctrl & 0x00000f00) >> 8;
                if (*conf == 5)
                        *conf |= 0x0100;
                break;
        case DCB_OUTPUT_LVDS:
-               *conf = disp->sor.lvdsconf;
-               break;
-       case DCB_OUTPUT_DP:
-               *conf = (ctrl & 0x00000f00) >> 8;
+               *conf |= disp->sor.lvdsconf;
                break;
-       case DCB_OUTPUT_ANALOG:
        default:
-               *conf = 0x00ff;
                break;
        }
 
-       data = nvbios_ocfg_match(bios, data, *conf, &ver, &hdr, &cnt, &len, &info2);
+       data = nvbios_ocfg_match(bios, data, *conf & 0xff, *conf >> 8,
+                                &ver, &hdr, &cnt, &len, &info2);
        if (data && id < 0xff) {
                data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk);
                if (data) {
index b694414..f4b9cf8 100644 (file)
@@ -36,7 +36,7 @@ gm107_disp = {
        .outp.internal.crt = nv50_dac_output_new,
        .outp.internal.tmds = nv50_sor_output_new,
        .outp.internal.lvds = nv50_sor_output_new,
-       .outp.internal.dp = gf119_sor_dp_new,
+       .outp.internal.dp = gm107_sor_dp_new,
        .dac.nr = 3,
        .dac.power = nv50_dac_power,
        .dac.sense = nv50_dac_sense,
index 4226d21..fcb1b0c 100644 (file)
@@ -387,22 +387,17 @@ exec_clkcmp(struct nv50_disp *disp, int head, int id, u32 pclk, u32 *conf)
        if (!outp)
                return NULL;
 
+       *conf = (ctrl & 0x00000f00) >> 8;
        if (outp->info.location == 0) {
                switch (outp->info.type) {
                case DCB_OUTPUT_TMDS:
-                       *conf = (ctrl & 0x00000f00) >> 8;
                        if (*conf == 5)
                                *conf |= 0x0100;
                        break;
                case DCB_OUTPUT_LVDS:
-                       *conf = disp->sor.lvdsconf;
+                       *conf |= disp->sor.lvdsconf;
                        break;
-               case DCB_OUTPUT_DP:
-                       *conf = (ctrl & 0x00000f00) >> 8;
-                       break;
-               case DCB_OUTPUT_ANALOG:
                default:
-                       *conf = 0x00ff;
                        break;
                }
        } else {
@@ -410,7 +405,8 @@ exec_clkcmp(struct nv50_disp *disp, int head, int id, u32 pclk, u32 *conf)
                pclk = pclk / 2;
        }
 
-       data = nvbios_ocfg_match(bios, data, *conf, &ver, &hdr, &cnt, &len, &info2);
+       data = nvbios_ocfg_match(bios, data, *conf & 0xff, *conf >> 8,
+                                &ver, &hdr, &cnt, &len, &info2);
        if (data && id < 0xff) {
                data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk);
                if (data) {
index e9067ba..4e983f6 100644 (file)
@@ -62,7 +62,12 @@ int g94_sor_dp_lnk_pwr(struct nvkm_output_dp *, int);
 int gf119_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *,
                     struct nvkm_output **);
 int gf119_sor_dp_lnk_ctl(struct nvkm_output_dp *, int, int, bool);
+int gf119_sor_dp_drv_ctl(struct nvkm_output_dp *, int, int, int, int);
 
-int  gm200_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *,
-                     struct nvkm_output **);
+int gm107_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *,
+                    struct nvkm_output **);
+int gm107_sor_dp_pattern(struct nvkm_output_dp *, int);
+
+int gm200_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *,
+                    struct nvkm_output **);
 #endif
index b4b41b1..22706c0 100644 (file)
@@ -40,8 +40,7 @@ static int
 gf119_sor_dp_pattern(struct nvkm_output_dp *outp, int pattern)
 {
        struct nvkm_device *device = outp->base.disp->engine.subdev.device;
-       const u32 loff = gf119_sor_loff(outp);
-       nvkm_mask(device, 0x61c110 + loff, 0x0f0f0f0f, 0x01010101 * pattern);
+       nvkm_mask(device, 0x61c110, 0x0f0f0f0f, 0x01010101 * pattern);
        return 0;
 }
 
@@ -64,7 +63,7 @@ gf119_sor_dp_lnk_ctl(struct nvkm_output_dp *outp, int nr, int bw, bool ef)
        return 0;
 }
 
-static int
+int
 gf119_sor_dp_drv_ctl(struct nvkm_output_dp *outp,
                     int ln, int vs, int pe, int pc)
 {
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c
new file mode 100644 (file)
index 0000000..37790b2
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2016 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+#include "nv50.h"
+#include "outpdp.h"
+
+int
+gm107_sor_dp_pattern(struct nvkm_output_dp *outp, int pattern)
+{
+       struct nvkm_device *device = outp->base.disp->engine.subdev.device;
+       const u32 soff = outp->base.or * 0x800;
+       const u32 data = 0x01010101 * pattern;
+       if (outp->base.info.sorconf.link & 1)
+               nvkm_mask(device, 0x61c110 + soff, 0x0f0f0f0f, data);
+       else
+               nvkm_mask(device, 0x61c12c + soff, 0x0f0f0f0f, data);
+       return 0;
+}
+
+static const struct nvkm_output_dp_func
+gm107_sor_dp_func = {
+       .pattern = gm107_sor_dp_pattern,
+       .lnk_pwr = g94_sor_dp_lnk_pwr,
+       .lnk_ctl = gf119_sor_dp_lnk_ctl,
+       .drv_ctl = gf119_sor_dp_drv_ctl,
+};
+
+int
+gm107_sor_dp_new(struct nvkm_disp *disp, int index,
+                struct dcb_output *dcbE, struct nvkm_output **poutp)
+{
+       return nvkm_output_dp_new_(&gm107_sor_dp_func, disp, index, dcbE, poutp);
+}
index 2cfbef9..c44fa7e 100644 (file)
@@ -56,19 +56,6 @@ gm200_sor_dp_lane_map(struct nvkm_device *device, u8 lane)
        return lane * 0x08;
 }
 
-static int
-gm200_sor_dp_pattern(struct nvkm_output_dp *outp, int pattern)
-{
-       struct nvkm_device *device = outp->base.disp->engine.subdev.device;
-       const u32 soff = gm200_sor_soff(outp);
-       const u32 data = 0x01010101 * pattern;
-       if (outp->base.info.sorconf.link & 1)
-               nvkm_mask(device, 0x61c110 + soff, 0x0f0f0f0f, data);
-       else
-               nvkm_mask(device, 0x61c12c + soff, 0x0f0f0f0f, data);
-       return 0;
-}
-
 static int
 gm200_sor_dp_lnk_pwr(struct nvkm_output_dp *outp, int nr)
 {
@@ -129,7 +116,7 @@ gm200_sor_dp_drv_ctl(struct nvkm_output_dp *outp,
 
 static const struct nvkm_output_dp_func
 gm200_sor_dp_func = {
-       .pattern = gm200_sor_dp_pattern,
+       .pattern = gm107_sor_dp_pattern,
        .lnk_pwr = gm200_sor_dp_lnk_pwr,
        .lnk_ctl = gf119_sor_dp_lnk_ctl,
        .drv_ctl = gm200_sor_dp_drv_ctl,
index 9513bad..ae9ab5b 100644 (file)
@@ -949,22 +949,41 @@ gf100_gr_trap_gpc_rop(struct gf100_gr *gr, int gpc)
 }
 
 static const struct nvkm_enum gf100_mp_warp_error[] = {
-       { 0x00, "NO_ERROR" },
-       { 0x01, "STACK_MISMATCH" },
+       { 0x01, "STACK_ERROR" },
+       { 0x02, "API_STACK_ERROR" },
+       { 0x03, "RET_EMPTY_STACK_ERROR" },
+       { 0x04, "PC_WRAP" },
        { 0x05, "MISALIGNED_PC" },
-       { 0x08, "MISALIGNED_GPR" },
-       { 0x09, "INVALID_OPCODE" },
-       { 0x0d, "GPR_OUT_OF_BOUNDS" },
-       { 0x0e, "MEM_OUT_OF_BOUNDS" },
-       { 0x0f, "UNALIGNED_MEM_ACCESS" },
+       { 0x06, "PC_OVERFLOW" },
+       { 0x07, "MISALIGNED_IMMC_ADDR" },
+       { 0x08, "MISALIGNED_REG" },
+       { 0x09, "ILLEGAL_INSTR_ENCODING" },
+       { 0x0a, "ILLEGAL_SPH_INSTR_COMBO" },
+       { 0x0b, "ILLEGAL_INSTR_PARAM" },
+       { 0x0c, "INVALID_CONST_ADDR" },
+       { 0x0d, "OOR_REG" },
+       { 0x0e, "OOR_ADDR" },
+       { 0x0f, "MISALIGNED_ADDR" },
        { 0x10, "INVALID_ADDR_SPACE" },
-       { 0x11, "INVALID_PARAM" },
+       { 0x11, "ILLEGAL_INSTR_PARAM2" },
+       { 0x12, "INVALID_CONST_ADDR_LDC" },
+       { 0x13, "GEOMETRY_SM_ERROR" },
+       { 0x14, "DIVERGENT" },
+       { 0x15, "WARP_EXIT" },
        {}
 };
 
 static const struct nvkm_bitfield gf100_mp_global_error[] = {
+       { 0x00000001, "SM_TO_SM_FAULT" },
+       { 0x00000002, "L1_ERROR" },
        { 0x00000004, "MULTIPLE_WARP_ERRORS" },
-       { 0x00000008, "OUT_OF_STACK_SPACE" },
+       { 0x00000008, "PHYSICAL_STACK_OVERFLOW" },
+       { 0x00000010, "BPT_INT" },
+       { 0x00000020, "BPT_PAUSE" },
+       { 0x00000040, "SINGLE_STEP_COMPLETE" },
+       { 0x20000000, "ECC_SEC_ERROR" },
+       { 0x40000000, "ECC_DED_ERROR" },
+       { 0x80000000, "TIMEOUT" },
        {}
 };
 
index a5e9213..9efb1b4 100644 (file)
@@ -141,7 +141,8 @@ nvbios_ocfg_parse(struct nvkm_bios *bios, u16 outp, u8 idx,
 {
        u16 data = nvbios_ocfg_entry(bios, outp, idx, ver, hdr, cnt, len);
        if (data) {
-               info->match     = nvbios_rd16(bios, data + 0x00);
+               info->proto     = nvbios_rd08(bios, data + 0x00);
+               info->flags     = nvbios_rd16(bios, data + 0x01);
                info->clkcmp[0] = nvbios_rd16(bios, data + 0x02);
                info->clkcmp[1] = nvbios_rd16(bios, data + 0x04);
        }
@@ -149,12 +150,13 @@ nvbios_ocfg_parse(struct nvkm_bios *bios, u16 outp, u8 idx,
 }
 
 u16
-nvbios_ocfg_match(struct nvkm_bios *bios, u16 outp, u16 type,
+nvbios_ocfg_match(struct nvkm_bios *bios, u16 outp, u8 proto, u8 flags,
                  u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_ocfg *info)
 {
        u16 data, idx = 0;
        while ((data = nvbios_ocfg_parse(bios, outp, idx++, ver, hdr, cnt, len, info))) {
-               if (info->match == type)
+               if ((info->proto == proto || info->proto == 0xff) &&
+                   (info->flags == flags))
                        break;
        }
        return data;
index 323c79a..41bd5d0 100644 (file)
@@ -276,6 +276,8 @@ nvkm_iccsense_oneinit(struct nvkm_subdev *subdev)
                struct pwr_rail_t *r = &stbl.rail[i];
                struct nvkm_iccsense_rail *rail;
                struct nvkm_iccsense_sensor *sensor;
+               int (*read)(struct nvkm_iccsense *,
+                           struct nvkm_iccsense_rail *);
 
                if (!r->mode || r->resistor_mohm == 0)
                        continue;
@@ -284,31 +286,31 @@ nvkm_iccsense_oneinit(struct nvkm_subdev *subdev)
                if (!sensor)
                        continue;
 
-               rail = kmalloc(sizeof(*rail), GFP_KERNEL);
-               if (!rail)
-                       return -ENOMEM;
-
                switch (sensor->type) {
                case NVBIOS_EXTDEV_INA209:
                        if (r->rail != 0)
                                continue;
-                       rail->read = nvkm_iccsense_ina209_read;
+                       read = nvkm_iccsense_ina209_read;
                        break;
                case NVBIOS_EXTDEV_INA219:
                        if (r->rail != 0)
                                continue;
-                       rail->read = nvkm_iccsense_ina219_read;
+                       read = nvkm_iccsense_ina219_read;
                        break;
                case NVBIOS_EXTDEV_INA3221:
                        if (r->rail >= 3)
                                continue;
-                       rail->read = nvkm_iccsense_ina3221_read;
+                       read = nvkm_iccsense_ina3221_read;
                        break;
                default:
                        continue;
                }
 
+               rail = kmalloc(sizeof(*rail), GFP_KERNEL);
+               if (!rail)
+                       return -ENOMEM;
                sensor->rail_mask |= 1 << r->rail;
+               rail->read = read;
                rail->sensor = sensor;
                rail->idx = r->rail;
                rail->mohm = r->resistor_mohm;
index e292f56..389fb13 100644 (file)
@@ -69,11 +69,11 @@ gm107_ltc_zbc_clear_depth(struct nvkm_ltc *ltc, int i, const u32 depth)
 }
 
 static void
-gm107_ltc_lts_isr(struct nvkm_ltc *ltc, int c, int s)
+gm107_ltc_intr_lts(struct nvkm_ltc *ltc, int c, int s)
 {
        struct nvkm_subdev *subdev = &ltc->subdev;
        struct nvkm_device *device = subdev->device;
-       u32 base = 0x140000 + (c * 0x2000) + (s * 0x200);
+       u32 base = 0x140400 + (c * 0x2000) + (s * 0x200);
        u32 stat = nvkm_rd32(device, base + 0x00c);
 
        if (stat) {
@@ -92,7 +92,7 @@ gm107_ltc_intr(struct nvkm_ltc *ltc)
        while (mask) {
                u32 s, c = __ffs(mask);
                for (s = 0; s < ltc->lts_nr; s++)
-                       gm107_ltc_lts_isr(ltc, c, s);
+                       gm107_ltc_intr_lts(ltc, c, s);
                mask &= ~(1 << c);
        }
 }
index 2a29bfd..e18e0dc 100644 (file)
@@ -46,7 +46,7 @@ static const struct nvkm_ltc_func
 gm200_ltc = {
        .oneinit = gm200_ltc_oneinit,
        .init = gm200_ltc_init,
-       .intr = gm107_ltc_intr, /*XXX: not validated */
+       .intr = gm107_ltc_intr,
        .cbc_clear = gm107_ltc_cbc_clear,
        .cbc_wait = gm107_ltc_cbc_wait,
        .zbc = 16,
index 73241c4..336ad4d 100644 (file)
@@ -2,6 +2,7 @@ config DRM_OMAP
        tristate "OMAP DRM"
        depends on DRM
        depends on ARCH_OMAP2PLUS || ARCH_MULTIPLATFORM
+       select OMAP2_DSS
        select DRM_KMS_HELPER
        select DRM_KMS_FB_HELPER
        select FB_SYS_FILLRECT
index 225fd8d..667ca4a 100644 (file)
@@ -9,6 +9,7 @@
  * the Free Software Foundation.
  */
 
+#include <linux/gpio/consumer.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
index 8c246c2..9594ff7 100644 (file)
@@ -14,7 +14,7 @@
  * the Free Software Foundation.
  */
 
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
index 2fd5602..671806c 100644 (file)
@@ -9,7 +9,7 @@
  * the Free Software Foundation.
  */
 
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
index e780fd4..7c2331b 100644 (file)
@@ -9,7 +9,7 @@
  * the Free Software Foundation.
  */
 
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
index 36485c2..2b11807 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/backlight.h>
 #include <linux/delay.h>
 #include <linux/fb.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/interrupt.h>
 #include <linux/jiffies.h>
 #include <linux/module.h>
index 458f77b..ac680e1 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/spi/spi.h>
 #include <linux/mutex.h>
 #include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 
 #include <video/omapdss.h>
 #include <video/omap-panel-data.h>
index 780cb26..38d2920 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/delay.h>
 #include <linux/spi/spi.h>
 #include <linux/fb.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/of_gpio.h>
 
 #include <video/omapdss.h>
index 529a017..4363fff 100644 (file)
@@ -10,7 +10,7 @@
  */
 
 #include <linux/delay.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
index 31efcca..deb4167 100644 (file)
@@ -29,7 +29,7 @@
 #include <linux/sched.h>
 #include <linux/backlight.h>
 #include <linux/fb.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
 
index 03e2beb..d93175b 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/delay.h>
 #include <linux/spi/spi.h>
 #include <linux/regulator/consumer.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/of_gpio.h>
index 8730646..56c43f3 100644 (file)
@@ -1167,7 +1167,6 @@ static int dsi_regulator_init(struct platform_device *dsidev)
 {
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
        struct regulator *vdds_dsi;
-       int r;
 
        if (dsi->vdds_dsi_reg != NULL)
                return 0;
@@ -1180,15 +1179,6 @@ static int dsi_regulator_init(struct platform_device *dsidev)
                return PTR_ERR(vdds_dsi);
        }
 
-       if (regulator_can_change_voltage(vdds_dsi)) {
-               r = regulator_set_voltage(vdds_dsi, 1800000, 1800000);
-               if (r) {
-                       devm_regulator_put(vdds_dsi);
-                       DSSERR("can't set the DSI regulator voltage\n");
-                       return r;
-               }
-       }
-
        dsi->vdds_dsi_reg = vdds_dsi;
 
        return 0;
index f95ff31..3303cfa 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/delay.h>
 #include <linux/seq_file.h>
 #include <linux/clk.h>
+#include <linux/pinctrl/consumer.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/gfp.h>
index f892ae1..4d46cdf 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/gpio.h>
 #include <linux/regulator/consumer.h>
 #include <linux/component.h>
+#include <linux/of.h>
 #include <video/omapdss.h>
 #include <sound/omap-hdmi-audio.h>
 
@@ -100,7 +101,6 @@ static irqreturn_t hdmi_irq_handler(int irq, void *data)
 
 static int hdmi_init_regulator(void)
 {
-       int r;
        struct regulator *reg;
 
        if (hdmi.vdda_reg != NULL)
@@ -114,15 +114,6 @@ static int hdmi_init_regulator(void)
                return PTR_ERR(reg);
        }
 
-       if (regulator_can_change_voltage(reg)) {
-               r = regulator_set_voltage(reg, 1800000, 1800000);
-               if (r) {
-                       devm_regulator_put(reg);
-                       DSSWARN("can't set the regulator voltage\n");
-                       return r;
-               }
-       }
-
        hdmi.vdda_reg = reg;
 
        return 0;
index fa72e73..ef3afe9 100644 (file)
@@ -211,7 +211,7 @@ static void hdmi_core_init(struct hdmi_core_video_config *video_cfg)
 static void hdmi_core_powerdown_disable(struct hdmi_core_data *core)
 {
        DSSDBG("Enter hdmi_core_powerdown_disable\n");
-       REG_FLD_MOD(core->base, HDMI_CORE_SYS_SYS_CTRL1, 0x0, 0, 0);
+       REG_FLD_MOD(core->base, HDMI_CORE_SYS_SYS_CTRL1, 0x1, 0, 0);
 }
 
 static void hdmi_core_swreset_release(struct hdmi_core_data *core)
index a43f7b1..9255c0e 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/gpio.h>
 #include <linux/regulator/consumer.h>
 #include <linux/component.h>
+#include <linux/of.h>
 #include <video/omapdss.h>
 #include <sound/omap-hdmi-audio.h>
 
@@ -119,7 +120,6 @@ static irqreturn_t hdmi_irq_handler(int irq, void *data)
 
 static int hdmi_init_regulator(void)
 {
-       int r;
        struct regulator *reg;
 
        if (hdmi.vdda_reg != NULL)
@@ -131,15 +131,6 @@ static int hdmi_init_regulator(void)
                return PTR_ERR(reg);
        }
 
-       if (regulator_can_change_voltage(reg)) {
-               r = regulator_set_voltage(reg, 1800000, 1800000);
-               if (r) {
-                       devm_regulator_put(reg);
-                       DSSWARN("can't set the regulator voltage\n");
-                       return r;
-               }
-       }
-
        hdmi.vdda_reg = reg;
 
        return 0;
index 6a39752..8ab2093 100644 (file)
@@ -51,8 +51,8 @@ static void hdmi_core_ddc_init(struct hdmi_core_data *core)
 {
        void __iomem *base = core->base;
        const unsigned long long iclk = 266000000;      /* DSS L3 ICLK */
-       const unsigned ss_scl_high = 4000;              /* ns */
-       const unsigned ss_scl_low = 4700;               /* ns */
+       const unsigned ss_scl_high = 4600;              /* ns */
+       const unsigned ss_scl_low = 5400;               /* ns */
        const unsigned fs_scl_high = 600;               /* ns */
        const unsigned fs_scl_low = 1300;               /* ns */
        const unsigned sda_hold = 1000;                 /* ns */
@@ -458,7 +458,7 @@ static void hdmi_core_write_avi_infoframe(struct hdmi_core_data *core,
 
        c = (ptr[1] >> 6) & 0x3;
        m = (ptr[1] >> 4) & 0x3;
-       r = (ptr[1] >> 0) & 0x3;
+       r = (ptr[1] >> 0) & 0xf;
 
        itc = (ptr[2] >> 7) & 0x1;
        ec = (ptr[2] >> 4) & 0x7;
index 1f5d19c..f98b750 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
+#include <linux/seq_file.h>
 #include <video/omapdss.h>
 
 #include "dss.h"
index 06e23a7..f1015e8 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
+#include <linux/seq_file.h>
 
 #include <video/omapdss.h>
 
index 13442b9..055f62f 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
+#include <linux/seq_file.h>
 #include <video/omapdss.h>
 
 #include "dss.h"
index 6f5fc14..479bf24 100644 (file)
@@ -17,6 +17,8 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/seq_file.h>
+
 #include <drm/drm_crtc.h>
 #include <drm/drm_fb_helper.h>
 
index de275a5..4ceed7a 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h> /* platform_device() */
 #include <linux/sched.h>
+#include <linux/seq_file.h>
 #include <linux/slab.h>
 #include <linux/time.h>
 #include <linux/vmalloc.h>
index 94ec06d..f84570d 100644 (file)
@@ -17,6 +17,8 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/seq_file.h>
+
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
 
index b97afc2..03698b6 100644 (file)
@@ -17,6 +17,7 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/seq_file.h>
 #include <linux/shmem_fs.h>
 #include <linux/spinlock.h>
 #include <linux/pfn_t.h>
index 2e216e2..259cd6e 100644 (file)
@@ -589,7 +589,8 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
                if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev) || ASIC_IS_DCE8(rdev))
                        radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV;
                /* use frac fb div on RS780/RS880 */
-               if ((rdev->family == CHIP_RS780) || (rdev->family == CHIP_RS880))
+               if (((rdev->family == CHIP_RS780) || (rdev->family == CHIP_RS880))
+                   && !radeon_crtc->ss_enabled)
                        radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV;
                if (ASIC_IS_DCE32(rdev) && mode->clock > 165000)
                        radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV;
@@ -626,7 +627,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
                        if (radeon_crtc->ss.refdiv) {
                                radeon_crtc->pll_flags |= RADEON_PLL_USE_REF_DIV;
                                radeon_crtc->pll_reference_div = radeon_crtc->ss.refdiv;
-                               if (ASIC_IS_AVIVO(rdev))
+                               if (rdev->family >= CHIP_RV770)
                                        radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV;
                        }
                }
index e721e6b..21c44b2 100644 (file)
@@ -630,6 +630,23 @@ void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc)
 /*
  * GPU helpers function.
  */
+
+/**
+ * radeon_device_is_virtual - check if we are running is a virtual environment
+ *
+ * Check if the asic has been passed through to a VM (all asics).
+ * Used at driver startup.
+ * Returns true if virtual or false if not.
+ */
+static bool radeon_device_is_virtual(void)
+{
+#ifdef CONFIG_X86
+       return boot_cpu_has(X86_FEATURE_HYPERVISOR);
+#else
+       return false;
+#endif
+}
+
 /**
  * radeon_card_posted - check if the hw has already been initialized
  *
@@ -643,6 +660,10 @@ bool radeon_card_posted(struct radeon_device *rdev)
 {
        uint32_t reg;
 
+       /* for pass through, always force asic_init */
+       if (radeon_device_is_virtual())
+               return false;
+
        /* required for EFI mode on macbook2,1 which uses an r5xx asic */
        if (efi_enabled(EFI_BOOT) &&
            (rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE) &&
@@ -1631,7 +1652,7 @@ int radeon_suspend_kms(struct drm_device *dev, bool suspend,
        radeon_agp_suspend(rdev);
 
        pci_save_state(dev->pdev);
-       if (freeze && rdev->family >= CHIP_R600) {
+       if (freeze && rdev->family >= CHIP_CEDAR) {
                rdev->asic->asic_reset(rdev, true);
                pci_restore_state(dev->pdev);
        } else if (suspend) {
index 505620c..e04deed 100644 (file)
@@ -51,15 +51,6 @@ static void sti_crtc_disabling(struct drm_crtc *crtc)
        mixer->status = STI_MIXER_DISABLING;
 }
 
-static bool sti_crtc_mode_fixup(struct drm_crtc *crtc,
-                               const struct drm_display_mode *mode,
-                               struct drm_display_mode *adjusted_mode)
-{
-       /* accept the provided drm_display_mode, do not fix it up */
-       drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
-       return true;
-}
-
 static int
 sti_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode)
 {
@@ -230,7 +221,6 @@ static void sti_crtc_atomic_flush(struct drm_crtc *crtc,
 static const struct drm_crtc_helper_funcs sti_crtc_helper_funcs = {
        .enable = sti_crtc_enable,
        .disable = sti_crtc_disabling,
-       .mode_fixup = sti_crtc_mode_fixup,
        .mode_set = drm_helper_crtc_mode_set,
        .mode_set_nofb = sti_crtc_mode_set_nofb,
        .mode_set_base = drm_helper_crtc_mode_set_base,
index 99510e6..a4b357d 100644 (file)
@@ -1,6 +1,6 @@
 config DRM_SUN4I
        tristate "DRM Support for Allwinner A10 Display Engine"
-       depends on DRM && ARM
+       depends on DRM && ARM && COMMON_CLK
        depends on ARCH_SUNXI || COMPILE_TEST
        select DRM_GEM_CMA_HELPER
        select DRM_KMS_HELPER
index f7a15c1..3ab5604 100644 (file)
@@ -190,7 +190,7 @@ int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend,
        /* Get the physical address of the buffer in memory */
        gem = drm_fb_cma_get_gem_obj(fb, 0);
 
-       DRM_DEBUG_DRIVER("Using GEM @ 0x%x\n", gem->paddr);
+       DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->paddr);
 
        /* Compute the start of the displayed memory */
        bpp = drm_format_plane_cpp(fb->pixel_format, 0);
@@ -198,7 +198,7 @@ int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend,
        paddr += (state->src_x >> 16) * bpp;
        paddr += (state->src_y >> 16) * fb->pitches[0];
 
-       DRM_DEBUG_DRIVER("Setting buffer address to 0x%x\n", paddr);
+       DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
 
        /* Write the 32 lower bits of the address (in bits) */
        lo_paddr = paddr << 3;
index 3ff668c..5b34631 100644 (file)
@@ -72,14 +72,40 @@ static unsigned long sun4i_dclk_recalc_rate(struct clk_hw *hw,
 static long sun4i_dclk_round_rate(struct clk_hw *hw, unsigned long rate,
                                  unsigned long *parent_rate)
 {
-       return *parent_rate / DIV_ROUND_CLOSEST(*parent_rate, rate);
+       unsigned long best_parent = 0;
+       u8 best_div = 1;
+       int i;
+
+       for (i = 6; i < 127; i++) {
+               unsigned long ideal = rate * i;
+               unsigned long rounded;
+
+               rounded = clk_hw_round_rate(clk_hw_get_parent(hw),
+                                           ideal);
+
+               if (rounded == ideal) {
+                       best_parent = rounded;
+                       best_div = i;
+                       goto out;
+               }
+
+               if ((rounded < ideal) && (rounded > best_parent)) {
+                       best_parent = rounded;
+                       best_div = i;
+               }
+       }
+
+out:
+       *parent_rate = best_parent;
+
+       return best_parent / best_div;
 }
 
 static int sun4i_dclk_set_rate(struct clk_hw *hw, unsigned long rate,
                               unsigned long parent_rate)
 {
        struct sun4i_dclk *dclk = hw_to_dclk(hw);
-       int div = DIV_ROUND_CLOSEST(parent_rate, rate);
+       u8 div = parent_rate / rate;
 
        return regmap_update_bits(dclk->regmap, SUN4I_TCON0_DCLK_REG,
                                  GENMASK(6, 0), div);
@@ -127,10 +153,14 @@ int sun4i_dclk_create(struct device *dev, struct sun4i_tcon *tcon)
        const char *clk_name, *parent_name;
        struct clk_init_data init;
        struct sun4i_dclk *dclk;
+       int ret;
 
        parent_name = __clk_get_name(tcon->sclk0);
-       of_property_read_string_index(dev->of_node, "clock-output-names", 0,
-                                     &clk_name);
+       ret = of_property_read_string_index(dev->of_node,
+                                           "clock-output-names", 0,
+                                           &clk_name);
+       if (ret)
+               return ret;
 
        dclk = devm_kzalloc(dev, sizeof(*dclk), GFP_KERNEL);
        if (!dclk)
@@ -140,6 +170,7 @@ int sun4i_dclk_create(struct device *dev, struct sun4i_tcon *tcon)
        init.ops = &sun4i_dclk_ops;
        init.parent_names = &parent_name;
        init.num_parents = 1;
+       init.flags = CLK_SET_RATE_PARENT;
 
        dclk->regmap = tcon->regs;
        dclk->hw.init = &init;
index 76e922b..257d2b4 100644 (file)
 #include "sun4i_layer.h"
 #include "sun4i_tcon.h"
 
-static int sun4i_drv_connector_plug_all(struct drm_device *drm)
-{
-       struct drm_connector *connector, *failed;
-       int ret;
-
-       mutex_lock(&drm->mode_config.mutex);
-       list_for_each_entry(connector, &drm->mode_config.connector_list, head) {
-               ret = drm_connector_register(connector);
-               if (ret) {
-                       failed = connector;
-                       goto err;
-               }
-       }
-       mutex_unlock(&drm->mode_config.mutex);
-       return 0;
-
-err:
-       list_for_each_entry(connector, &drm->mode_config.connector_list, head) {
-               if (failed == connector)
-                       break;
-
-               drm_connector_unregister(connector);
-       }
-       mutex_unlock(&drm->mode_config.mutex);
-
-       return ret;
-}
-
 static int sun4i_drv_enable_vblank(struct drm_device *drm, unsigned int pipe)
 {
        struct sun4i_drv *drv = drm->dev_private;
@@ -125,6 +97,22 @@ static struct drm_driver sun4i_drv_driver = {
        .disable_vblank         = sun4i_drv_disable_vblank,
 };
 
+static void sun4i_remove_framebuffers(void)
+{
+       struct apertures_struct *ap;
+
+       ap = alloc_apertures(1);
+       if (!ap)
+               return;
+
+       /* The framebuffer can be located anywhere in RAM */
+       ap->ranges[0].base = 0;
+       ap->ranges[0].size = ~0;
+
+       remove_conflicting_framebuffers(ap, "sun4i-drm-fb", false);
+       kfree(ap);
+}
+
 static int sun4i_drv_bind(struct device *dev)
 {
        struct drm_device *drm;
@@ -172,6 +160,9 @@ static int sun4i_drv_bind(struct device *dev)
        }
        drm->irq_enabled = true;
 
+       /* Remove early framebuffers (ie. simplefb) */
+       sun4i_remove_framebuffers();
+
        /* Create our framebuffer */
        drv->fbdev = sun4i_framebuffer_init(drm);
        if (IS_ERR(drv->fbdev)) {
@@ -187,7 +178,7 @@ static int sun4i_drv_bind(struct device *dev)
        if (ret)
                goto free_drm;
 
-       ret = sun4i_drv_connector_plug_all(drm);
+       ret = drm_connector_register_all(drm);
        if (ret)
                goto unregister_drm;
 
@@ -204,6 +195,7 @@ static void sun4i_drv_unbind(struct device *dev)
 {
        struct drm_device *drm = dev_get_drvdata(dev);
 
+       drm_connector_unregister_all(drm);
        drm_dev_unregister(drm);
        drm_kms_helper_poll_fini(drm);
        sun4i_framebuffer_free(drm);
index ab64948..aaffe9e 100644 (file)
@@ -54,8 +54,13 @@ static int sun4i_rgb_get_modes(struct drm_connector *connector)
 static int sun4i_rgb_mode_valid(struct drm_connector *connector,
                                struct drm_display_mode *mode)
 {
+       struct sun4i_rgb *rgb = drm_connector_to_sun4i_rgb(connector);
+       struct sun4i_drv *drv = rgb->drv;
+       struct sun4i_tcon *tcon = drv->tcon;
        u32 hsync = mode->hsync_end - mode->hsync_start;
        u32 vsync = mode->vsync_end - mode->vsync_start;
+       unsigned long rate = mode->clock * 1000;
+       long rounded_rate;
 
        DRM_DEBUG_DRIVER("Validating modes...\n");
 
@@ -87,6 +92,15 @@ static int sun4i_rgb_mode_valid(struct drm_connector *connector,
 
        DRM_DEBUG_DRIVER("Vertical parameters OK\n");
 
+       rounded_rate = clk_round_rate(tcon->dclk, rate);
+       if (rounded_rate < rate)
+               return MODE_CLOCK_LOW;
+
+       if (rounded_rate > rate)
+               return MODE_CLOCK_HIGH;
+
+       DRM_DEBUG_DRIVER("Clock rate OK\n");
+
        return MODE_OK;
 }
 
@@ -203,7 +217,7 @@ int sun4i_rgb_init(struct drm_device *drm)
        int ret;
 
        /* If we don't have a panel, there's no point in going on */
-       if (!tcon->panel)
+       if (IS_ERR(tcon->panel))
                return -ENODEV;
 
        rgb = devm_kzalloc(drm->dev, sizeof(*rgb), GFP_KERNEL);
index 9f19b0e..652385f 100644 (file)
@@ -425,11 +425,11 @@ static struct drm_panel *sun4i_tcon_find_panel(struct device_node *node)
 
        remote = of_graph_get_remote_port_parent(end_node);
        if (!remote) {
-               DRM_DEBUG_DRIVER("Enable to parse remote node\n");
+               DRM_DEBUG_DRIVER("Unable to parse remote node\n");
                return ERR_PTR(-EINVAL);
        }
 
-       return of_drm_find_panel(remote);
+       return of_drm_find_panel(remote) ?: ERR_PTR(-EPROBE_DEFER);
 }
 
 static int sun4i_tcon_bind(struct device *dev, struct device *master,
@@ -490,7 +490,11 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
                return 0;
        }
 
-       return sun4i_rgb_init(drm);
+       ret = sun4i_rgb_init(drm);
+       if (ret < 0)
+               goto err_free_clocks;
+
+       return 0;
 
 err_free_clocks:
        sun4i_tcon_free_clocks(tcon);
@@ -522,12 +526,13 @@ static int sun4i_tcon_probe(struct platform_device *pdev)
         * Defer the probe.
         */
        panel = sun4i_tcon_find_panel(node);
-       if (IS_ERR(panel)) {
-               /*
-                * If we don't have a panel endpoint, just go on
-                */
-               if (PTR_ERR(panel) != -ENODEV)
-                       return -EPROBE_DEFER;
+
+       /*
+        * If we don't have a panel endpoint, just go on
+        */
+       if (PTR_ERR(panel) == -EPROBE_DEFER) {
+               DRM_DEBUG_DRIVER("Still waiting for our panel. Deferring...\n");
+               return -EPROBE_DEFER;
        }
 
        return component_add(&pdev->dev, &sun4i_tcon_ops);
index 904d075..0f18b76 100644 (file)
@@ -456,14 +456,6 @@ static void vc4_crtc_atomic_flush(struct drm_crtc *crtc,
 
        WARN_ON_ONCE(dlist_next - dlist_start != vc4_state->mm.size);
 
-       HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
-                 vc4_state->mm.start);
-
-       if (debug_dump_regs) {
-               DRM_INFO("CRTC %d HVS after:\n", drm_crtc_index(crtc));
-               vc4_hvs_dump_state(dev);
-       }
-
        if (crtc->state->event) {
                unsigned long flags;
 
@@ -473,8 +465,20 @@ static void vc4_crtc_atomic_flush(struct drm_crtc *crtc,
 
                spin_lock_irqsave(&dev->event_lock, flags);
                vc4_crtc->event = crtc->state->event;
-               spin_unlock_irqrestore(&dev->event_lock, flags);
                crtc->state->event = NULL;
+
+               HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
+                         vc4_state->mm.start);
+
+               spin_unlock_irqrestore(&dev->event_lock, flags);
+       } else {
+               HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
+                         vc4_state->mm.start);
+       }
+
+       if (debug_dump_regs) {
+               DRM_INFO("CRTC %d HVS after:\n", drm_crtc_index(crtc));
+               vc4_hvs_dump_state(dev);
        }
 }
 
@@ -500,12 +504,17 @@ static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc)
 {
        struct drm_crtc *crtc = &vc4_crtc->base;
        struct drm_device *dev = crtc->dev;
+       struct vc4_dev *vc4 = to_vc4_dev(dev);
+       struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
+       u32 chan = vc4_crtc->channel;
        unsigned long flags;
 
        spin_lock_irqsave(&dev->event_lock, flags);
-       if (vc4_crtc->event) {
+       if (vc4_crtc->event &&
+           (vc4_state->mm.start == HVS_READ(SCALER_DISPLACTX(chan)))) {
                drm_crtc_send_vblank_event(crtc, vc4_crtc->event);
                vc4_crtc->event = NULL;
+               drm_crtc_vblank_put(crtc);
        }
        spin_unlock_irqrestore(&dev->event_lock, flags);
 }
@@ -556,6 +565,7 @@ vc4_async_page_flip_complete(struct vc4_seqno_cb *cb)
                spin_unlock_irqrestore(&dev->event_lock, flags);
        }
 
+       drm_crtc_vblank_put(crtc);
        drm_framebuffer_unreference(flip_state->fb);
        kfree(flip_state);
 
@@ -598,6 +608,8 @@ static int vc4_async_page_flip(struct drm_crtc *crtc,
                return ret;
        }
 
+       WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+
        /* Immediately update the plane's legacy fb pointer, so that later
         * modeset prep sees the state that will be present when the semaphore
         * is released.
index 3446ece..250ed7e 100644 (file)
@@ -66,12 +66,12 @@ static const struct file_operations vc4_drm_fops = {
 };
 
 static const struct drm_ioctl_desc vc4_drm_ioctls[] = {
-       DRM_IOCTL_DEF_DRV(VC4_SUBMIT_CL, vc4_submit_cl_ioctl, 0),
-       DRM_IOCTL_DEF_DRV(VC4_WAIT_SEQNO, vc4_wait_seqno_ioctl, 0),
-       DRM_IOCTL_DEF_DRV(VC4_WAIT_BO, vc4_wait_bo_ioctl, 0),
-       DRM_IOCTL_DEF_DRV(VC4_CREATE_BO, vc4_create_bo_ioctl, 0),
-       DRM_IOCTL_DEF_DRV(VC4_MMAP_BO, vc4_mmap_bo_ioctl, 0),
-       DRM_IOCTL_DEF_DRV(VC4_CREATE_SHADER_BO, vc4_create_shader_bo_ioctl, 0),
+       DRM_IOCTL_DEF_DRV(VC4_SUBMIT_CL, vc4_submit_cl_ioctl, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(VC4_WAIT_SEQNO, vc4_wait_seqno_ioctl, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(VC4_WAIT_BO, vc4_wait_bo_ioctl, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(VC4_CREATE_BO, vc4_create_bo_ioctl, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(VC4_MMAP_BO, vc4_mmap_bo_ioctl, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(VC4_CREATE_SHADER_BO, vc4_create_shader_bo_ioctl, DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(VC4_GET_HANG_STATE, vc4_get_hang_state_ioctl,
                          DRM_ROOT_ONLY),
 };
@@ -91,7 +91,7 @@ static struct drm_driver vc4_drm_driver = {
 
        .enable_vblank = vc4_enable_vblank,
        .disable_vblank = vc4_disable_vblank,
-       .get_vblank_counter = drm_vblank_count,
+       .get_vblank_counter = drm_vblank_no_hw_counter,
 
 #if defined(CONFIG_DEBUG_FS)
        .debugfs_init = vc4_debugfs_init,
index cb37751..861a623 100644 (file)
@@ -117,10 +117,18 @@ static int vc4_atomic_commit(struct drm_device *dev,
                return -ENOMEM;
 
        /* Make sure that any outstanding modesets have finished. */
-       ret = down_interruptible(&vc4->async_modeset);
-       if (ret) {
-               kfree(c);
-               return ret;
+       if (nonblock) {
+               ret = down_trylock(&vc4->async_modeset);
+               if (ret) {
+                       kfree(c);
+                       return -EBUSY;
+               }
+       } else {
+               ret = down_interruptible(&vc4->async_modeset);
+               if (ret) {
+                       kfree(c);
+                       return ret;
+               }
        }
 
        ret = drm_atomic_helper_prepare_planes(dev, state);
index 6163b95..f99eece 100644 (file)
 #define SCALER_DISPLACT0                        0x00000030
 #define SCALER_DISPLACT1                        0x00000034
 #define SCALER_DISPLACT2                        0x00000038
+#define SCALER_DISPLACTX(x)                    (SCALER_DISPLACT0 +     \
+                                                (x) * (SCALER_DISPLACT1 - \
+                                                       SCALER_DISPLACT0))
+
 #define SCALER_DISPCTRL0                        0x00000040
 # define SCALER_DISPCTRLX_ENABLE               BIT(31)
 # define SCALER_DISPCTRLX_RESET                        BIT(30)
index 6de283c..f0374f9 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/frame.h>
 #include <asm/hypervisor.h>
 #include "drmP.h"
 #include "vmwgfx_msg.h"
@@ -194,7 +195,7 @@ static int vmw_send_msg(struct rpc_channel *channel, const char *msg)
 
        return -EINVAL;
 }
-
+STACK_FRAME_NON_STANDARD(vmw_send_msg);
 
 
 /**
@@ -304,6 +305,7 @@ static int vmw_recv_msg(struct rpc_channel *channel, void **msg,
 
        return 0;
 }
+STACK_FRAME_NON_STANDARD(vmw_recv_msg);
 
 
 /**
index aad8c16..0cd4f72 100644 (file)
@@ -261,7 +261,7 @@ static void elo_remove(struct hid_device *hdev)
        struct elo_priv *priv = hid_get_drvdata(hdev);
 
        hid_hw_stop(hdev);
-       flush_workqueue(wq);
+       cancel_delayed_work_sync(&priv->work);
        kfree(priv);
 }
 
index c741f5e..95b7d61 100644 (file)
@@ -1401,6 +1401,11 @@ static const struct hid_device_id mt_devices[] = {
                MT_USB_DEVICE(USB_VENDOR_ID_NOVATEK,
                        USB_DEVICE_ID_NOVATEK_PCT) },
 
+       /* Ntrig Panel */
+       { .driver_data = MT_CLS_NSMU,
+               HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
+                       USB_VENDOR_ID_NTRIG, 0x1b05) },
+
        /* PixArt optical touch screen */
        { .driver_data = MT_CLS_INRANGE_CONTACTNUMBER,
                MT_USB_DEVICE(USB_VENDOR_ID_PIXART,
index 2f1ddca..700145b 100644 (file)
@@ -516,13 +516,13 @@ static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd,
                                        goto inval;
                        } else if (uref->usage_index >= field->report_count)
                                goto inval;
-
-                       else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) &&
-                                (uref_multi->num_values > HID_MAX_MULTI_USAGES ||
-                                 uref->usage_index + uref_multi->num_values > field->report_count))
-                               goto inval;
                }
 
+               if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) &&
+                   (uref_multi->num_values > HID_MAX_MULTI_USAGES ||
+                    uref->usage_index + uref_multi->num_values > field->report_count))
+                       goto inval;
+
                switch (cmd) {
                case HIDIOCGUSAGE:
                        uref->value = field->value[uref->usage_index];
index c43318d..2ac87d5 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/uaccess.h>
 #include <linux/io.h>
 #include <linux/sched.h>
+#include <linux/ctype.h>
 
 #include <linux/i8k.h>
 
 
 static DEFINE_MUTEX(i8k_mutex);
 static char bios_version[4];
+static char bios_machineid[16];
 static struct device *i8k_hwmon_dev;
 static u32 i8k_hwmon_flags;
 static uint i8k_fan_mult = I8K_FAN_MULT;
 static uint i8k_pwm_mult;
 static uint i8k_fan_max = I8K_FAN_HIGH;
+static bool disallow_fan_type_call;
 
 #define I8K_HWMON_HAVE_TEMP1   (1 << 0)
 #define I8K_HWMON_HAVE_TEMP2   (1 << 1)
@@ -94,13 +97,13 @@ module_param(ignore_dmi, bool, 0);
 MODULE_PARM_DESC(ignore_dmi, "Continue probing hardware even if DMI data does not match");
 
 #if IS_ENABLED(CONFIG_I8K)
-static bool restricted;
+static bool restricted = true;
 module_param(restricted, bool, 0);
-MODULE_PARM_DESC(restricted, "Allow fan control if SYS_ADMIN capability set");
+MODULE_PARM_DESC(restricted, "Restrict fan control and serial number to CAP_SYS_ADMIN (default: 1)");
 
 static bool power_status;
 module_param(power_status, bool, 0600);
-MODULE_PARM_DESC(power_status, "Report power status in /proc/i8k");
+MODULE_PARM_DESC(power_status, "Report power status in /proc/i8k (default: 0)");
 #endif
 
 static uint fan_mult;
@@ -235,14 +238,28 @@ static int i8k_get_fan_speed(int fan)
 /*
  * Read the fan type.
  */
-static int i8k_get_fan_type(int fan)
+static int _i8k_get_fan_type(int fan)
 {
        struct smm_regs regs = { .eax = I8K_SMM_GET_FAN_TYPE, };
 
+       if (disallow_fan_type_call)
+               return -EINVAL;
+
        regs.ebx = fan & 0xff;
        return i8k_smm(&regs) ? : regs.eax & 0xff;
 }
 
+static int i8k_get_fan_type(int fan)
+{
+       /* I8K_SMM_GET_FAN_TYPE SMM call is expensive, so cache values */
+       static int types[2] = { INT_MIN, INT_MIN };
+
+       if (types[fan] == INT_MIN)
+               types[fan] = _i8k_get_fan_type(fan);
+
+       return types[fan];
+}
+
 /*
  * Read the fan nominal rpm for specific fan speed.
  */
@@ -387,14 +404,20 @@ i8k_ioctl_unlocked(struct file *fp, unsigned int cmd, unsigned long arg)
 
        switch (cmd) {
        case I8K_BIOS_VERSION:
+               if (!isdigit(bios_version[0]) || !isdigit(bios_version[1]) ||
+                   !isdigit(bios_version[2]))
+                       return -EINVAL;
+
                val = (bios_version[0] << 16) |
                                (bios_version[1] << 8) | bios_version[2];
                break;
 
        case I8K_MACHINE_ID:
-               memset(buff, 0, 16);
-               strlcpy(buff, i8k_get_dmi_data(DMI_PRODUCT_SERIAL),
-                       sizeof(buff));
+               if (restricted && !capable(CAP_SYS_ADMIN))
+                       return -EPERM;
+
+               memset(buff, 0, sizeof(buff));
+               strlcpy(buff, bios_machineid, sizeof(buff));
                break;
 
        case I8K_FN_STATUS:
@@ -511,7 +534,7 @@ static int i8k_proc_show(struct seq_file *seq, void *offset)
        seq_printf(seq, "%s %s %s %d %d %d %d %d %d %d\n",
                   I8K_PROC_FMT,
                   bios_version,
-                  i8k_get_dmi_data(DMI_PRODUCT_SERIAL),
+                  (restricted && !capable(CAP_SYS_ADMIN)) ? "-1" : bios_machineid,
                   cpu_temp,
                   left_fan, right_fan, left_speed, right_speed,
                   ac_power, fn_key);
@@ -718,6 +741,9 @@ static struct attribute *i8k_attrs[] = {
 static umode_t i8k_is_visible(struct kobject *kobj, struct attribute *attr,
                              int index)
 {
+       if (disallow_fan_type_call &&
+           (index == 9 || index == 12))
+               return 0;
        if (index >= 0 && index <= 1 &&
            !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP1))
                return 0;
@@ -767,13 +793,17 @@ static int __init i8k_init_hwmon(void)
        if (err >= 0)
                i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP4;
 
-       /* First fan attributes, if fan type is OK */
-       err = i8k_get_fan_type(0);
+       /* First fan attributes, if fan status or type is OK */
+       err = i8k_get_fan_status(0);
+       if (err < 0)
+               err = i8k_get_fan_type(0);
        if (err >= 0)
                i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN1;
 
-       /* Second fan attributes, if fan type is OK */
-       err = i8k_get_fan_type(1);
+       /* Second fan attributes, if fan status or type is OK */
+       err = i8k_get_fan_status(1);
+       if (err < 0)
+               err = i8k_get_fan_type(1);
        if (err >= 0)
                i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN2;
 
@@ -929,12 +959,14 @@ static struct dmi_system_id i8k_dmi_table[] __initdata = {
 
 MODULE_DEVICE_TABLE(dmi, i8k_dmi_table);
 
-static struct dmi_system_id i8k_blacklist_dmi_table[] __initdata = {
+/*
+ * On some machines once I8K_SMM_GET_FAN_TYPE is issued then CPU fan speed
+ * randomly going up and down due to bug in Dell SMM or BIOS. Here is blacklist
+ * of affected Dell machines for which we disallow I8K_SMM_GET_FAN_TYPE call.
+ * See bug: https://bugzilla.kernel.org/show_bug.cgi?id=100121
+ */
+static struct dmi_system_id i8k_blacklist_fan_type_dmi_table[] __initdata = {
        {
-               /*
-                * CPU fan speed going up and down on Dell Studio XPS 8000
-                * for unknown reasons.
-                */
                .ident = "Dell Studio XPS 8000",
                .matches = {
                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
@@ -942,16 +974,19 @@ static struct dmi_system_id i8k_blacklist_dmi_table[] __initdata = {
                },
        },
        {
-               /*
-                * CPU fan speed going up and down on Dell Studio XPS 8100
-                * for unknown reasons.
-                */
                .ident = "Dell Studio XPS 8100",
                .matches = {
                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
                        DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Studio XPS 8100"),
                },
        },
+       {
+               .ident = "Dell Inspiron 580",
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Inspiron 580 "),
+               },
+       },
        { }
 };
 
@@ -966,8 +1001,7 @@ static int __init i8k_probe(void)
        /*
         * Get DMI information
         */
-       if (!dmi_check_system(i8k_dmi_table) ||
-           dmi_check_system(i8k_blacklist_dmi_table)) {
+       if (!dmi_check_system(i8k_dmi_table)) {
                if (!ignore_dmi && !force)
                        return -ENODEV;
 
@@ -978,8 +1012,13 @@ static int __init i8k_probe(void)
                        i8k_get_dmi_data(DMI_BIOS_VERSION));
        }
 
+       if (dmi_check_system(i8k_blacklist_fan_type_dmi_table))
+               disallow_fan_type_call = true;
+
        strlcpy(bios_version, i8k_get_dmi_data(DMI_BIOS_VERSION),
                sizeof(bios_version));
+       strlcpy(bios_machineid, i8k_get_dmi_data(DMI_PRODUCT_SERIAL),
+               sizeof(bios_machineid));
 
        /*
         * Get SMM Dell signature
index eb97a92..15aa49d 100644 (file)
@@ -172,9 +172,9 @@ static void do_read_registers_on_cu(void *_data)
  */
 static int read_registers(struct fam15h_power_data *data)
 {
-       int this_cpu, ret, cpu;
        int core, this_core;
        cpumask_var_t mask;
+       int ret, cpu;
 
        ret = zalloc_cpumask_var(&mask, GFP_KERNEL);
        if (!ret)
@@ -183,7 +183,6 @@ static int read_registers(struct fam15h_power_data *data)
        memset(data->cu_on, 0, sizeof(int) * MAX_CUS);
 
        get_online_cpus();
-       this_cpu = smp_processor_id();
 
        /*
         * Choose the first online core of each compute unit, and then
@@ -205,12 +204,9 @@ static int read_registers(struct fam15h_power_data *data)
                cpumask_set_cpu(cpumask_any(topology_sibling_cpumask(cpu)), mask);
        }
 
-       if (cpumask_test_cpu(this_cpu, mask))
-               do_read_registers_on_cu(data);
+       on_each_cpu_mask(mask, do_read_registers_on_cu, data, true);
 
-       smp_call_function_many(mask, do_read_registers_on_cu, data, true);
        put_online_cpus();
-
        free_cpumask_var(mask);
 
        return 0;
index c9ff08d..e30a593 100644 (file)
@@ -375,7 +375,7 @@ struct lm90_data {
        int kind;
        u32 flags;
 
-       int update_interval;    /* in milliseconds */
+       unsigned int update_interval; /* in milliseconds */
 
        u8 config_orig;         /* Original configuration register value */
        u8 convrate_orig;       /* Original conversion rate register value */
index 847d1b5..688be9e 100644 (file)
@@ -300,13 +300,10 @@ int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata)
        if (local_read(&drvdata->mode) == CS_MODE_SYSFS) {
                /*
                 * The trace run will continue with the same allocated trace
-                * buffer. As such zero-out the buffer so that we don't end
-                * up with stale data.
-                *
-                * Since the tracer is still enabled drvdata::buf
-                * can't be NULL.
+                * buffer. The trace buffer is cleared in tmc_etr_enable_hw(),
+                * so we don't have to explicitly clear it. Also, since the
+                * tracer is still enabled drvdata::buf can't be NULL.
                 */
-               memset(drvdata->buf, 0, drvdata->size);
                tmc_etr_enable_hw(drvdata);
        } else {
                /*
@@ -315,7 +312,7 @@ int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata)
                 */
                vaddr = drvdata->vaddr;
                paddr = drvdata->paddr;
-               drvdata->buf = NULL;
+               drvdata->buf = drvdata->vaddr = NULL;
        }
 
        drvdata->reading = false;
index 5443d03..d08d1ab 100644 (file)
@@ -385,7 +385,6 @@ static int _coresight_build_path(struct coresight_device *csdev,
        int i;
        bool found = false;
        struct coresight_node *node;
-       struct coresight_connection *conn;
 
        /* An activated sink has been found.  Enqueue the element */
        if ((csdev->type == CORESIGHT_DEV_TYPE_SINK ||
@@ -394,8 +393,9 @@ static int _coresight_build_path(struct coresight_device *csdev,
 
        /* Not a sink - recursively explore each port found on this element */
        for (i = 0; i < csdev->nr_outport; i++) {
-               conn = &csdev->conns[i];
-               if (_coresight_build_path(conn->child_dev, path) == 0) {
+               struct coresight_device *child_dev = csdev->conns[i].child_dev;
+
+               if (child_dev && _coresight_build_path(child_dev, path) == 0) {
                        found = true;
                        break;
                }
@@ -425,6 +425,7 @@ out:
 struct list_head *coresight_build_path(struct coresight_device *csdev)
 {
        struct list_head *path;
+       int rc;
 
        path = kzalloc(sizeof(struct list_head), GFP_KERNEL);
        if (!path)
@@ -432,9 +433,10 @@ struct list_head *coresight_build_path(struct coresight_device *csdev)
 
        INIT_LIST_HEAD(path);
 
-       if (_coresight_build_path(csdev, path)) {
+       rc = _coresight_build_path(csdev, path);
+       if (rc) {
                kfree(path);
-               path = NULL;
+               return ERR_PTR(rc);
        }
 
        return path;
@@ -507,8 +509,9 @@ int coresight_enable(struct coresight_device *csdev)
                goto out;
 
        path = coresight_build_path(csdev);
-       if (!path) {
+       if (IS_ERR(path)) {
                pr_err("building path(s) failed\n");
+               ret = PTR_ERR(path);
                goto out;
        }
 
index 64b1208..4a60ad2 100644 (file)
@@ -245,6 +245,13 @@ struct i801_priv {
        struct platform_device *mux_pdev;
 #endif
        struct platform_device *tco_pdev;
+
+       /*
+        * If set to true the host controller registers are reserved for
+        * ACPI AML use. Protected by acpi_lock.
+        */
+       bool acpi_reserved;
+       struct mutex acpi_lock;
 };
 
 #define FEATURE_SMBUS_PEC      (1 << 0)
@@ -718,6 +725,12 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr,
        int ret = 0, xact = 0;
        struct i801_priv *priv = i2c_get_adapdata(adap);
 
+       mutex_lock(&priv->acpi_lock);
+       if (priv->acpi_reserved) {
+               mutex_unlock(&priv->acpi_lock);
+               return -EBUSY;
+       }
+
        pm_runtime_get_sync(&priv->pci_dev->dev);
 
        hwpec = (priv->features & FEATURE_SMBUS_PEC) && (flags & I2C_CLIENT_PEC)
@@ -820,6 +833,7 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr,
 out:
        pm_runtime_mark_last_busy(&priv->pci_dev->dev);
        pm_runtime_put_autosuspend(&priv->pci_dev->dev);
+       mutex_unlock(&priv->acpi_lock);
        return ret;
 }
 
@@ -1257,6 +1271,83 @@ static void i801_add_tco(struct i801_priv *priv)
        priv->tco_pdev = pdev;
 }
 
+#ifdef CONFIG_ACPI
+static acpi_status
+i801_acpi_io_handler(u32 function, acpi_physical_address address, u32 bits,
+                    u64 *value, void *handler_context, void *region_context)
+{
+       struct i801_priv *priv = handler_context;
+       struct pci_dev *pdev = priv->pci_dev;
+       acpi_status status;
+
+       /*
+        * Once BIOS AML code touches the OpRegion we warn and inhibit any
+        * further access from the driver itself. This device is now owned
+        * by the system firmware.
+        */
+       mutex_lock(&priv->acpi_lock);
+
+       if (!priv->acpi_reserved) {
+               priv->acpi_reserved = true;
+
+               dev_warn(&pdev->dev, "BIOS is accessing SMBus registers\n");
+               dev_warn(&pdev->dev, "Driver SMBus register access inhibited\n");
+
+               /*
+                * BIOS is accessing the host controller so prevent it from
+                * suspending automatically from now on.
+                */
+               pm_runtime_get_sync(&pdev->dev);
+       }
+
+       if ((function & ACPI_IO_MASK) == ACPI_READ)
+               status = acpi_os_read_port(address, (u32 *)value, bits);
+       else
+               status = acpi_os_write_port(address, (u32)*value, bits);
+
+       mutex_unlock(&priv->acpi_lock);
+
+       return status;
+}
+
+static int i801_acpi_probe(struct i801_priv *priv)
+{
+       struct acpi_device *adev;
+       acpi_status status;
+
+       adev = ACPI_COMPANION(&priv->pci_dev->dev);
+       if (adev) {
+               status = acpi_install_address_space_handler(adev->handle,
+                               ACPI_ADR_SPACE_SYSTEM_IO, i801_acpi_io_handler,
+                               NULL, priv);
+               if (ACPI_SUCCESS(status))
+                       return 0;
+       }
+
+       return acpi_check_resource_conflict(&priv->pci_dev->resource[SMBBAR]);
+}
+
+static void i801_acpi_remove(struct i801_priv *priv)
+{
+       struct acpi_device *adev;
+
+       adev = ACPI_COMPANION(&priv->pci_dev->dev);
+       if (!adev)
+               return;
+
+       acpi_remove_address_space_handler(adev->handle,
+               ACPI_ADR_SPACE_SYSTEM_IO, i801_acpi_io_handler);
+
+       mutex_lock(&priv->acpi_lock);
+       if (priv->acpi_reserved)
+               pm_runtime_put(&priv->pci_dev->dev);
+       mutex_unlock(&priv->acpi_lock);
+}
+#else
+static inline int i801_acpi_probe(struct i801_priv *priv) { return 0; }
+static inline void i801_acpi_remove(struct i801_priv *priv) { }
+#endif
+
 static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
        unsigned char temp;
@@ -1274,6 +1365,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
        priv->adapter.dev.parent = &dev->dev;
        ACPI_COMPANION_SET(&priv->adapter.dev, ACPI_COMPANION(&dev->dev));
        priv->adapter.retries = 3;
+       mutex_init(&priv->acpi_lock);
 
        priv->pci_dev = dev;
        switch (dev->device) {
@@ -1336,10 +1428,8 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
                return -ENODEV;
        }
 
-       err = acpi_check_resource_conflict(&dev->resource[SMBBAR]);
-       if (err) {
+       if (i801_acpi_probe(priv))
                return -ENODEV;
-       }
 
        err = pcim_iomap_regions(dev, 1 << SMBBAR,
                                 dev_driver_string(&dev->dev));
@@ -1348,6 +1438,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
                        "Failed to request SMBus region 0x%lx-0x%Lx\n",
                        priv->smba,
                        (unsigned long long)pci_resource_end(dev, SMBBAR));
+               i801_acpi_remove(priv);
                return err;
        }
 
@@ -1412,6 +1503,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
        err = i2c_add_adapter(&priv->adapter);
        if (err) {
                dev_err(&dev->dev, "Failed to add SMBus adapter\n");
+               i801_acpi_remove(priv);
                return err;
        }
 
@@ -1438,6 +1530,7 @@ static void i801_remove(struct pci_dev *dev)
 
        i801_del_mux(priv);
        i2c_del_adapter(&priv->adapter);
+       i801_acpi_remove(priv);
        pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg);
 
        platform_device_unregister(priv->tco_pdev);
index aa5f01e..30ae351 100644 (file)
@@ -934,8 +934,15 @@ static int octeon_i2c_read(struct octeon_i2c *i2c, int target,
                return result;
 
        for (i = 0; i < length; i++) {
-               /* for the last byte TWSI_CTL_AAK must not be set */
-               if (i + 1 == length)
+               /*
+                * For the last byte to receive TWSI_CTL_AAK must not be set.
+                *
+                * A special case is I2C_M_RECV_LEN where we don't know the
+                * additional length yet. If recv_len is set we assume we're
+                * not reading the final byte and therefore need to set
+                * TWSI_CTL_AAK.
+                */
+               if ((i + 1 == length) && !(recv_len && i == 0))
                        final_read = true;
 
                /* clear iflg to allow next event */
@@ -950,12 +957,8 @@ static int octeon_i2c_read(struct octeon_i2c *i2c, int target,
 
                data[i] = octeon_i2c_data_read(i2c);
                if (recv_len && i == 0) {
-                       if (data[i] > I2C_SMBUS_BLOCK_MAX + 1) {
-                               dev_err(i2c->dev,
-                                       "%s: read len > I2C_SMBUS_BLOCK_MAX %d\n",
-                                       __func__, data[i]);
+                       if (data[i] > I2C_SMBUS_BLOCK_MAX + 1)
                                return -EPROTO;
-                       }
                        length += data[i];
                }
 
index 6773cad..26e7c51 100644 (file)
@@ -260,6 +260,7 @@ static struct platform_driver i2c_mux_reg_driver = {
        .remove = i2c_mux_reg_remove,
        .driver = {
                .name   = "i2c-mux-reg",
+               .of_match_table = of_match_ptr(i2c_mux_reg_of_match),
        },
 };
 
index a1e642e..7fddc13 100644 (file)
@@ -91,7 +91,7 @@ static const struct iio_buffer_setup_ops st_accel_buffer_setup_ops = {
 
 int st_accel_allocate_ring(struct iio_dev *indio_dev)
 {
-       return iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
+       return iio_triggered_buffer_setup(indio_dev, NULL,
                &st_sensors_trigger_handler, &st_accel_buffer_setup_ops);
 }
 
index dc73f2d..4d95bfc 100644 (file)
@@ -741,6 +741,7 @@ static const struct iio_info accel_info = {
 static const struct iio_trigger_ops st_accel_trigger_ops = {
        .owner = THIS_MODULE,
        .set_trigger_state = ST_ACCEL_TRIGGER_SET_STATE,
+       .validate_device = st_sensors_validate_device,
 };
 #define ST_ACCEL_TRIGGER_OPS (&st_accel_trigger_ops)
 #else
index c558985..f1693db 100644 (file)
@@ -57,31 +57,20 @@ irqreturn_t st_sensors_trigger_handler(int irq, void *p)
        struct iio_poll_func *pf = p;
        struct iio_dev *indio_dev = pf->indio_dev;
        struct st_sensor_data *sdata = iio_priv(indio_dev);
+       s64 timestamp;
 
-       /* If we have a status register, check if this IRQ came from us */
-       if (sdata->sensor_settings->drdy_irq.addr_stat_drdy) {
-               u8 status;
-
-               len = sdata->tf->read_byte(&sdata->tb, sdata->dev,
-                          sdata->sensor_settings->drdy_irq.addr_stat_drdy,
-                          &status);
-               if (len < 0)
-                       dev_err(sdata->dev, "could not read channel status\n");
-
-               /*
-                * If this was not caused by any channels on this sensor,
-                * return IRQ_NONE
-                */
-               if (!(status & (u8)indio_dev->active_scan_mask[0]))
-                       return IRQ_NONE;
-       }
+       /* If we do timetamping here, do it before reading the values */
+       if (sdata->hw_irq_trigger)
+               timestamp = sdata->hw_timestamp;
+       else
+               timestamp = iio_get_time_ns();
 
        len = st_sensors_get_buffer_element(indio_dev, sdata->buffer_data);
        if (len < 0)
                goto st_sensors_get_buffer_element_error;
 
        iio_push_to_buffers_with_timestamp(indio_dev, sdata->buffer_data,
-               pf->timestamp);
+                                          timestamp);
 
 st_sensors_get_buffer_element_error:
        iio_trigger_notify_done(indio_dev->trig);
index dffe006..9e59c90 100644 (file)
@@ -363,6 +363,11 @@ int st_sensors_init_sensor(struct iio_dev *indio_dev,
        if (err < 0)
                return err;
 
+       /* Disable DRDY, this might be still be enabled after reboot. */
+       err = st_sensors_set_dataready_irq(indio_dev, false);
+       if (err < 0)
+               return err;
+
        if (sdata->current_fullscale) {
                err = st_sensors_set_fullscale(indio_dev,
                                                sdata->current_fullscale->num);
@@ -424,6 +429,9 @@ int st_sensors_set_dataready_irq(struct iio_dev *indio_dev, bool enable)
        else
                drdy_mask = sdata->sensor_settings->drdy_irq.mask_int2;
 
+       /* Flag to the poll function that the hardware trigger is in use */
+       sdata->hw_irq_trigger = enable;
+
        /* Enable/Disable the interrupt generator for data ready. */
        err = st_sensors_write_data_with_mask(indio_dev,
                                        sdata->sensor_settings->drdy_irq.addr,
index da72279..296e4ff 100644 (file)
 #include <linux/iio/common/st_sensors.h>
 #include "st_sensors_core.h"
 
+/**
+ * st_sensors_irq_handler() - top half of the IRQ-based triggers
+ * @irq: irq number
+ * @p: private handler data
+ */
+irqreturn_t st_sensors_irq_handler(int irq, void *p)
+{
+       struct iio_trigger *trig = p;
+       struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+       struct st_sensor_data *sdata = iio_priv(indio_dev);
+
+       /* Get the time stamp as close in time as possible */
+       sdata->hw_timestamp = iio_get_time_ns();
+       return IRQ_WAKE_THREAD;
+}
+
+/**
+ * st_sensors_irq_thread() - bottom half of the IRQ-based triggers
+ * @irq: irq number
+ * @p: private handler data
+ */
+irqreturn_t st_sensors_irq_thread(int irq, void *p)
+{
+       struct iio_trigger *trig = p;
+       struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+       struct st_sensor_data *sdata = iio_priv(indio_dev);
+       int ret;
+
+       /*
+        * If this trigger is backed by a hardware interrupt and we have a
+        * status register, check if this IRQ came from us
+        */
+       if (sdata->sensor_settings->drdy_irq.addr_stat_drdy) {
+               u8 status;
+
+               ret = sdata->tf->read_byte(&sdata->tb, sdata->dev,
+                          sdata->sensor_settings->drdy_irq.addr_stat_drdy,
+                          &status);
+               if (ret < 0) {
+                       dev_err(sdata->dev, "could not read channel status\n");
+                       goto out_poll;
+               }
+               /*
+                * the lower bits of .active_scan_mask[0] is directly mapped
+                * to the channels on the sensor: either bit 0 for
+                * one-dimensional sensors, or e.g. x,y,z for accelerometers,
+                * gyroscopes or magnetometers. No sensor use more than 3
+                * channels, so cut the other status bits here.
+                */
+               status &= 0x07;
+
+               /*
+                * If this was not caused by any channels on this sensor,
+                * return IRQ_NONE
+                */
+               if (!indio_dev->active_scan_mask)
+                       return IRQ_NONE;
+               if (!(status & (u8)indio_dev->active_scan_mask[0]))
+                       return IRQ_NONE;
+       }
+
+out_poll:
+       /* It's our IRQ: proceed to handle the register polling */
+       iio_trigger_poll_chained(p);
+       return IRQ_HANDLED;
+}
+
 int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
                                const struct iio_trigger_ops *trigger_ops)
 {
@@ -30,6 +97,10 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
                return -ENOMEM;
        }
 
+       iio_trigger_set_drvdata(sdata->trig, indio_dev);
+       sdata->trig->ops = trigger_ops;
+       sdata->trig->dev.parent = sdata->dev;
+
        irq = sdata->get_irq_data_ready(indio_dev);
        irq_trig = irqd_get_trigger_type(irq_get_irq_data(irq));
        /*
@@ -77,9 +148,12 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
            sdata->sensor_settings->drdy_irq.addr_stat_drdy)
                irq_trig |= IRQF_SHARED;
 
-       err = request_threaded_irq(irq,
-                       iio_trigger_generic_data_rdy_poll,
-                       NULL,
+       /* Let's create an interrupt thread masking the hard IRQ here */
+       irq_trig |= IRQF_ONESHOT;
+
+       err = request_threaded_irq(sdata->get_irq_data_ready(indio_dev),
+                       st_sensors_irq_handler,
+                       st_sensors_irq_thread,
                        irq_trig,
                        sdata->trig->name,
                        sdata->trig);
@@ -88,10 +162,6 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
                goto iio_trigger_free;
        }
 
-       iio_trigger_set_drvdata(sdata->trig, indio_dev);
-       sdata->trig->ops = trigger_ops;
-       sdata->trig->dev.parent = sdata->dev;
-
        err = iio_trigger_register(sdata->trig);
        if (err < 0) {
                dev_err(&indio_dev->dev, "failed to register iio trigger.\n");
@@ -119,6 +189,18 @@ void st_sensors_deallocate_trigger(struct iio_dev *indio_dev)
 }
 EXPORT_SYMBOL(st_sensors_deallocate_trigger);
 
+int st_sensors_validate_device(struct iio_trigger *trig,
+                              struct iio_dev *indio_dev)
+{
+       struct iio_dev *indio = iio_trigger_get_drvdata(trig);
+
+       if (indio != indio_dev)
+               return -EINVAL;
+
+       return 0;
+}
+EXPORT_SYMBOL(st_sensors_validate_device);
+
 MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
 MODULE_DESCRIPTION("STMicroelectronics ST-sensors trigger");
 MODULE_LICENSE("GPL v2");
index e63b957..f7c71da 100644 (file)
@@ -247,7 +247,7 @@ config MCP4922
 
 config STX104
        tristate "Apex Embedded Systems STX104 DAC driver"
-       depends on X86 && ISA
+       depends on X86 && ISA_BUS_API
        help
          Say yes here to build support for the 2-channel DAC on the Apex
          Embedded Systems STX104 integrated analog PC/104 card. The base port
index 948f600..69bde59 100644 (file)
@@ -525,7 +525,7 @@ static int ad5592r_alloc_channels(struct ad5592r_state *st)
 
        device_for_each_child_node(st->dev, child) {
                ret = fwnode_property_read_u32(child, "reg", &reg);
-               if (ret || reg > ARRAY_SIZE(st->channel_modes))
+               if (ret || reg >= ARRAY_SIZE(st->channel_modes))
                        continue;
 
                ret = fwnode_property_read_u32(child, "adi,mode", &tmp);
index d67b17b..a537704 100644 (file)
@@ -91,7 +91,7 @@ static const struct iio_buffer_setup_ops st_gyro_buffer_setup_ops = {
 
 int st_gyro_allocate_ring(struct iio_dev *indio_dev)
 {
-       return iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
+       return iio_triggered_buffer_setup(indio_dev, NULL,
                &st_sensors_trigger_handler, &st_gyro_buffer_setup_ops);
 }
 
index 52a3c87..a801295 100644 (file)
@@ -409,6 +409,7 @@ static const struct iio_info gyro_info = {
 static const struct iio_trigger_ops st_gyro_trigger_ops = {
        .owner = THIS_MODULE,
        .set_trigger_state = ST_GYRO_TRIGGER_SET_STATE,
+       .validate_device = st_sensors_validate_device,
 };
 #define ST_GYRO_TRIGGER_OPS (&st_gyro_trigger_ops)
 #else
index 3be6d20..1153591 100644 (file)
@@ -165,10 +165,8 @@ static irqreturn_t am2315_trigger_handler(int irq, void *p)
        struct am2315_sensor_data sensor_data;
 
        ret = am2315_read_data(data, &sensor_data);
-       if (ret < 0) {
-               mutex_unlock(&data->lock);
+       if (ret < 0)
                goto err;
-       }
 
        mutex_lock(&data->lock);
        if (*(indio_dev->active_scan_mask) == AM2315_ALL_CHANNEL_MASK) {
index fa47676..a03832a 100644 (file)
@@ -55,7 +55,7 @@ static const struct {
        },
        { /* IIO_HUMIDITYRELATIVE channel */
                .shift = 8,
-               .mask = 2,
+               .mask = 3,
        },
 };
 
@@ -164,14 +164,14 @@ static int hdc100x_get_measurement(struct hdc100x_data *data,
                dev_err(&client->dev, "cannot read high byte measurement");
                return ret;
        }
-       val = ret << 6;
+       val = ret << 8;
 
        ret = i2c_smbus_read_byte(client);
        if (ret < 0) {
                dev_err(&client->dev, "cannot read low byte measurement");
                return ret;
        }
-       val |= ret >> 2;
+       val |= ret;
 
        return val;
 }
@@ -211,18 +211,18 @@ static int hdc100x_read_raw(struct iio_dev *indio_dev,
                return IIO_VAL_INT_PLUS_MICRO;
        case IIO_CHAN_INFO_SCALE:
                if (chan->type == IIO_TEMP) {
-                       *val = 165;
-                       *val2 = 65536 >> 2;
+                       *val = 165000;
+                       *val2 = 65536;
                        return IIO_VAL_FRACTIONAL;
                } else {
-                       *val = 0;
-                       *val2 = 10000;
-                       return IIO_VAL_INT_PLUS_MICRO;
+                       *val = 100;
+                       *val2 = 65536;
+                       return IIO_VAL_FRACTIONAL;
                }
                break;
        case IIO_CHAN_INFO_OFFSET:
-               *val = -3971;
-               *val2 = 879096;
+               *val = -15887;
+               *val2 = 515151;
                return IIO_VAL_INT_PLUS_MICRO;
        default:
                return -EINVAL;
index 0bf92b0..b8a290e 100644 (file)
@@ -209,11 +209,11 @@ static const struct  bmi160_scale_item bmi160_scale_table[] = {
 };
 
 static const struct bmi160_odr bmi160_accel_odr[] = {
-       {0x01, 0, 78125},
-       {0x02, 1, 5625},
-       {0x03, 3, 125},
-       {0x04, 6, 25},
-       {0x05, 12, 5},
+       {0x01, 0, 781250},
+       {0x02, 1, 562500},
+       {0x03, 3, 125000},
+       {0x04, 6, 250000},
+       {0x05, 12, 500000},
        {0x06, 25, 0},
        {0x07, 50, 0},
        {0x08, 100, 0},
@@ -229,7 +229,7 @@ static const struct bmi160_odr bmi160_gyro_odr[] = {
        {0x08, 100, 0},
        {0x09, 200, 0},
        {0x0A, 400, 0},
-       {0x0B, 8000, 0},
+       {0x0B, 800, 0},
        {0x0C, 1600, 0},
        {0x0D, 3200, 0},
 };
@@ -364,8 +364,8 @@ int bmi160_set_odr(struct bmi160_data *data, enum bmi160_sensor_type t,
 
        return regmap_update_bits(data->regmap,
                                  bmi160_regs[t].config,
-                                 bmi160_odr_table[t].tbl[i].bits,
-                                 bmi160_regs[t].config_odr_mask);
+                                 bmi160_regs[t].config_odr_mask,
+                                 bmi160_odr_table[t].tbl[i].bits);
 }
 
 static int bmi160_get_odr(struct bmi160_data *data, enum bmi160_sensor_type t,
index ae2806a..0c52dfe 100644 (file)
@@ -210,22 +210,35 @@ static int iio_trigger_attach_poll_func(struct iio_trigger *trig,
 
        /* Prevent the module from being removed whilst attached to a trigger */
        __module_get(pf->indio_dev->info->driver_module);
+
+       /* Get irq number */
        pf->irq = iio_trigger_get_irq(trig);
+       if (pf->irq < 0)
+               goto out_put_module;
+
+       /* Request irq */
        ret = request_threaded_irq(pf->irq, pf->h, pf->thread,
                                   pf->type, pf->name,
                                   pf);
-       if (ret < 0) {
-               module_put(pf->indio_dev->info->driver_module);
-               return ret;
-       }
+       if (ret < 0)
+               goto out_put_irq;
 
+       /* Enable trigger in driver */
        if (trig->ops && trig->ops->set_trigger_state && notinuse) {
                ret = trig->ops->set_trigger_state(trig, true);
                if (ret < 0)
-                       module_put(pf->indio_dev->info->driver_module);
+                       goto out_free_irq;
        }
 
        return ret;
+
+out_free_irq:
+       free_irq(pf->irq, pf);
+out_put_irq:
+       iio_trigger_put_irq(trig, pf->irq);
+out_put_module:
+       module_put(pf->indio_dev->info->driver_module);
+       return ret;
 }
 
 static int iio_trigger_detach_poll_func(struct iio_trigger *trig,
index b4dbb39..651d57b 100644 (file)
@@ -1011,6 +1011,7 @@ static int apds9960_probe(struct i2c_client *client,
 
        iio_device_attach_buffer(indio_dev, buffer);
 
+       indio_dev->dev.parent = &client->dev;
        indio_dev->info = &apds9960_info;
        indio_dev->name = APDS9960_DRV_NAME;
        indio_dev->channels = apds9960_channels;
index 72b364e..b54dcba 100644 (file)
@@ -84,7 +84,7 @@ static int bh1780_debugfs_reg_access(struct iio_dev *indio_dev,
        int ret;
 
        if (!readval)
-               bh1780_write(bh1780, (u8)reg, (u8)writeval);
+               return bh1780_write(bh1780, (u8)reg, (u8)writeval);
 
        ret = bh1780_read(bh1780, (u8)reg);
        if (ret < 0)
@@ -187,7 +187,7 @@ static int bh1780_probe(struct i2c_client *client,
 
        indio_dev->dev.parent = &client->dev;
        indio_dev->info = &bh1780_info;
-       indio_dev->name = id->name;
+       indio_dev->name = "bh1780";
        indio_dev->channels = bh1780_channels;
        indio_dev->num_channels = ARRAY_SIZE(bh1780_channels);
        indio_dev->modes = INDIO_DIRECT_MODE;
@@ -226,7 +226,8 @@ static int bh1780_remove(struct i2c_client *client)
 static int bh1780_runtime_suspend(struct device *dev)
 {
        struct i2c_client *client = to_i2c_client(dev);
-       struct bh1780_data *bh1780 = i2c_get_clientdata(client);
+       struct iio_dev *indio_dev = i2c_get_clientdata(client);
+       struct bh1780_data *bh1780 = iio_priv(indio_dev);
        int ret;
 
        ret = bh1780_write(bh1780, BH1780_REG_CONTROL, BH1780_POFF);
@@ -241,7 +242,8 @@ static int bh1780_runtime_suspend(struct device *dev)
 static int bh1780_runtime_resume(struct device *dev)
 {
        struct i2c_client *client = to_i2c_client(dev);
-       struct bh1780_data *bh1780 = i2c_get_clientdata(client);
+       struct iio_dev *indio_dev = i2c_get_clientdata(client);
+       struct bh1780_data *bh1780 = iio_priv(indio_dev);
        int ret;
 
        ret = bh1780_write(bh1780, BH1780_REG_CONTROL, BH1780_PON);
index e01e58a..f17cb2e 100644 (file)
@@ -147,7 +147,6 @@ static const struct iio_chan_spec max44000_channels[] = {
        {
                .type = IIO_PROXIMITY,
                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
-               .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
                .scan_index = MAX44000_SCAN_INDEX_PRX,
                .scan_type = {
                        .sign           = 'u',
index ecd3bd0..0a9e8fa 100644 (file)
@@ -82,7 +82,7 @@ static const struct iio_buffer_setup_ops st_magn_buffer_setup_ops = {
 
 int st_magn_allocate_ring(struct iio_dev *indio_dev)
 {
-       return iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
+       return iio_triggered_buffer_setup(indio_dev, NULL,
                &st_sensors_trigger_handler, &st_magn_buffer_setup_ops);
 }
 
index 62036d2..8250fc3 100644 (file)
@@ -572,6 +572,7 @@ static const struct iio_info magn_info = {
 static const struct iio_trigger_ops st_magn_trigger_ops = {
        .owner = THIS_MODULE,
        .set_trigger_state = ST_MAGN_TRIGGER_SET_STATE,
+       .validate_device = st_sensors_validate_device,
 };
 #define ST_MAGN_TRIGGER_OPS (&st_magn_trigger_ops)
 #else
index 2f1498e..724452d 100644 (file)
@@ -879,8 +879,8 @@ static int bmp280_probe(struct i2c_client *client,
        if (ret < 0)
                return ret;
        if (chip_id != id->driver_data) {
-               dev_err(&client->dev, "bad chip id.  expected %x got %x\n",
-                       BMP280_CHIP_ID, chip_id);
+               dev_err(&client->dev, "bad chip id.  expected %lx got %x\n",
+                       id->driver_data, chip_id);
                return -EINVAL;
        }
 
index 2ff53f2..99468d0 100644 (file)
@@ -82,7 +82,7 @@ static const struct iio_buffer_setup_ops st_press_buffer_setup_ops = {
 
 int st_press_allocate_ring(struct iio_dev *indio_dev)
 {
-       return iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
+       return iio_triggered_buffer_setup(indio_dev, NULL,
                &st_sensors_trigger_handler, &st_press_buffer_setup_ops);
 }
 
index 9e9b72a..92a118c 100644 (file)
 #include <linux/iio/common/st_sensors.h>
 #include "st_pressure.h"
 
+#define MCELSIUS_PER_CELSIUS                   1000
+
+/* Default pressure sensitivity */
 #define ST_PRESS_LSB_PER_MBAR                  4096UL
 #define ST_PRESS_KPASCAL_NANO_SCALE            (100000000UL / \
                                                 ST_PRESS_LSB_PER_MBAR)
+
+/* Default temperature sensitivity */
 #define ST_PRESS_LSB_PER_CELSIUS               480UL
-#define ST_PRESS_CELSIUS_NANO_SCALE            (1000000000UL / \
-                                                ST_PRESS_LSB_PER_CELSIUS)
+#define ST_PRESS_MILLI_CELSIUS_OFFSET          42500UL
+
 #define ST_PRESS_NUMBER_DATA_CHANNELS          1
 
 /* FULLSCALE */
+#define ST_PRESS_FS_AVL_1100MB                 1100
 #define ST_PRESS_FS_AVL_1260MB                 1260
 
 #define ST_PRESS_1_OUT_XL_ADDR                 0x28
@@ -54,9 +60,6 @@
 #define ST_PRESS_LPS331AP_PW_MASK              0x80
 #define ST_PRESS_LPS331AP_FS_ADDR              0x23
 #define ST_PRESS_LPS331AP_FS_MASK              0x30
-#define ST_PRESS_LPS331AP_FS_AVL_1260_VAL      0x00
-#define ST_PRESS_LPS331AP_FS_AVL_1260_GAIN     ST_PRESS_KPASCAL_NANO_SCALE
-#define ST_PRESS_LPS331AP_FS_AVL_TEMP_GAIN     ST_PRESS_CELSIUS_NANO_SCALE
 #define ST_PRESS_LPS331AP_BDU_ADDR             0x20
 #define ST_PRESS_LPS331AP_BDU_MASK             0x04
 #define ST_PRESS_LPS331AP_DRDY_IRQ_ADDR                0x22
 #define ST_PRESS_LPS331AP_OD_IRQ_ADDR          0x22
 #define ST_PRESS_LPS331AP_OD_IRQ_MASK          0x40
 #define ST_PRESS_LPS331AP_MULTIREAD_BIT                true
-#define ST_PRESS_LPS331AP_TEMP_OFFSET          42500
 
 /* CUSTOM VALUES FOR LPS001WP SENSOR */
+
+/* LPS001WP pressure resolution */
+#define ST_PRESS_LPS001WP_LSB_PER_MBAR         16UL
+/* LPS001WP temperature resolution */
+#define ST_PRESS_LPS001WP_LSB_PER_CELSIUS      64UL
+
 #define ST_PRESS_LPS001WP_WAI_EXP              0xba
 #define ST_PRESS_LPS001WP_ODR_ADDR             0x20
 #define ST_PRESS_LPS001WP_ODR_MASK             0x30
@@ -78,6 +86,8 @@
 #define ST_PRESS_LPS001WP_ODR_AVL_13HZ_VAL     0x03
 #define ST_PRESS_LPS001WP_PW_ADDR              0x20
 #define ST_PRESS_LPS001WP_PW_MASK              0x40
+#define ST_PRESS_LPS001WP_FS_AVL_PRESS_GAIN \
+       (100000000UL / ST_PRESS_LPS001WP_LSB_PER_MBAR)
 #define ST_PRESS_LPS001WP_BDU_ADDR             0x20
 #define ST_PRESS_LPS001WP_BDU_MASK             0x04
 #define ST_PRESS_LPS001WP_MULTIREAD_BIT                true
 #define ST_PRESS_LPS25H_ODR_AVL_25HZ_VAL       0x04
 #define ST_PRESS_LPS25H_PW_ADDR                        0x20
 #define ST_PRESS_LPS25H_PW_MASK                        0x80
-#define ST_PRESS_LPS25H_FS_ADDR                        0x00
-#define ST_PRESS_LPS25H_FS_MASK                        0x00
-#define ST_PRESS_LPS25H_FS_AVL_1260_VAL                0x00
-#define ST_PRESS_LPS25H_FS_AVL_1260_GAIN       ST_PRESS_KPASCAL_NANO_SCALE
-#define ST_PRESS_LPS25H_FS_AVL_TEMP_GAIN       ST_PRESS_CELSIUS_NANO_SCALE
 #define ST_PRESS_LPS25H_BDU_ADDR               0x20
 #define ST_PRESS_LPS25H_BDU_MASK               0x04
 #define ST_PRESS_LPS25H_DRDY_IRQ_ADDR          0x23
 #define ST_PRESS_LPS25H_OD_IRQ_ADDR            0x22
 #define ST_PRESS_LPS25H_OD_IRQ_MASK            0x40
 #define ST_PRESS_LPS25H_MULTIREAD_BIT          true
-#define ST_PRESS_LPS25H_TEMP_OFFSET            42500
 #define ST_PRESS_LPS25H_OUT_XL_ADDR            0x28
 #define ST_TEMP_LPS25H_OUT_L_ADDR              0x2b
 
@@ -161,7 +165,9 @@ static const struct iio_chan_spec st_press_lps001wp_channels[] = {
                        .storagebits = 16,
                        .endianness = IIO_LE,
                },
-               .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+               .info_mask_separate =
+                       BIT(IIO_CHAN_INFO_RAW) |
+                       BIT(IIO_CHAN_INFO_SCALE),
                .modified = 0,
        },
        {
@@ -177,7 +183,7 @@ static const struct iio_chan_spec st_press_lps001wp_channels[] = {
                },
                .info_mask_separate =
                        BIT(IIO_CHAN_INFO_RAW) |
-                       BIT(IIO_CHAN_INFO_OFFSET),
+                       BIT(IIO_CHAN_INFO_SCALE),
                .modified = 0,
        },
        IIO_CHAN_SOFT_TIMESTAMP(1)
@@ -212,11 +218,14 @@ static const struct st_sensor_settings st_press_sensors_settings[] = {
                        .addr = ST_PRESS_LPS331AP_FS_ADDR,
                        .mask = ST_PRESS_LPS331AP_FS_MASK,
                        .fs_avl = {
+                               /*
+                                * Pressure and temperature sensitivity values
+                                * as defined in table 3 of LPS331AP datasheet.
+                                */
                                [0] = {
                                        .num = ST_PRESS_FS_AVL_1260MB,
-                                       .value = ST_PRESS_LPS331AP_FS_AVL_1260_VAL,
-                                       .gain = ST_PRESS_LPS331AP_FS_AVL_1260_GAIN,
-                                       .gain2 = ST_PRESS_LPS331AP_FS_AVL_TEMP_GAIN,
+                                       .gain = ST_PRESS_KPASCAL_NANO_SCALE,
+                                       .gain2 = ST_PRESS_LSB_PER_CELSIUS,
                                },
                        },
                },
@@ -261,7 +270,17 @@ static const struct st_sensor_settings st_press_sensors_settings[] = {
                        .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
                },
                .fs = {
-                       .addr = 0,
+                       .fs_avl = {
+                               /*
+                                * Pressure and temperature resolution values
+                                * as defined in table 3 of LPS001WP datasheet.
+                                */
+                               [0] = {
+                                       .num = ST_PRESS_FS_AVL_1100MB,
+                                       .gain = ST_PRESS_LPS001WP_FS_AVL_PRESS_GAIN,
+                                       .gain2 = ST_PRESS_LPS001WP_LSB_PER_CELSIUS,
+                               },
+                       },
                },
                .bdu = {
                        .addr = ST_PRESS_LPS001WP_BDU_ADDR,
@@ -298,14 +317,15 @@ static const struct st_sensor_settings st_press_sensors_settings[] = {
                        .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
                },
                .fs = {
-                       .addr = ST_PRESS_LPS25H_FS_ADDR,
-                       .mask = ST_PRESS_LPS25H_FS_MASK,
                        .fs_avl = {
+                               /*
+                                * Pressure and temperature sensitivity values
+                                * as defined in table 3 of LPS25H datasheet.
+                                */
                                [0] = {
                                        .num = ST_PRESS_FS_AVL_1260MB,
-                                       .value = ST_PRESS_LPS25H_FS_AVL_1260_VAL,
-                                       .gain = ST_PRESS_LPS25H_FS_AVL_1260_GAIN,
-                                       .gain2 = ST_PRESS_LPS25H_FS_AVL_TEMP_GAIN,
+                                       .gain = ST_PRESS_KPASCAL_NANO_SCALE,
+                                       .gain2 = ST_PRESS_LSB_PER_CELSIUS,
                                },
                        },
                },
@@ -364,26 +384,26 @@ static int st_press_read_raw(struct iio_dev *indio_dev,
 
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_SCALE:
-               *val = 0;
-
                switch (ch->type) {
                case IIO_PRESSURE:
+                       *val = 0;
                        *val2 = press_data->current_fullscale->gain;
-                       break;
+                       return IIO_VAL_INT_PLUS_NANO;
                case IIO_TEMP:
+                       *val = MCELSIUS_PER_CELSIUS;
                        *val2 = press_data->current_fullscale->gain2;
-                       break;
+                       return IIO_VAL_FRACTIONAL;
                default:
                        err = -EINVAL;
                        goto read_error;
                }
 
-               return IIO_VAL_INT_PLUS_NANO;
        case IIO_CHAN_INFO_OFFSET:
                switch (ch->type) {
                case IIO_TEMP:
-                       *val = 425;
-                       *val2 = 10;
+                       *val = ST_PRESS_MILLI_CELSIUS_OFFSET *
+                              press_data->current_fullscale->gain2;
+                       *val2 = MCELSIUS_PER_CELSIUS;
                        break;
                default:
                        err = -EINVAL;
@@ -425,6 +445,7 @@ static const struct iio_info press_info = {
 static const struct iio_trigger_ops st_press_trigger_ops = {
        .owner = THIS_MODULE,
        .set_trigger_state = ST_PRESS_TRIGGER_SET_STATE,
+       .validate_device = st_sensors_validate_device,
 };
 #define ST_PRESS_TRIGGER_OPS (&st_press_trigger_ops)
 #else
index f4d29d5..e2f926c 100644 (file)
@@ -64,6 +64,7 @@ struct as3935_state {
        struct delayed_work work;
 
        u32 tune_cap;
+       u8 buffer[16]; /* 8-bit data + 56-bit padding + 64-bit timestamp */
        u8 buf[2] ____cacheline_aligned;
 };
 
@@ -72,7 +73,8 @@ static const struct iio_chan_spec as3935_channels[] = {
                .type           = IIO_PROXIMITY,
                .info_mask_separate =
                        BIT(IIO_CHAN_INFO_RAW) |
-                       BIT(IIO_CHAN_INFO_PROCESSED),
+                       BIT(IIO_CHAN_INFO_PROCESSED) |
+                       BIT(IIO_CHAN_INFO_SCALE),
                .scan_index     = 0,
                .scan_type = {
                        .sign           = 'u',
@@ -181,7 +183,12 @@ static int as3935_read_raw(struct iio_dev *indio_dev,
                /* storm out of range */
                if (*val == AS3935_DATA_MASK)
                        return -EINVAL;
-               *val *= 1000;
+
+               if (m == IIO_CHAN_INFO_PROCESSED)
+                       *val *= 1000;
+               break;
+       case IIO_CHAN_INFO_SCALE:
+               *val = 1000;
                break;
        default:
                return -EINVAL;
@@ -206,10 +213,10 @@ static irqreturn_t as3935_trigger_handler(int irq, void *private)
        ret = as3935_read(st, AS3935_DATA, &val);
        if (ret)
                goto err_read;
-       val &= AS3935_DATA_MASK;
-       val *= 1000;
 
-       iio_push_to_buffers_with_timestamp(indio_dev, &val, pf->timestamp);
+       st->buffer[0] = val & AS3935_DATA_MASK;
+       iio_push_to_buffers_with_timestamp(indio_dev, &st->buffer,
+                                          pf->timestamp);
 err_read:
        iio_trigger_notify_done(indio_dev->trig);
 
index c2e257d..1a2984c 100644 (file)
@@ -178,6 +178,7 @@ static int write_gid(struct ib_device *ib_dev, u8 port,
 {
        int ret = 0;
        struct net_device *old_net_dev;
+       enum ib_gid_type old_gid_type;
 
        /* in rdma_cap_roce_gid_table, this funciton should be protected by a
         * sleep-able lock.
@@ -199,6 +200,7 @@ static int write_gid(struct ib_device *ib_dev, u8 port,
        }
 
        old_net_dev = table->data_vec[ix].attr.ndev;
+       old_gid_type = table->data_vec[ix].attr.gid_type;
        if (old_net_dev && old_net_dev != attr->ndev)
                dev_put(old_net_dev);
        /* if modify_gid failed, just delete the old gid */
@@ -207,10 +209,14 @@ static int write_gid(struct ib_device *ib_dev, u8 port,
                attr = &zattr;
                table->data_vec[ix].context = NULL;
        }
-       if (default_gid)
-               table->data_vec[ix].props |= GID_TABLE_ENTRY_DEFAULT;
+
        memcpy(&table->data_vec[ix].gid, gid, sizeof(*gid));
        memcpy(&table->data_vec[ix].attr, attr, sizeof(*attr));
+       if (default_gid) {
+               table->data_vec[ix].props |= GID_TABLE_ENTRY_DEFAULT;
+               if (action == GID_TABLE_WRITE_ACTION_DEL)
+                       table->data_vec[ix].attr.gid_type = old_gid_type;
+       }
        if (table->data_vec[ix].attr.ndev &&
            table->data_vec[ix].attr.ndev != old_net_dev)
                dev_hold(table->data_vec[ix].attr.ndev);
@@ -405,7 +411,9 @@ int ib_cache_gid_del_all_netdev_gids(struct ib_device *ib_dev, u8 port,
 
        for (ix = 0; ix < table->sz; ix++)
                if (table->data_vec[ix].attr.ndev == ndev)
-                       if (!del_gid(ib_dev, port, table, ix, false))
+                       if (!del_gid(ib_dev, port, table, ix,
+                                    !!(table->data_vec[ix].props &
+                                       GID_TABLE_ENTRY_DEFAULT)))
                                deleted = true;
 
        write_unlock_irq(&table->rwlock);
index 1d92e09..c995255 100644 (file)
@@ -3452,14 +3452,14 @@ static int cm_establish(struct ib_cm_id *cm_id)
        work->cm_event.event = IB_CM_USER_ESTABLISHED;
 
        /* Check if the device started its remove_one */
-       spin_lock_irq(&cm.lock);
+       spin_lock_irqsave(&cm.lock, flags);
        if (!cm_dev->going_down) {
                queue_delayed_work(cm.wq, &work->work, 0);
        } else {
                kfree(work);
                ret = -ENODEV;
        }
-       spin_unlock_irq(&cm.lock);
+       spin_unlock_irqrestore(&cm.lock, flags);
 
 out:
        return ret;
index f0c91ba..ad1b1ad 100644 (file)
@@ -708,17 +708,6 @@ static void cma_deref_id(struct rdma_id_private *id_priv)
                complete(&id_priv->comp);
 }
 
-static int cma_disable_callback(struct rdma_id_private *id_priv,
-                               enum rdma_cm_state state)
-{
-       mutex_lock(&id_priv->handler_mutex);
-       if (id_priv->state != state) {
-               mutex_unlock(&id_priv->handler_mutex);
-               return -EINVAL;
-       }
-       return 0;
-}
-
 struct rdma_cm_id *rdma_create_id(struct net *net,
                                  rdma_cm_event_handler event_handler,
                                  void *context, enum rdma_port_space ps,
@@ -1671,11 +1660,12 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
        struct rdma_cm_event event;
        int ret = 0;
 
+       mutex_lock(&id_priv->handler_mutex);
        if ((ib_event->event != IB_CM_TIMEWAIT_EXIT &&
-               cma_disable_callback(id_priv, RDMA_CM_CONNECT)) ||
+            id_priv->state != RDMA_CM_CONNECT) ||
            (ib_event->event == IB_CM_TIMEWAIT_EXIT &&
-               cma_disable_callback(id_priv, RDMA_CM_DISCONNECT)))
-               return 0;
+            id_priv->state != RDMA_CM_DISCONNECT))
+               goto out;
 
        memset(&event, 0, sizeof event);
        switch (ib_event->event) {
@@ -1870,7 +1860,7 @@ static int cma_check_req_qp_type(struct rdma_cm_id *id, struct ib_cm_event *ib_e
 
 static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
 {
-       struct rdma_id_private *listen_id, *conn_id;
+       struct rdma_id_private *listen_id, *conn_id = NULL;
        struct rdma_cm_event event;
        struct net_device *net_dev;
        int offset, ret;
@@ -1884,9 +1874,10 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
                goto net_dev_put;
        }
 
-       if (cma_disable_callback(listen_id, RDMA_CM_LISTEN)) {
+       mutex_lock(&listen_id->handler_mutex);
+       if (listen_id->state != RDMA_CM_LISTEN) {
                ret = -ECONNABORTED;
-               goto net_dev_put;
+               goto err1;
        }
 
        memset(&event, 0, sizeof event);
@@ -1976,8 +1967,9 @@ static int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event)
        struct sockaddr *laddr = (struct sockaddr *)&iw_event->local_addr;
        struct sockaddr *raddr = (struct sockaddr *)&iw_event->remote_addr;
 
-       if (cma_disable_callback(id_priv, RDMA_CM_CONNECT))
-               return 0;
+       mutex_lock(&id_priv->handler_mutex);
+       if (id_priv->state != RDMA_CM_CONNECT)
+               goto out;
 
        memset(&event, 0, sizeof event);
        switch (iw_event->event) {
@@ -2029,6 +2021,7 @@ static int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event)
                return ret;
        }
 
+out:
        mutex_unlock(&id_priv->handler_mutex);
        return ret;
 }
@@ -2039,13 +2032,15 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
        struct rdma_cm_id *new_cm_id;
        struct rdma_id_private *listen_id, *conn_id;
        struct rdma_cm_event event;
-       int ret;
+       int ret = -ECONNABORTED;
        struct sockaddr *laddr = (struct sockaddr *)&iw_event->local_addr;
        struct sockaddr *raddr = (struct sockaddr *)&iw_event->remote_addr;
 
        listen_id = cm_id->context;
-       if (cma_disable_callback(listen_id, RDMA_CM_LISTEN))
-               return -ECONNABORTED;
+
+       mutex_lock(&listen_id->handler_mutex);
+       if (listen_id->state != RDMA_CM_LISTEN)
+               goto out;
 
        /* Create a new RDMA id for the new IW CM ID */
        new_cm_id = rdma_create_id(listen_id->id.route.addr.dev_addr.net,
@@ -3216,8 +3211,9 @@ static int cma_sidr_rep_handler(struct ib_cm_id *cm_id,
        struct ib_cm_sidr_rep_event_param *rep = &ib_event->param.sidr_rep_rcvd;
        int ret = 0;
 
-       if (cma_disable_callback(id_priv, RDMA_CM_CONNECT))
-               return 0;
+       mutex_lock(&id_priv->handler_mutex);
+       if (id_priv->state != RDMA_CM_CONNECT)
+               goto out;
 
        memset(&event, 0, sizeof event);
        switch (ib_event->event) {
@@ -3673,12 +3669,13 @@ static int cma_ib_mc_handler(int status, struct ib_sa_multicast *multicast)
        struct rdma_id_private *id_priv;
        struct cma_multicast *mc = multicast->context;
        struct rdma_cm_event event;
-       int ret;
+       int ret = 0;
 
        id_priv = mc->id_priv;
-       if (cma_disable_callback(id_priv, RDMA_CM_ADDR_BOUND) &&
-           cma_disable_callback(id_priv, RDMA_CM_ADDR_RESOLVED))
-               return 0;
+       mutex_lock(&id_priv->handler_mutex);
+       if (id_priv->state != RDMA_CM_ADDR_BOUND &&
+           id_priv->state != RDMA_CM_ADDR_RESOLVED)
+               goto out;
 
        if (!status)
                status = cma_set_qkey(id_priv, be32_to_cpu(multicast->rec.qkey));
@@ -3720,6 +3717,7 @@ static int cma_ib_mc_handler(int status, struct ib_sa_multicast *multicast)
                return 0;
        }
 
+out:
        mutex_unlock(&id_priv->handler_mutex);
        return 0;
 }
@@ -3878,12 +3876,12 @@ static int cma_iboe_join_multicast(struct rdma_id_private *id_priv,
        gid_type = id_priv->cma_dev->default_gid_type[id_priv->id.port_num -
                   rdma_start_port(id_priv->cma_dev->device)];
        if (addr->sa_family == AF_INET) {
-               if (gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP)
+               if (gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP) {
+                       mc->multicast.ib->rec.hop_limit = IPV6_DEFAULT_HOPLIMIT;
                        err = cma_igmp_send(ndev, &mc->multicast.ib->rec.mgid,
                                            true);
-               if (!err) {
-                       mc->igmp_joined = true;
-                       mc->multicast.ib->rec.hop_limit = IPV6_DEFAULT_HOPLIMIT;
+                       if (!err)
+                               mc->igmp_joined = true;
                }
        } else {
                if (gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP)
index 5516fb0..5c155fa 100644 (file)
@@ -661,6 +661,9 @@ int ib_query_port(struct ib_device *device,
        if (err || port_attr->subnet_prefix)
                return err;
 
+       if (rdma_port_get_link_layer(device, port_num) != IB_LINK_LAYER_INFINIBAND)
+               return 0;
+
        err = ib_query_gid(device, port_num, 0, &gid, NULL);
        if (err)
                return err;
@@ -1024,7 +1027,8 @@ static int __init ib_core_init(void)
                goto err_mad;
        }
 
-       if (ib_add_ibnl_clients()) {
+       ret = ib_add_ibnl_clients();
+       if (ret) {
                pr_warn("Couldn't register ibnl clients\n");
                goto err_sa;
        }
index 43e3fa2..1c41b95 100644 (file)
@@ -506,7 +506,7 @@ int iwpm_add_and_query_mapping_cb(struct sk_buff *skb,
        if (!nlmsg_request) {
                pr_info("%s: Could not find a matching request (seq = %u)\n",
                                 __func__, msg_seq);
-                       return -EINVAL;
+               return -EINVAL;
        }
        pm_msg = nlmsg_request->req_buffer;
        local_sockaddr = (struct sockaddr_storage *)
index 82fb511..2d49228 100644 (file)
@@ -1638,9 +1638,9 @@ static void remove_mad_reg_req(struct ib_mad_agent_private *agent_priv)
                /* Now, check to see if there are any methods still in use */
                if (!check_method_table(method)) {
                        /* If not, release management method table */
-                        kfree(method);
-                        class->method_table[mgmt_class] = NULL;
-                        /* Any management classes left ? */
+                       kfree(method);
+                       class->method_table[mgmt_class] = NULL;
+                       /* Any management classes left ? */
                        if (!check_class_table(class)) {
                                /* If not, release management class table */
                                kfree(class);
index 5e573bb..a5793c8 100644 (file)
@@ -889,9 +889,9 @@ static struct attribute *alloc_hsa_lifespan(char *name, u8 port_num)
 static void setup_hw_stats(struct ib_device *device, struct ib_port *port,
                           u8 port_num)
 {
-       struct attribute_group *hsag = NULL;
+       struct attribute_group *hsag;
        struct rdma_hw_stats *stats;
-       int i = 0, ret;
+       int i, ret;
 
        stats = device->alloc_hw_stats(device, port_num);
 
@@ -899,19 +899,22 @@ static void setup_hw_stats(struct ib_device *device, struct ib_port *port,
                return;
 
        if (!stats->names || stats->num_counters <= 0)
-               goto err;
+               goto err_free_stats;
 
+       /*
+        * Two extra attribue elements here, one for the lifespan entry and
+        * one to NULL terminate the list for the sysfs core code
+        */
        hsag = kzalloc(sizeof(*hsag) +
-                      // 1 extra for the lifespan config entry
-                      sizeof(void *) * (stats->num_counters + 1),
+                      sizeof(void *) * (stats->num_counters + 2),
                       GFP_KERNEL);
        if (!hsag)
-               return;
+               goto err_free_stats;
 
        ret = device->get_hw_stats(device, stats, port_num,
                                   stats->num_counters);
        if (ret != stats->num_counters)
-               goto err;
+               goto err_free_hsag;
 
        stats->timestamp = jiffies;
 
@@ -922,10 +925,13 @@ static void setup_hw_stats(struct ib_device *device, struct ib_port *port,
                hsag->attrs[i] = alloc_hsa(i, port_num, stats->names[i]);
                if (!hsag->attrs[i])
                        goto err;
+               sysfs_attr_init(hsag->attrs[i]);
        }
 
        /* treat an error here as non-fatal */
        hsag->attrs[i] = alloc_hsa_lifespan("lifespan", port_num);
+       if (hsag->attrs[i])
+               sysfs_attr_init(hsag->attrs[i]);
 
        if (port) {
                struct kobject *kobj = &port->kobj;
@@ -946,10 +952,12 @@ static void setup_hw_stats(struct ib_device *device, struct ib_port *port,
        return;
 
 err:
-       kfree(stats);
        for (; i >= 0; i--)
                kfree(hsag->attrs[i]);
+err_free_hsag:
        kfree(hsag);
+err_free_stats:
+       kfree(stats);
        return;
 }
 
index 1a8babb..825021d 100644 (file)
@@ -1747,7 +1747,7 @@ static int create_qp(struct ib_uverbs_file *file,
        struct ib_srq                   *srq = NULL;
        struct ib_qp                    *qp;
        char                            *buf;
-       struct ib_qp_init_attr          attr;
+       struct ib_qp_init_attr          attr = {};
        struct ib_uverbs_ex_create_qp_resp resp;
        int                             ret;
 
index 1d7d4cf..6298f54 100644 (file)
@@ -511,12 +511,16 @@ int ib_init_ah_from_wc(struct ib_device *device, u8 port_num,
                ah_attr->grh.dgid = sgid;
 
                if (!rdma_cap_eth_ah(device, port_num)) {
-                       ret = ib_find_cached_gid_by_port(device, &dgid,
-                                                        IB_GID_TYPE_IB,
-                                                        port_num, NULL,
-                                                        &gid_index);
-                       if (ret)
-                               return ret;
+                       if (dgid.global.interface_id != cpu_to_be64(IB_SA_WELL_KNOWN_GUID)) {
+                               ret = ib_find_cached_gid_by_port(device, &dgid,
+                                                                IB_GID_TYPE_IB,
+                                                                port_num, NULL,
+                                                                &gid_index);
+                               if (ret)
+                                       return ret;
+                       } else {
+                               gid_index = 0;
+                       }
                }
 
                ah_attr->grh.sgid_index = (u8) gid_index;
index 6e7050a..14d7eeb 100644 (file)
@@ -300,16 +300,15 @@ int hfi1_get_proc_affinity(struct hfi1_devdata *dd, int node)
        const struct cpumask *node_mask,
                *proc_mask = tsk_cpus_allowed(current);
        struct cpu_mask_set *set = &dd->affinity->proc;
-       char buf[1024];
 
        /*
         * check whether process/context affinity has already
         * been set
         */
        if (cpumask_weight(proc_mask) == 1) {
-               scnprintf(buf, 1024, "%*pbl", cpumask_pr_args(proc_mask));
-               hfi1_cdbg(PROC, "PID %u %s affinity set to CPU %s",
-                         current->pid, current->comm, buf);
+               hfi1_cdbg(PROC, "PID %u %s affinity set to CPU %*pbl",
+                         current->pid, current->comm,
+                         cpumask_pr_args(proc_mask));
                /*
                 * Mark the pre-set CPU as used. This is atomic so we don't
                 * need the lock
@@ -318,9 +317,9 @@ int hfi1_get_proc_affinity(struct hfi1_devdata *dd, int node)
                cpumask_set_cpu(cpu, &set->used);
                goto done;
        } else if (cpumask_weight(proc_mask) < cpumask_weight(&set->mask)) {
-               scnprintf(buf, 1024, "%*pbl", cpumask_pr_args(proc_mask));
-               hfi1_cdbg(PROC, "PID %u %s affinity set to CPU set(s) %s",
-                         current->pid, current->comm, buf);
+               hfi1_cdbg(PROC, "PID %u %s affinity set to CPU set(s) %*pbl",
+                         current->pid, current->comm,
+                         cpumask_pr_args(proc_mask));
                goto done;
        }
 
@@ -356,8 +355,8 @@ int hfi1_get_proc_affinity(struct hfi1_devdata *dd, int node)
        cpumask_or(intrs, intrs, (dd->affinity->rcv_intr.gen ?
                                  &dd->affinity->rcv_intr.mask :
                                  &dd->affinity->rcv_intr.used));
-       scnprintf(buf, 1024, "%*pbl", cpumask_pr_args(intrs));
-       hfi1_cdbg(PROC, "CPUs used by interrupts: %s", buf);
+       hfi1_cdbg(PROC, "CPUs used by interrupts: %*pbl",
+                 cpumask_pr_args(intrs));
 
        /*
         * If we don't have a NUMA node requested, preference is towards
@@ -366,18 +365,16 @@ int hfi1_get_proc_affinity(struct hfi1_devdata *dd, int node)
        if (node == -1)
                node = dd->node;
        node_mask = cpumask_of_node(node);
-       scnprintf(buf, 1024, "%*pbl", cpumask_pr_args(node_mask));
-       hfi1_cdbg(PROC, "device on NUMA %u, CPUs %s", node, buf);
+       hfi1_cdbg(PROC, "device on NUMA %u, CPUs %*pbl", node,
+                 cpumask_pr_args(node_mask));
 
        /* diff will hold all unused cpus */
        cpumask_andnot(diff, &set->mask, &set->used);
-       scnprintf(buf, 1024, "%*pbl", cpumask_pr_args(diff));
-       hfi1_cdbg(PROC, "unused CPUs (all) %s", buf);
+       hfi1_cdbg(PROC, "unused CPUs (all) %*pbl", cpumask_pr_args(diff));
 
        /* get cpumask of available CPUs on preferred NUMA */
        cpumask_and(mask, diff, node_mask);
-       scnprintf(buf, 1024, "%*pbl", cpumask_pr_args(mask));
-       hfi1_cdbg(PROC, "available cpus on NUMA %s", buf);
+       hfi1_cdbg(PROC, "available cpus on NUMA %*pbl", cpumask_pr_args(mask));
 
        /*
         * At first, we don't want to place processes on the same
@@ -395,8 +392,8 @@ int hfi1_get_proc_affinity(struct hfi1_devdata *dd, int node)
                cpumask_andnot(diff, &set->mask, &set->used);
                cpumask_andnot(mask, diff, node_mask);
        }
-       scnprintf(buf, 1024, "%*pbl", cpumask_pr_args(mask));
-       hfi1_cdbg(PROC, "possible CPUs for process %s", buf);
+       hfi1_cdbg(PROC, "possible CPUs for process %*pbl",
+                 cpumask_pr_args(mask));
 
        cpu = cpumask_first(mask);
        if (cpu >= nr_cpu_ids) /* empty */
index 3b876da..f5de851 100644 (file)
@@ -1037,7 +1037,7 @@ static void dc_shutdown(struct hfi1_devdata *);
 static void dc_start(struct hfi1_devdata *);
 static int qos_rmt_entries(struct hfi1_devdata *dd, unsigned int *mp,
                           unsigned int *np);
-static void remove_full_mgmt_pkey(struct hfi1_pportdata *ppd);
+static void clear_full_mgmt_pkey(struct hfi1_pportdata *ppd);
 
 /*
  * Error interrupt table entry.  This is used as input to the interrupt
@@ -6962,8 +6962,6 @@ void handle_link_down(struct work_struct *work)
        }
 
        reset_neighbor_info(ppd);
-       if (ppd->mgmt_allowed)
-               remove_full_mgmt_pkey(ppd);
 
        /* disable the port */
        clear_rcvctrl(ppd->dd, RCV_CTRL_RCV_PORT_ENABLE_SMASK);
@@ -7070,12 +7068,16 @@ static void add_full_mgmt_pkey(struct hfi1_pportdata *ppd)
                            __func__, ppd->pkeys[2], FULL_MGMT_P_KEY);
        ppd->pkeys[2] = FULL_MGMT_P_KEY;
        (void)hfi1_set_ib_cfg(ppd, HFI1_IB_CFG_PKEYS, 0);
+       hfi1_event_pkey_change(ppd->dd, ppd->port);
 }
 
-static void remove_full_mgmt_pkey(struct hfi1_pportdata *ppd)
+static void clear_full_mgmt_pkey(struct hfi1_pportdata *ppd)
 {
-       ppd->pkeys[2] = 0;
-       (void)hfi1_set_ib_cfg(ppd, HFI1_IB_CFG_PKEYS, 0);
+       if (ppd->pkeys[2] != 0) {
+               ppd->pkeys[2] = 0;
+               (void)hfi1_set_ib_cfg(ppd, HFI1_IB_CFG_PKEYS, 0);
+               hfi1_event_pkey_change(ppd->dd, ppd->port);
+       }
 }
 
 /*
@@ -7832,8 +7834,8 @@ static void handle_dcc_err(struct hfi1_devdata *dd, u32 unused, u64 reg)
                         * save first 2 flits in the packet that caused
                         * the error
                         */
-                        dd->err_info_rcvport.packet_flit1 = hdr0;
-                        dd->err_info_rcvport.packet_flit2 = hdr1;
+                       dd->err_info_rcvport.packet_flit1 = hdr0;
+                       dd->err_info_rcvport.packet_flit2 = hdr1;
                }
                switch (info) {
                case 1:
@@ -9168,6 +9170,13 @@ int start_link(struct hfi1_pportdata *ppd)
                return 0;
        }
 
+       /*
+        * FULL_MGMT_P_KEY is cleared from the pkey table, so that the
+        * pkey table can be configured properly if the HFI unit is connected
+        * to switch port with MgmtAllowed=NO
+        */
+       clear_full_mgmt_pkey(ppd);
+
        return set_link_state(ppd, HLS_DN_POLL);
 }
 
@@ -9777,7 +9786,7 @@ static void set_send_length(struct hfi1_pportdata *ppd)
        u64 len1 = 0, len2 = (((dd->vld[15].mtu + max_hb) >> 2)
                              & SEND_LEN_CHECK1_LEN_VL15_MASK) <<
                SEND_LEN_CHECK1_LEN_VL15_SHIFT;
-       int i;
+       int i, j;
        u32 thres;
 
        for (i = 0; i < ppd->vls_supported; i++) {
@@ -9801,7 +9810,10 @@ static void set_send_length(struct hfi1_pportdata *ppd)
                            sc_mtu_to_threshold(dd->vld[i].sc,
                                                dd->vld[i].mtu,
                                                dd->rcd[0]->rcvhdrqentsize));
-               sc_set_cr_threshold(dd->vld[i].sc, thres);
+               for (j = 0; j < INIT_SC_PER_VL; j++)
+                       sc_set_cr_threshold(
+                                       pio_select_send_context_vl(dd, j, i),
+                                           thres);
        }
        thres = min(sc_percent_to_threshold(dd->vld[15].sc, 50),
                    sc_mtu_to_threshold(dd->vld[15].sc,
@@ -11906,7 +11918,7 @@ static void update_synth_timer(unsigned long opaque)
                hfi1_cdbg(CNTR, "[%d] No update necessary", dd->unit);
        }
 
-mod_timer(&dd->synth_stats_timer, jiffies + HZ * SYNTH_CNT_TIME);
+       mod_timer(&dd->synth_stats_timer, jiffies + HZ * SYNTH_CNT_TIME);
 }
 
 #define C_MAX_NAME 13 /* 12 chars + one for /0 */
index 7a5b0e6..c702a00 100644 (file)
@@ -203,6 +203,9 @@ static long hfi1_file_ioctl(struct file *fp, unsigned int cmd,
 
        switch (cmd) {
        case HFI1_IOCTL_ASSIGN_CTXT:
+               if (uctxt)
+                       return -EINVAL;
+
                if (copy_from_user(&uinfo,
                                   (struct hfi1_user_info __user *)arg,
                                   sizeof(uinfo)))
index 5cc492e..eed971c 100644 (file)
@@ -1337,7 +1337,7 @@ static void cleanup_device_data(struct hfi1_devdata *dd)
                dma_free_coherent(&dd->pcidev->dev, sizeof(u64),
                                  (void *)dd->rcvhdrtail_dummy_kvaddr,
                                  dd->rcvhdrtail_dummy_physaddr);
-                                 dd->rcvhdrtail_dummy_kvaddr = NULL;
+               dd->rcvhdrtail_dummy_kvaddr = NULL;
        }
 
        for (ctxt = 0; tmp && ctxt < dd->num_rcv_contexts; ctxt++) {
@@ -1383,7 +1383,7 @@ static void postinit_cleanup(struct hfi1_devdata *dd)
 static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        int ret = 0, j, pidx, initfail;
-       struct hfi1_devdata *dd = NULL;
+       struct hfi1_devdata *dd = ERR_PTR(-EINVAL);
        struct hfi1_pportdata *ppd;
 
        /* First, lock the non-writable module parameters */
index 2190295..fca07a1 100644 (file)
@@ -78,6 +78,16 @@ static inline void clear_opa_smp_data(struct opa_smp *smp)
        memset(data, 0, size);
 }
 
+void hfi1_event_pkey_change(struct hfi1_devdata *dd, u8 port)
+{
+       struct ib_event event;
+
+       event.event = IB_EVENT_PKEY_CHANGE;
+       event.device = &dd->verbs_dev.rdi.ibdev;
+       event.element.port_num = port;
+       ib_dispatch_event(&event);
+}
+
 static void send_trap(struct hfi1_ibport *ibp, void *data, unsigned len)
 {
        struct ib_mad_send_buf *send_buf;
@@ -1418,15 +1428,10 @@ static int set_pkeys(struct hfi1_devdata *dd, u8 port, u16 *pkeys)
        }
 
        if (changed) {
-               struct ib_event event;
-
                (void)hfi1_set_ib_cfg(ppd, HFI1_IB_CFG_PKEYS, 0);
-
-               event.event = IB_EVENT_PKEY_CHANGE;
-               event.device = &dd->verbs_dev.rdi.ibdev;
-               event.element.port_num = port;
-               ib_dispatch_event(&event);
+               hfi1_event_pkey_change(dd, port);
        }
+
        return 0;
 }
 
index 55ee086..8b734aa 100644 (file)
@@ -434,4 +434,6 @@ struct sc2vlnt {
                    COUNTER_MASK(1, 3) | \
                    COUNTER_MASK(1, 4))
 
+void hfi1_event_pkey_change(struct hfi1_devdata *dd, u8 port);
+
 #endif                         /* _HFI1_MAD_H */
index d5edb1a..d402245 100644 (file)
@@ -995,7 +995,7 @@ static void sc_wait_for_packet_egress(struct send_context *sc, int pause)
                /* counter is reset if occupancy count changes */
                if (reg != reg_prev)
                        loop = 0;
-               if (loop > 500) {
+               if (loop > 50000) {
                        /* timed out - bounce the link */
                        dd_dev_err(dd,
                                   "%s: context %u(%u) timeout waiting for packets to egress, remaining count %u, bouncing link\n",
@@ -1797,6 +1797,21 @@ static void pio_map_rcu_callback(struct rcu_head *list)
        pio_map_free(m);
 }
 
+/*
+ * Set credit return threshold for the kernel send context
+ */
+static void set_threshold(struct hfi1_devdata *dd, int scontext, int i)
+{
+       u32 thres;
+
+       thres = min(sc_percent_to_threshold(dd->kernel_send_context[scontext],
+                                           50),
+                   sc_mtu_to_threshold(dd->kernel_send_context[scontext],
+                                       dd->vld[i].mtu,
+                                       dd->rcd[0]->rcvhdrqentsize));
+       sc_set_cr_threshold(dd->kernel_send_context[scontext], thres);
+}
+
 /*
  * pio_map_init - called when #vls change
  * @dd: hfi1_devdata
@@ -1872,11 +1887,16 @@ int pio_map_init(struct hfi1_devdata *dd, u8 port, u8 num_vls, u8 *vl_scontexts)
                        if (!newmap->map[i])
                                goto bail;
                        newmap->map[i]->mask = (1 << ilog2(sz)) - 1;
-                       /* assign send contexts */
+                       /*
+                        * assign send contexts and
+                        * adjust credit return threshold
+                        */
                        for (j = 0; j < sz; j++) {
-                               if (dd->kernel_send_context[scontext])
+                               if (dd->kernel_send_context[scontext]) {
                                        newmap->map[i]->ksc[j] =
                                        dd->kernel_send_context[scontext];
+                                       set_threshold(dd, scontext, i);
+                               }
                                if (++scontext >= first_scontext +
                                                  vl_scontexts[i])
                                        /* wrap back to first send context */
index 2441669..9fb5616 100644 (file)
@@ -579,7 +579,8 @@ int qsfp_dump(struct hfi1_pportdata *ppd, char *buf, int len)
 
        if (ppd->qsfp_info.cache_valid) {
                if (QSFP_IS_CU(cache[QSFP_MOD_TECH_OFFS]))
-                       sprintf(lenstr, "%dM ", cache[QSFP_MOD_LEN_OFFS]);
+                       snprintf(lenstr, sizeof(lenstr), "%dM ",
+                                cache[QSFP_MOD_LEN_OFFS]);
 
                power_byte = cache[QSFP_MOD_PWR_OFFS];
                sofar += scnprintf(buf + sofar, len - sofar, "PWR:%.3sW\n",
index 79b2952..4cfb137 100644 (file)
@@ -214,19 +214,6 @@ const char *print_u32_array(
        return ret;
 }
 
-const char *print_u64_array(
-       struct trace_seq *p,
-       u64 *arr, int len)
-{
-       int i;
-       const char *ret = trace_seq_buffer_ptr(p);
-
-       for (i = 0; i < len; i++)
-               trace_seq_printf(p, "%s0x%016llx", i == 0 ? "" : " ", arr[i]);
-       trace_seq_putc(p, 0);
-       return ret;
-}
-
 __hfi1_trace_fn(PKT);
 __hfi1_trace_fn(PROC);
 __hfi1_trace_fn(SDMA);
index 29f4795..47ffd27 100644 (file)
@@ -183,7 +183,7 @@ struct user_sdma_iovec {
        struct sdma_mmu_node *node;
 };
 
-#define SDMA_CACHE_NODE_EVICT BIT(0)
+#define SDMA_CACHE_NODE_EVICT 0
 
 struct sdma_mmu_node {
        struct mmu_rb_node rb;
@@ -1355,11 +1355,11 @@ static int set_txreq_header(struct user_sdma_request *req,
                 */
                SDMA_DBG(req, "TID offset %ubytes %uunits om%u",
                         req->tidoffset, req->tidoffset / req->omfactor,
-                        !!(req->omfactor - KDETH_OM_SMALL));
+                        req->omfactor != KDETH_OM_SMALL);
                KDETH_SET(hdr->kdeth.ver_tid_offset, OFFSET,
                          req->tidoffset / req->omfactor);
                KDETH_SET(hdr->kdeth.ver_tid_offset, OM,
-                         !!(req->omfactor - KDETH_OM_SMALL));
+                         req->omfactor != KDETH_OM_SMALL);
        }
 done:
        trace_hfi1_sdma_user_header(pq->dd, pq->ctxt, pq->subctxt,
index bc95c41..d8fb056 100644 (file)
@@ -92,11 +92,10 @@ void hfi1_put_txreq(struct verbs_txreq *tx)
 
 struct verbs_txreq *__get_txreq(struct hfi1_ibdev *dev,
                                struct rvt_qp *qp)
+       __must_hold(&qp->s_lock)
 {
        struct verbs_txreq *tx = ERR_PTR(-EBUSY);
-       unsigned long flags;
 
-       spin_lock_irqsave(&qp->s_lock, flags);
        write_seqlock(&dev->iowait_lock);
        if (ib_rvt_state_ops[qp->state] & RVT_PROCESS_RECV_OK) {
                struct hfi1_qp_priv *priv;
@@ -116,7 +115,6 @@ struct verbs_txreq *__get_txreq(struct hfi1_ibdev *dev,
        }
 out:
        write_sequnlock(&dev->iowait_lock);
-       spin_unlock_irqrestore(&qp->s_lock, flags);
        return tx;
 }
 
index 1cf69b2..a1d6e08 100644 (file)
@@ -73,6 +73,7 @@ struct verbs_txreq *__get_txreq(struct hfi1_ibdev *dev,
 
 static inline struct verbs_txreq *get_txreq(struct hfi1_ibdev *dev,
                                            struct rvt_qp *qp)
+       __must_hold(&qp->slock)
 {
        struct verbs_txreq *tx;
        struct hfi1_qp_priv *priv = qp->priv;
index 8b95320..b738acd 100644 (file)
 
 #define IW_HMC_OBJ_TYPE_NUM ARRAY_SIZE(iw_hmc_obj_types)
 #define IW_CFG_FPM_QP_COUNT            32768
+#define I40IW_MAX_PAGES_PER_FMR                512
+#define I40IW_MIN_PAGES_PER_FMR                1
 
 #define I40IW_MTU_TO_MSS               40
 #define I40IW_DEFAULT_MSS              1460
index 02a735b..33959ed 100644 (file)
@@ -79,6 +79,7 @@ static int i40iw_query_device(struct ib_device *ibdev,
        props->max_qp_init_rd_atom = props->max_qp_rd_atom;
        props->atomic_cap = IB_ATOMIC_NONE;
        props->max_map_per_fmr = 1;
+       props->max_fast_reg_page_list_len = I40IW_MAX_PAGES_PER_FMR;
        return 0;
 }
 
@@ -1527,7 +1528,7 @@ static struct ib_mr *i40iw_alloc_mr(struct ib_pd *pd,
        mutex_lock(&iwdev->pbl_mutex);
        status = i40iw_get_pble(&iwdev->sc_dev, iwdev->pble_rsrc, palloc, iwmr->page_cnt);
        mutex_unlock(&iwdev->pbl_mutex);
-       if (!status)
+       if (status)
                goto err1;
 
        if (palloc->level != I40IW_LEVEL_1)
@@ -2149,6 +2150,7 @@ static int i40iw_post_send(struct ib_qp *ibqp,
                        struct i40iw_sc_dev *dev = &iwqp->iwdev->sc_dev;
                        struct i40iw_fast_reg_stag_info info;
 
+                       memset(&info, 0, sizeof(info));
                        info.access_rights = I40IW_ACCESS_FLAGS_LOCALREAD;
                        info.access_rights |= i40iw_get_user_access(flags);
                        info.stag_key = reg_wr(ib_wr)->key & 0xff;
@@ -2158,10 +2160,14 @@ static int i40iw_post_send(struct ib_qp *ibqp,
                        info.addr_type = I40IW_ADDR_TYPE_VA_BASED;
                        info.va = (void *)(uintptr_t)iwmr->ibmr.iova;
                        info.total_len = iwmr->ibmr.length;
+                       info.reg_addr_pa = *(u64 *)palloc->level1.addr;
                        info.first_pm_pbl_index = palloc->level1.idx;
                        info.local_fence = ib_wr->send_flags & IB_SEND_FENCE;
                        info.signaled = ib_wr->send_flags & IB_SEND_SIGNALED;
 
+                       if (iwmr->npages > I40IW_MIN_PAGES_PER_FMR)
+                               info.chunk_size = 1;
+
                        if (page_shift == 21)
                                info.page_size = 1; /* 2M page */
 
@@ -2327,13 +2333,16 @@ static int i40iw_req_notify_cq(struct ib_cq *ibcq,
 {
        struct i40iw_cq *iwcq;
        struct i40iw_cq_uk *ukcq;
-       enum i40iw_completion_notify cq_notify = IW_CQ_COMPL_SOLICITED;
+       unsigned long flags;
+       enum i40iw_completion_notify cq_notify = IW_CQ_COMPL_EVENT;
 
        iwcq = (struct i40iw_cq *)ibcq;
        ukcq = &iwcq->sc_cq.cq_uk;
-       if (notify_flags == IB_CQ_NEXT_COMP)
-               cq_notify = IW_CQ_COMPL_EVENT;
+       if (notify_flags == IB_CQ_SOLICITED)
+               cq_notify = IW_CQ_COMPL_SOLICITED;
+       spin_lock_irqsave(&iwcq->lock, flags);
        ukcq->ops.iw_cq_request_notification(ukcq, cq_notify);
+       spin_unlock_irqrestore(&iwcq->lock, flags);
        return 0;
 }
 
index 105246f..5fc6233 100644 (file)
@@ -47,6 +47,7 @@ static struct ib_ah *create_ib_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr,
 
        ah->av.ib.port_pd = cpu_to_be32(to_mpd(pd)->pdn | (ah_attr->port_num << 24));
        ah->av.ib.g_slid  = ah_attr->src_path_bits;
+       ah->av.ib.sl_tclass_flowlabel = cpu_to_be32(ah_attr->sl << 28);
        if (ah_attr->ah_flags & IB_AH_GRH) {
                ah->av.ib.g_slid   |= 0x80;
                ah->av.ib.gid_index = ah_attr->grh.sgid_index;
@@ -64,7 +65,6 @@ static struct ib_ah *create_ib_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr,
                       !(1 << ah->av.ib.stat_rate & dev->caps.stat_rate_support))
                        --ah->av.ib.stat_rate;
        }
-       ah->av.ib.sl_tclass_flowlabel = cpu_to_be32(ah_attr->sl << 28);
 
        return &ah->ibah;
 }
index d68f506..9c2e53d 100644 (file)
@@ -527,7 +527,7 @@ int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port,
                tun_tx_ix = (++tun_qp->tx_ix_head) & (MLX4_NUM_TUNNEL_BUFS - 1);
        spin_unlock(&tun_qp->tx_lock);
        if (ret)
-               goto out;
+               goto end;
 
        tun_mad = (struct mlx4_rcv_tunnel_mad *) (tun_qp->tx_ring[tun_tx_ix].buf.addr);
        if (tun_qp->tx_ring[tun_tx_ix].ah)
@@ -596,9 +596,15 @@ int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port,
        wr.wr.send_flags = IB_SEND_SIGNALED;
 
        ret = ib_post_send(src_qp, &wr.wr, &bad_wr);
-out:
-       if (ret)
-               ib_destroy_ah(ah);
+       if (!ret)
+               return 0;
+ out:
+       spin_lock(&tun_qp->tx_lock);
+       tun_qp->tx_ix_tail++;
+       spin_unlock(&tun_qp->tx_lock);
+       tun_qp->tx_ring[tun_tx_ix].ah = NULL;
+end:
+       ib_destroy_ah(ah);
        return ret;
 }
 
@@ -1326,9 +1332,15 @@ int mlx4_ib_send_to_wire(struct mlx4_ib_dev *dev, int slave, u8 port,
 
 
        ret = ib_post_send(send_qp, &wr.wr, &bad_wr);
+       if (!ret)
+               return 0;
+
+       spin_lock(&sqp->tx_lock);
+       sqp->tx_ix_tail++;
+       spin_unlock(&sqp->tx_lock);
+       sqp->tx_ring[wire_tx_ix].ah = NULL;
 out:
-       if (ret)
-               ib_destroy_ah(ah);
+       ib_destroy_ah(ah);
        return ret;
 }
 
index b01ef6e..42a4607 100644 (file)
@@ -505,9 +505,9 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
                        props->device_cap_flags |= IB_DEVICE_MEM_WINDOW_TYPE_2B;
                else
                        props->device_cap_flags |= IB_DEVICE_MEM_WINDOW_TYPE_2A;
-       if (dev->steering_support ==  MLX4_STEERING_MODE_DEVICE_MANAGED)
-               props->device_cap_flags |= IB_DEVICE_MANAGED_FLOW_STEERING;
        }
+       if (dev->steering_support == MLX4_STEERING_MODE_DEVICE_MANAGED)
+               props->device_cap_flags |= IB_DEVICE_MANAGED_FLOW_STEERING;
 
        props->device_cap_flags |= IB_DEVICE_RAW_IP_CSUM;
 
@@ -1704,6 +1704,9 @@ static struct ib_flow *mlx4_ib_create_flow(struct ib_qp *qp,
        struct mlx4_dev *dev = (to_mdev(qp->device))->dev;
        int is_bonded = mlx4_is_bonded(dev);
 
+       if (flow_attr->port < 1 || flow_attr->port > qp->device->phys_port_cnt)
+               return ERR_PTR(-EINVAL);
+
        if ((flow_attr->flags & IB_FLOW_ATTR_FLAGS_DONT_TRAP) &&
            (flow_attr->type != IB_FLOW_ATTR_NORMAL))
                return ERR_PTR(-EOPNOTSUPP);
index 6c5ac5d..29acda2 100644 (file)
@@ -139,7 +139,7 @@ struct mlx4_ib_mr {
        u32                     max_pages;
        struct mlx4_mr          mmr;
        struct ib_umem         *umem;
-       void                    *pages_alloc;
+       size_t                  page_map_size;
 };
 
 struct mlx4_ib_mw {
index 6312721..5d73989 100644 (file)
@@ -277,20 +277,23 @@ mlx4_alloc_priv_pages(struct ib_device *device,
                      struct mlx4_ib_mr *mr,
                      int max_pages)
 {
-       int size = max_pages * sizeof(u64);
-       int add_size;
        int ret;
 
-       add_size = max_t(int, MLX4_MR_PAGES_ALIGN - ARCH_KMALLOC_MINALIGN, 0);
+       /* Ensure that size is aligned to DMA cacheline
+        * requirements.
+        * max_pages is limited to MLX4_MAX_FAST_REG_PAGES
+        * so page_map_size will never cross PAGE_SIZE.
+        */
+       mr->page_map_size = roundup(max_pages * sizeof(u64),
+                                   MLX4_MR_PAGES_ALIGN);
 
-       mr->pages_alloc = kzalloc(size + add_size, GFP_KERNEL);
-       if (!mr->pages_alloc)
+       /* Prevent cross page boundary allocation. */
+       mr->pages = (__be64 *)get_zeroed_page(GFP_KERNEL);
+       if (!mr->pages)
                return -ENOMEM;
 
-       mr->pages = PTR_ALIGN(mr->pages_alloc, MLX4_MR_PAGES_ALIGN);
-
        mr->page_map = dma_map_single(device->dma_device, mr->pages,
-                                     size, DMA_TO_DEVICE);
+                                     mr->page_map_size, DMA_TO_DEVICE);
 
        if (dma_mapping_error(device->dma_device, mr->page_map)) {
                ret = -ENOMEM;
@@ -298,9 +301,9 @@ mlx4_alloc_priv_pages(struct ib_device *device,
        }
 
        return 0;
-err:
-       kfree(mr->pages_alloc);
 
+err:
+       free_page((unsigned long)mr->pages);
        return ret;
 }
 
@@ -309,11 +312,10 @@ mlx4_free_priv_pages(struct mlx4_ib_mr *mr)
 {
        if (mr->pages) {
                struct ib_device *device = mr->ibmr.device;
-               int size = mr->max_pages * sizeof(u64);
 
                dma_unmap_single(device->dma_device, mr->page_map,
-                                size, DMA_TO_DEVICE);
-               kfree(mr->pages_alloc);
+                                mr->page_map_size, DMA_TO_DEVICE);
+               free_page((unsigned long)mr->pages);
                mr->pages = NULL;
        }
 }
@@ -537,14 +539,12 @@ int mlx4_ib_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents,
        mr->npages = 0;
 
        ib_dma_sync_single_for_cpu(ibmr->device, mr->page_map,
-                                  sizeof(u64) * mr->max_pages,
-                                  DMA_TO_DEVICE);
+                                  mr->page_map_size, DMA_TO_DEVICE);
 
        rc = ib_sg_to_pages(ibmr, sg, sg_nents, sg_offset, mlx4_set_page);
 
        ib_dma_sync_single_for_device(ibmr->device, mr->page_map,
-                                     sizeof(u64) * mr->max_pages,
-                                     DMA_TO_DEVICE);
+                                     mr->page_map_size, DMA_TO_DEVICE);
 
        return rc;
 }
index 81b0e1f..8db8405 100644 (file)
@@ -362,7 +362,7 @@ static int send_wqe_overhead(enum mlx4_ib_qp_type type, u32 flags)
                        sizeof (struct mlx4_wqe_raddr_seg);
        case MLX4_IB_QPT_RC:
                return sizeof (struct mlx4_wqe_ctrl_seg) +
-                       sizeof (struct mlx4_wqe_atomic_seg) +
+                       sizeof (struct mlx4_wqe_masked_atomic_seg) +
                        sizeof (struct mlx4_wqe_raddr_seg);
        case MLX4_IB_QPT_SMI:
        case MLX4_IB_QPT_GSI:
@@ -1191,8 +1191,10 @@ static struct ib_qp *_mlx4_ib_create_qp(struct ib_pd *pd,
        {
                err = create_qp_common(to_mdev(pd->device), pd, init_attr,
                                       udata, 0, &qp, gfp);
-               if (err)
+               if (err) {
+                       kfree(qp);
                        return ERR_PTR(err);
+               }
 
                qp->ibqp.qp_num = qp->mqp.qpn;
                qp->xrcdn = xrcdn;
index dabcc65..9c0e67b 100644 (file)
@@ -822,7 +822,8 @@ struct ib_cq *mlx5_ib_create_cq(struct ib_device *ibdev,
        int eqn;
        int err;
 
-       if (entries < 0)
+       if (entries < 0 ||
+           (entries > (1 << MLX5_CAP_GEN(dev->mdev, log_max_cq_sz))))
                return ERR_PTR(-EINVAL);
 
        if (check_cq_create_flags(attr->flags))
@@ -1168,11 +1169,16 @@ int mlx5_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata)
                return -ENOSYS;
        }
 
-       if (entries < 1)
+       if (entries < 1 ||
+           entries > (1 << MLX5_CAP_GEN(dev->mdev, log_max_cq_sz))) {
+               mlx5_ib_warn(dev, "wrong entries number %d, max %d\n",
+                            entries,
+                            1 << MLX5_CAP_GEN(dev->mdev, log_max_cq_sz));
                return -EINVAL;
+       }
 
        entries = roundup_pow_of_two(entries + 1);
-       if (entries >  (1 << MLX5_CAP_GEN(dev->mdev, log_max_cq_sz)) + 1)
+       if (entries > (1 << MLX5_CAP_GEN(dev->mdev, log_max_cq_sz)) + 1)
                return -EINVAL;
 
        if (entries == ibcq->cqe + 1)
index 1534af1..364aab9 100644 (file)
@@ -121,7 +121,7 @@ static void pma_cnt_ext_assign(struct ib_pma_portcounters_ext *pma_cnt_ext,
        pma_cnt_ext->port_xmit_data =
                cpu_to_be64(MLX5_SUM_CNT(out, transmitted_ib_unicast.octets,
                                         transmitted_ib_multicast.octets) >> 2);
-       pma_cnt_ext->port_xmit_data =
+       pma_cnt_ext->port_rcv_data =
                cpu_to_be64(MLX5_SUM_CNT(out, received_ib_unicast.octets,
                                         received_ib_multicast.octets) >> 2);
        pma_cnt_ext->port_xmit_packets =
index c72797c..b48ad85 100644 (file)
@@ -524,6 +524,9 @@ static int mlx5_ib_query_device(struct ib_device *ibdev,
            MLX5_CAP_ETH(dev->mdev, scatter_fcs))
                props->device_cap_flags |= IB_DEVICE_RAW_SCATTER_FCS;
 
+       if (mlx5_get_flow_namespace(dev->mdev, MLX5_FLOW_NAMESPACE_BYPASS))
+               props->device_cap_flags |= IB_DEVICE_MANAGED_FLOW_STEERING;
+
        props->vendor_part_id      = mdev->pdev->device;
        props->hw_ver              = mdev->pdev->revision;
 
@@ -915,7 +918,8 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
        num_uars = req.total_num_uuars / MLX5_NON_FP_BF_REGS_PER_PAGE;
        gross_uuars = num_uars * MLX5_BF_REGS_PER_PAGE;
        resp.qp_tab_size = 1 << MLX5_CAP_GEN(dev->mdev, log_max_qp);
-       resp.bf_reg_size = 1 << MLX5_CAP_GEN(dev->mdev, log_bf_reg_size);
+       if (mlx5_core_is_pf(dev->mdev) && MLX5_CAP_GEN(dev->mdev, bf))
+               resp.bf_reg_size = 1 << MLX5_CAP_GEN(dev->mdev, log_bf_reg_size);
        resp.cache_line_size = L1_CACHE_BYTES;
        resp.max_sq_desc_sz = MLX5_CAP_GEN(dev->mdev, max_wqe_sz_sq);
        resp.max_rq_desc_sz = MLX5_CAP_GEN(dev->mdev, max_wqe_sz_rq);
@@ -988,7 +992,14 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
        if (field_avail(typeof(resp), cqe_version, udata->outlen))
                resp.response_length += sizeof(resp.cqe_version);
 
-       if (field_avail(typeof(resp), hca_core_clock_offset, udata->outlen)) {
+       /*
+        * We don't want to expose information from the PCI bar that is located
+        * after 4096 bytes, so if the arch only supports larger pages, let's
+        * pretend we don't support reading the HCA's core clock. This is also
+        * forced by mmap function.
+        */
+       if (PAGE_SIZE <= 4096 &&
+           field_avail(typeof(resp), hca_core_clock_offset, udata->outlen)) {
                resp.comp_mask |=
                        MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_CORE_CLOCK_OFFSET;
                resp.hca_core_clock_offset =
@@ -1798,7 +1809,7 @@ static ssize_t show_fw_ver(struct device *device, struct device_attribute *attr,
 {
        struct mlx5_ib_dev *dev =
                container_of(device, struct mlx5_ib_dev, ib_dev.dev);
-       return sprintf(buf, "%d.%d.%d\n", fw_rev_maj(dev->mdev),
+       return sprintf(buf, "%d.%d.%04d\n", fw_rev_maj(dev->mdev),
                       fw_rev_min(dev->mdev), fw_rev_sub(dev->mdev));
 }
 
@@ -1866,14 +1877,11 @@ static void mlx5_ib_event(struct mlx5_core_dev *dev, void *context,
                break;
 
        case MLX5_DEV_EVENT_PORT_DOWN:
+       case MLX5_DEV_EVENT_PORT_INITIALIZED:
                ibev.event = IB_EVENT_PORT_ERR;
                port = (u8)param;
                break;
 
-       case MLX5_DEV_EVENT_PORT_INITIALIZED:
-               /* not used by ULPs */
-               return;
-
        case MLX5_DEV_EVENT_LID_CHANGE:
                ibev.event = IB_EVENT_LID_CHANGE;
                port = (u8)param;
index 5041176..ce0a7ab 100644 (file)
@@ -235,6 +235,8 @@ static int set_rq_size(struct mlx5_ib_dev *dev, struct ib_qp_cap *cap,
                qp->rq.max_gs = 0;
                qp->rq.wqe_cnt = 0;
                qp->rq.wqe_shift = 0;
+               cap->max_recv_wr = 0;
+               cap->max_recv_sge = 0;
        } else {
                if (ucmd) {
                        qp->rq.wqe_cnt = ucmd->rq_wqe_count;
@@ -1851,13 +1853,15 @@ static int modify_raw_packet_eth_prio(struct mlx5_core_dev *dev,
 static int mlx5_set_path(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
                         const struct ib_ah_attr *ah,
                         struct mlx5_qp_path *path, u8 port, int attr_mask,
-                        u32 path_flags, const struct ib_qp_attr *attr)
+                        u32 path_flags, const struct ib_qp_attr *attr,
+                        bool alt)
 {
        enum rdma_link_layer ll = rdma_port_get_link_layer(&dev->ib_dev, port);
        int err;
 
        if (attr_mask & IB_QP_PKEY_INDEX)
-               path->pkey_index = attr->pkey_index;
+               path->pkey_index = cpu_to_be16(alt ? attr->alt_pkey_index :
+                                                    attr->pkey_index);
 
        if (ah->ah_flags & IB_AH_GRH) {
                if (ah->grh.sgid_index >=
@@ -1877,9 +1881,9 @@ static int mlx5_set_path(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
                                                          ah->grh.sgid_index);
                path->dci_cfi_prio_sl = (ah->sl & 0x7) << 4;
        } else {
-               path->fl = (path_flags & MLX5_PATH_FLAG_FL) ? 0x80 : 0;
-               path->free_ar = (path_flags & MLX5_PATH_FLAG_FREE_AR) ? 0x80 :
-                                                                       0;
+               path->fl_free_ar = (path_flags & MLX5_PATH_FLAG_FL) ? 0x80 : 0;
+               path->fl_free_ar |=
+                       (path_flags & MLX5_PATH_FLAG_FREE_AR) ? 0x40 : 0;
                path->rlid = cpu_to_be16(ah->dlid);
                path->grh_mlid = ah->src_path_bits & 0x7f;
                if (ah->ah_flags & IB_AH_GRH)
@@ -1903,7 +1907,7 @@ static int mlx5_set_path(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
        path->port = port;
 
        if (attr_mask & IB_QP_TIMEOUT)
-               path->ackto_lt = attr->timeout << 3;
+               path->ackto_lt = (alt ? attr->alt_timeout : attr->timeout) << 3;
 
        if ((qp->ibqp.qp_type == IB_QPT_RAW_PACKET) && qp->sq.wqe_cnt)
                return modify_raw_packet_eth_prio(dev->mdev,
@@ -2264,7 +2268,7 @@ static int __mlx5_ib_modify_qp(struct ib_qp *ibqp,
                context->log_pg_sz_remote_qpn = cpu_to_be32(attr->dest_qp_num);
 
        if (attr_mask & IB_QP_PKEY_INDEX)
-               context->pri_path.pkey_index = attr->pkey_index;
+               context->pri_path.pkey_index = cpu_to_be16(attr->pkey_index);
 
        /* todo implement counter_index functionality */
 
@@ -2277,7 +2281,7 @@ static int __mlx5_ib_modify_qp(struct ib_qp *ibqp,
        if (attr_mask & IB_QP_AV) {
                err = mlx5_set_path(dev, qp, &attr->ah_attr, &context->pri_path,
                                    attr_mask & IB_QP_PORT ? attr->port_num : qp->port,
-                                   attr_mask, 0, attr);
+                                   attr_mask, 0, attr, false);
                if (err)
                        goto out;
        }
@@ -2288,7 +2292,9 @@ static int __mlx5_ib_modify_qp(struct ib_qp *ibqp,
        if (attr_mask & IB_QP_ALT_PATH) {
                err = mlx5_set_path(dev, qp, &attr->alt_ah_attr,
                                    &context->alt_path,
-                                   attr->alt_port_num, attr_mask, 0, attr);
+                                   attr->alt_port_num,
+                                   attr_mask | IB_QP_PKEY_INDEX | IB_QP_TIMEOUT,
+                                   0, attr, true);
                if (err)
                        goto out;
        }
@@ -3326,10 +3332,11 @@ static u8 get_fence(u8 fence, struct ib_send_wr *wr)
                        return MLX5_FENCE_MODE_SMALL_AND_FENCE;
                else
                        return fence;
-
-       } else {
-               return 0;
+       } else if (unlikely(wr->send_flags & IB_SEND_FENCE)) {
+               return MLX5_FENCE_MODE_FENCE;
        }
+
+       return 0;
 }
 
 static int begin_wqe(struct mlx5_ib_qp *qp, void **seg,
@@ -4013,11 +4020,12 @@ static int query_qp_attr(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
        if (qp->ibqp.qp_type == IB_QPT_RC || qp->ibqp.qp_type == IB_QPT_UC) {
                to_ib_ah_attr(dev, &qp_attr->ah_attr, &context->pri_path);
                to_ib_ah_attr(dev, &qp_attr->alt_ah_attr, &context->alt_path);
-               qp_attr->alt_pkey_index = context->alt_path.pkey_index & 0x7f;
+               qp_attr->alt_pkey_index =
+                       be16_to_cpu(context->alt_path.pkey_index);
                qp_attr->alt_port_num   = qp_attr->alt_ah_attr.port_num;
        }
 
-       qp_attr->pkey_index = context->pri_path.pkey_index & 0x7f;
+       qp_attr->pkey_index = be16_to_cpu(context->pri_path.pkey_index);
        qp_attr->port_num = context->pri_path.port;
 
        /* qp_attr->en_sqd_async_notify is only applicable in modify qp */
@@ -4079,17 +4087,19 @@ int mlx5_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
        qp_attr->cap.max_recv_sge    = qp->rq.max_gs;
 
        if (!ibqp->uobject) {
-               qp_attr->cap.max_send_wr  = qp->sq.wqe_cnt;
+               qp_attr->cap.max_send_wr  = qp->sq.max_post;
                qp_attr->cap.max_send_sge = qp->sq.max_gs;
+               qp_init_attr->qp_context = ibqp->qp_context;
        } else {
                qp_attr->cap.max_send_wr  = 0;
                qp_attr->cap.max_send_sge = 0;
        }
 
-       /* We don't support inline sends for kernel QPs (yet), and we
-        * don't know what userspace's value should be.
-        */
-       qp_attr->cap.max_inline_data = 0;
+       qp_init_attr->qp_type = ibqp->qp_type;
+       qp_init_attr->recv_cq = ibqp->recv_cq;
+       qp_init_attr->send_cq = ibqp->send_cq;
+       qp_init_attr->srq = ibqp->srq;
+       qp_attr->cap.max_inline_data = qp->max_inline_data;
 
        qp_init_attr->cap            = qp_attr->cap;
 
index ff946d5..382466a 100644 (file)
@@ -2178,6 +2178,11 @@ static ssize_t qib_write(struct file *fp, const char __user *data,
 
        switch (cmd.type) {
        case QIB_CMD_ASSIGN_CTXT:
+               if (rcd) {
+                       ret = -EINVAL;
+                       goto bail;
+               }
+
                ret = qib_assign_ctxt(fp, &cmd.cmd.user_info);
                if (ret)
                        goto bail;
index 7209fbc..a0b6ebe 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/dma-mapping.h>
 #include <linux/sched.h>
 #include <linux/hugetlb.h>
-#include <linux/dma-attrs.h>
 #include <linux/iommu.h>
 #include <linux/workqueue.h>
 #include <linux/list.h>
@@ -112,10 +111,6 @@ static int usnic_uiom_get_pages(unsigned long addr, size_t size, int writable,
        int i;
        int flags;
        dma_addr_t pa;
-       DEFINE_DMA_ATTRS(attrs);
-
-       if (dmasync)
-               dma_set_attr(DMA_ATTR_WRITE_BARRIER, &attrs);
 
        if (!can_do_mlock())
                return -EPERM;
index 5fa4d4d..41ba7e9 100644 (file)
@@ -369,8 +369,8 @@ static int alloc_qpn(struct rvt_dev_info *rdi, struct rvt_qpn_table *qpt,
                        /* wrap to first map page, invert bit 0 */
                        offset = qpt->incr | ((offset & 1) ^ 1);
                }
-               /* there can be no bits at shift and below */
-               WARN_ON(offset & (rdi->dparms.qos_shift - 1));
+               /* there can be no set bits in low-order QoS bits */
+               WARN_ON(offset & (BIT(rdi->dparms.qos_shift) - 1));
                qpn = mk_qpn(qpt, map, offset);
        }
 
@@ -502,6 +502,12 @@ static void rvt_remove_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp)
  */
 static void rvt_reset_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp,
                  enum ib_qp_type type)
+       __releases(&qp->s_lock)
+       __releases(&qp->s_hlock)
+       __releases(&qp->r_lock)
+       __acquires(&qp->r_lock)
+       __acquires(&qp->s_hlock)
+       __acquires(&qp->s_lock)
 {
        if (qp->state != IB_QPS_RESET) {
                qp->state = IB_QPS_RESET;
@@ -570,12 +576,6 @@ static void rvt_reset_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp,
        qp->s_ssn = 1;
        qp->s_lsn = 0;
        qp->s_mig_state = IB_MIG_MIGRATED;
-       if (qp->s_ack_queue)
-               memset(
-                       qp->s_ack_queue,
-                       0,
-                       rvt_max_atomic(rdi) *
-                               sizeof(*qp->s_ack_queue));
        qp->r_head_ack_queue = 0;
        qp->s_tail_ack_queue = 0;
        qp->s_num_rd_atomic = 0;
@@ -699,8 +699,10 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
                 * initialization that is needed.
                 */
                priv = rdi->driver_f.qp_priv_alloc(rdi, qp, gfp);
-               if (!priv)
+               if (IS_ERR(priv)) {
+                       ret = priv;
                        goto bail_qp;
+               }
                qp->priv = priv;
                qp->timeout_jiffies =
                        usecs_to_jiffies((4096UL * (1UL << qp->timeout)) /
index e1cc2cc..30c4fda 100644 (file)
@@ -501,9 +501,7 @@ static noinline int check_support(struct rvt_dev_info *rdi, int verb)
                            !rdi->driver_f.quiesce_qp ||
                            !rdi->driver_f.notify_error_qp ||
                            !rdi->driver_f.mtu_from_qp ||
-                           !rdi->driver_f.mtu_to_path_mtu ||
-                           !rdi->driver_f.shut_down_port ||
-                           !rdi->driver_f.cap_mask_chg)
+                           !rdi->driver_f.mtu_to_path_mtu)
                                return -EINVAL;
                break;
 
index bab7db6..4f7d9b4 100644 (file)
@@ -94,6 +94,7 @@ enum {
        IPOIB_NEIGH_TBL_FLUSH     = 12,
        IPOIB_FLAG_DEV_ADDR_SET   = 13,
        IPOIB_FLAG_DEV_ADDR_CTRL  = 14,
+       IPOIB_FLAG_GOING_DOWN     = 15,
 
        IPOIB_MAX_BACKOFF_SECONDS = 16,
 
index b2f4283..951d9ab 100644 (file)
@@ -1486,6 +1486,10 @@ static ssize_t set_mode(struct device *d, struct device_attribute *attr,
 {
        struct net_device *dev = to_net_dev(d);
        int ret;
+       struct ipoib_dev_priv *priv = netdev_priv(dev);
+
+       if (test_bit(IPOIB_FLAG_GOING_DOWN, &priv->flags))
+               return -EPERM;
 
        if (!rtnl_trylock())
                return restart_syscall();
index 45c40a1..dc6d241 100644 (file)
@@ -1015,7 +1015,7 @@ static bool ipoib_dev_addr_changed_valid(struct ipoib_dev_priv *priv)
        if (ib_query_gid(priv->ca, priv->port, 0, &gid0, NULL))
                return false;
 
-       netif_addr_lock(priv->dev);
+       netif_addr_lock_bh(priv->dev);
 
        /* The subnet prefix may have changed, update it now so we won't have
         * to do it later
@@ -1026,12 +1026,12 @@ static bool ipoib_dev_addr_changed_valid(struct ipoib_dev_priv *priv)
 
        search_gid.global.interface_id = priv->local_gid.global.interface_id;
 
-       netif_addr_unlock(priv->dev);
+       netif_addr_unlock_bh(priv->dev);
 
        err = ib_find_gid(priv->ca, &search_gid, IB_GID_TYPE_IB,
                          priv->dev, &port, &index);
 
-       netif_addr_lock(priv->dev);
+       netif_addr_lock_bh(priv->dev);
 
        if (search_gid.global.interface_id !=
            priv->local_gid.global.interface_id)
@@ -1092,7 +1092,7 @@ static bool ipoib_dev_addr_changed_valid(struct ipoib_dev_priv *priv)
        }
 
 out:
-       netif_addr_unlock(priv->dev);
+       netif_addr_unlock_bh(priv->dev);
 
        return ret;
 }
index 2d7c163..5f58c41 100644 (file)
@@ -1206,7 +1206,9 @@ struct ipoib_neigh *ipoib_neigh_get(struct net_device *dev, u8 *daddr)
                                neigh = NULL;
                                goto out_unlock;
                        }
-                       neigh->alive = jiffies;
+
+                       if (likely(skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE))
+                               neigh->alive = jiffies;
                        goto out_unlock;
                }
        }
@@ -1851,7 +1853,7 @@ static void set_base_guid(struct ipoib_dev_priv *priv, union ib_gid *gid)
        struct ipoib_dev_priv *child_priv;
        struct net_device *netdev = priv->dev;
 
-       netif_addr_lock(netdev);
+       netif_addr_lock_bh(netdev);
 
        memcpy(&priv->local_gid.global.interface_id,
               &gid->global.interface_id,
@@ -1859,7 +1861,7 @@ static void set_base_guid(struct ipoib_dev_priv *priv, union ib_gid *gid)
        memcpy(netdev->dev_addr + 4, &priv->local_gid, sizeof(priv->local_gid));
        clear_bit(IPOIB_FLAG_DEV_ADDR_SET, &priv->flags);
 
-       netif_addr_unlock(netdev);
+       netif_addr_unlock_bh(netdev);
 
        if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) {
                down_read(&priv->vlan_rwsem);
@@ -1875,7 +1877,7 @@ static int ipoib_check_lladdr(struct net_device *dev,
        union ib_gid *gid = (union ib_gid *)(ss->__data + 4);
        int ret = 0;
 
-       netif_addr_lock(dev);
+       netif_addr_lock_bh(dev);
 
        /* Make sure the QPN, reserved and subnet prefix match the current
         * lladdr, it also makes sure the lladdr is unicast.
@@ -1885,7 +1887,7 @@ static int ipoib_check_lladdr(struct net_device *dev,
            gid->global.interface_id == 0)
                ret = -EINVAL;
 
-       netif_addr_unlock(dev);
+       netif_addr_unlock_bh(dev);
 
        return ret;
 }
@@ -2141,6 +2143,9 @@ static void ipoib_remove_one(struct ib_device *device, void *client_data)
                ib_unregister_event_handler(&priv->event_handler);
                flush_workqueue(ipoib_workqueue);
 
+               /* mark interface in the middle of destruction */
+               set_bit(IPOIB_FLAG_GOING_DOWN, &priv->flags);
+
                rtnl_lock();
                dev_change_flags(priv->dev, priv->dev->flags & ~IFF_UP);
                rtnl_unlock();
index 82fbc94..d3394b6 100644 (file)
@@ -582,13 +582,13 @@ void ipoib_mcast_join_task(struct work_struct *work)
                return;
        }
        priv->local_lid = port_attr.lid;
-       netif_addr_lock(dev);
+       netif_addr_lock_bh(dev);
 
        if (!test_bit(IPOIB_FLAG_DEV_ADDR_SET, &priv->flags)) {
-               netif_addr_unlock(dev);
+               netif_addr_unlock_bh(dev);
                return;
        }
-       netif_addr_unlock(dev);
+       netif_addr_unlock_bh(dev);
 
        spin_lock_irq(&priv->lock);
        if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags))
index 64a3559..a2f9f29 100644 (file)
@@ -131,6 +131,9 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
 
        ppriv = netdev_priv(pdev);
 
+       if (test_bit(IPOIB_FLAG_GOING_DOWN, &ppriv->flags))
+               return -EPERM;
+
        snprintf(intf_name, sizeof intf_name, "%s.%04x",
                 ppriv->dev->name, pkey);
        priv = ipoib_intf_alloc(intf_name);
@@ -183,6 +186,9 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey)
 
        ppriv = netdev_priv(pdev);
 
+       if (test_bit(IPOIB_FLAG_GOING_DOWN, &ppriv->flags))
+               return -EPERM;
+
        if (!rtnl_trylock())
                return restart_syscall();
 
index 646de17..3322ed7 100644 (file)
@@ -1457,7 +1457,6 @@ static int srp_map_sg_fr(struct srp_map_state *state, struct srp_rdma_ch *ch,
 {
        unsigned int sg_offset = 0;
 
-       state->desc = req->indirect_desc;
        state->fr.next = req->fr_list;
        state->fr.end = req->fr_list + ch->target->mr_per_cmd;
        state->sg = scat;
@@ -1489,7 +1488,6 @@ static int srp_map_sg_dma(struct srp_map_state *state, struct srp_rdma_ch *ch,
        struct scatterlist *sg;
        int i;
 
-       state->desc = req->indirect_desc;
        for_each_sg(scat, sg, count, i) {
                srp_map_desc(state, ib_sg_dma_address(dev->dev, sg),
                             ib_sg_dma_len(dev->dev, sg),
@@ -1655,6 +1653,7 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_rdma_ch *ch,
                                   target->indirect_size, DMA_TO_DEVICE);
 
        memset(&state, 0, sizeof(state));
+       state.desc = req->indirect_desc;
        if (dev->use_fast_reg)
                ret = srp_map_sg_fr(&state, ch, req, scat, count);
        else if (dev->use_fmr)
@@ -3526,7 +3525,7 @@ static void srp_add_one(struct ib_device *device)
        int mr_page_shift, p;
        u64 max_pages_per_mr;
 
-       srp_dev = kmalloc(sizeof *srp_dev, GFP_KERNEL);
+       srp_dev = kzalloc(sizeof(*srp_dev), GFP_KERNEL);
        if (!srp_dev)
                return;
 
@@ -3586,8 +3585,6 @@ static void srp_add_one(struct ib_device *device)
                                                   IB_ACCESS_REMOTE_WRITE);
                if (IS_ERR(srp_dev->global_mr))
                        goto err_pd;
-       } else {
-               srp_dev->global_mr = NULL;
        }
 
        for (p = rdma_start_port(device); p <= rdma_end_port(device); ++p) {
index e68b20c..4a41556 100644 (file)
@@ -1638,8 +1638,7 @@ retry:
         */
        qp_init->cap.max_send_wr = srp_sq_size / 2;
        qp_init->cap.max_rdma_ctxs = srp_sq_size / 2;
-       qp_init->cap.max_send_sge = max(sdev->device->attrs.max_sge_rd,
-                                       sdev->device->attrs.max_sge);
+       qp_init->cap.max_send_sge = SRPT_DEF_SG_PER_WQE;
        qp_init->port_num = ch->sport->port;
 
        ch->qp = ib_create_qp(sdev->pd, qp_init);
index fee6bfd..3890304 100644 (file)
@@ -106,6 +106,7 @@ enum {
        SRP_LOGIN_RSP_MULTICHAN_MAINTAINED = 0x2,
 
        SRPT_DEF_SG_TABLESIZE = 128,
+       SRPT_DEF_SG_PER_WQE = 16,
 
        MIN_SRPT_SQ_SIZE = 16,
        DEF_SRPT_SQ_SIZE = 4096,
index 94b6821..5f6b3bc 100644 (file)
@@ -1941,6 +1941,7 @@ static struct iommu_ops arm_smmu_ops = {
        .attach_dev             = arm_smmu_attach_dev,
        .map                    = arm_smmu_map,
        .unmap                  = arm_smmu_unmap,
+       .map_sg                 = default_iommu_map_sg,
        .iova_to_phys           = arm_smmu_iova_to_phys,
        .add_device             = arm_smmu_add_device,
        .remove_device          = arm_smmu_remove_device,
index a644d0c..1070094 100644 (file)
@@ -3222,11 +3222,6 @@ static int __init init_dmars(void)
                        }
                }
 
-               iommu_flush_write_buffer(iommu);
-               iommu_set_root_entry(iommu);
-               iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL);
-               iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
-
                if (!ecap_pass_through(iommu->ecap))
                        hw_pass_through = 0;
 #ifdef CONFIG_INTEL_IOMMU_SVM
@@ -3235,6 +3230,18 @@ static int __init init_dmars(void)
 #endif
        }
 
+       /*
+        * Now that qi is enabled on all iommus, set the root entry and flush
+        * caches. This is required on some Intel X58 chipsets, otherwise the
+        * flush_context function will loop forever and the boot hangs.
+        */
+       for_each_active_iommu(iommu, drhd) {
+               iommu_flush_write_buffer(iommu);
+               iommu_set_root_entry(iommu);
+               iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL);
+               iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
+       }
+
        if (iommu_pass_through)
                iommu_identity_mapping |= IDENTMAP_ALL;
 
index c7d6156..25b4627 100644 (file)
@@ -815,7 +815,7 @@ static int rk_iommu_attach_device(struct iommu_domain *domain,
        dte_addr = virt_to_phys(rk_domain->dt);
        for (i = 0; i < iommu->num_mmu; i++) {
                rk_iommu_write(iommu->bases[i], RK_MMU_DTE_ADDR, dte_addr);
-               rk_iommu_command(iommu->bases[i], RK_MMU_CMD_ZAP_CACHE);
+               rk_iommu_base_command(iommu->bases[i], RK_MMU_CMD_ZAP_CACHE);
                rk_iommu_write(iommu->bases[i], RK_MMU_INT_MASK, RK_MMU_IRQ_MASK);
        }
 
index 6bd881b..5eb1f9e 100644 (file)
@@ -41,6 +41,7 @@
 
 #define ITS_FLAGS_CMDQ_NEEDS_FLUSHING          (1ULL << 0)
 #define ITS_FLAGS_WORKAROUND_CAVIUM_22375      (1ULL << 1)
+#define ITS_FLAGS_WORKAROUND_CAVIUM_23144      (1ULL << 2)
 
 #define RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING    (1 << 0)
 
@@ -82,6 +83,7 @@ struct its_node {
        u64                     flags;
        u32                     ite_size;
        u32                     device_ids;
+       int                     numa_node;
 };
 
 #define ITS_ITT_ALIGN          SZ_256
@@ -613,11 +615,23 @@ static void its_unmask_irq(struct irq_data *d)
 static int its_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
                            bool force)
 {
-       unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask);
+       unsigned int cpu;
+       const struct cpumask *cpu_mask = cpu_online_mask;
        struct its_device *its_dev = irq_data_get_irq_chip_data(d);
        struct its_collection *target_col;
        u32 id = its_get_event_id(d);
 
+       /* lpi cannot be routed to a redistributor that is on a foreign node */
+       if (its_dev->its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_23144) {
+               if (its_dev->its->numa_node >= 0) {
+                       cpu_mask = cpumask_of_node(its_dev->its->numa_node);
+                       if (!cpumask_intersects(mask_val, cpu_mask))
+                               return -EINVAL;
+               }
+       }
+
+       cpu = cpumask_any_and(mask_val, cpu_mask);
+
        if (cpu >= nr_cpu_ids)
                return -EINVAL;
 
@@ -1101,6 +1115,16 @@ static void its_cpu_init_collection(void)
        list_for_each_entry(its, &its_nodes, entry) {
                u64 target;
 
+               /* avoid cross node collections and its mapping */
+               if (its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_23144) {
+                       struct device_node *cpu_node;
+
+                       cpu_node = of_get_cpu_node(cpu, NULL);
+                       if (its->numa_node != NUMA_NO_NODE &&
+                               its->numa_node != of_node_to_nid(cpu_node))
+                               continue;
+               }
+
                /*
                 * We now have to bind each collection to its target
                 * redistributor.
@@ -1351,9 +1375,14 @@ static void its_irq_domain_activate(struct irq_domain *domain,
 {
        struct its_device *its_dev = irq_data_get_irq_chip_data(d);
        u32 event = its_get_event_id(d);
+       const struct cpumask *cpu_mask = cpu_online_mask;
+
+       /* get the cpu_mask of local node */
+       if (its_dev->its->numa_node >= 0)
+               cpu_mask = cpumask_of_node(its_dev->its->numa_node);
 
        /* Bind the LPI to the first possible CPU */
-       its_dev->event_map.col_map[event] = cpumask_first(cpu_online_mask);
+       its_dev->event_map.col_map[event] = cpumask_first(cpu_mask);
 
        /* Map the GIC IRQ and event to the device */
        its_send_mapvi(its_dev, d->hwirq, event);
@@ -1443,6 +1472,13 @@ static void __maybe_unused its_enable_quirk_cavium_22375(void *data)
        its->flags |= ITS_FLAGS_WORKAROUND_CAVIUM_22375;
 }
 
+static void __maybe_unused its_enable_quirk_cavium_23144(void *data)
+{
+       struct its_node *its = data;
+
+       its->flags |= ITS_FLAGS_WORKAROUND_CAVIUM_23144;
+}
+
 static const struct gic_quirk its_quirks[] = {
 #ifdef CONFIG_CAVIUM_ERRATUM_22375
        {
@@ -1451,6 +1487,14 @@ static const struct gic_quirk its_quirks[] = {
                .mask   = 0xffff0fff,
                .init   = its_enable_quirk_cavium_22375,
        },
+#endif
+#ifdef CONFIG_CAVIUM_ERRATUM_23144
+       {
+               .desc   = "ITS: Cavium erratum 23144",
+               .iidr   = 0xa100034c,   /* ThunderX pass 1.x */
+               .mask   = 0xffff0fff,
+               .init   = its_enable_quirk_cavium_23144,
+       },
 #endif
        {
        }
@@ -1514,6 +1558,7 @@ static int __init its_probe(struct device_node *node,
        its->base = its_base;
        its->phys_base = res.start;
        its->ite_size = ((readl_relaxed(its_base + GITS_TYPER) >> 4) & 0xf) + 1;
+       its->numa_node = of_node_to_nid(node);
 
        its->cmd_base = kzalloc(ITS_CMD_QUEUE_SZ, GFP_KERNEL);
        if (!its->cmd_base) {
index fb042ba..2c5ba0e 100644 (file)
@@ -155,7 +155,7 @@ static void gic_enable_redist(bool enable)
 
        while (count--) {
                val = readl_relaxed(rbase + GICR_WAKER);
-               if (enable ^ (val & GICR_WAKER_ChildrenAsleep))
+               if (enable ^ (bool)(val & GICR_WAKER_ChildrenAsleep))
                        break;
                cpu_relax();
                udelay(1);
index 3b5e10a..8a4adbe 100644 (file)
@@ -746,6 +746,12 @@ static int gic_irq_domain_alloc(struct irq_domain *d, unsigned int virq,
                /* verify that it doesn't conflict with an IPI irq */
                if (test_bit(spec->hwirq, ipi_resrv))
                        return -EBUSY;
+
+               hwirq = GIC_SHARED_TO_HWIRQ(spec->hwirq);
+
+               return irq_domain_set_hwirq_and_chip(d, virq, hwirq,
+                                                    &gic_level_irq_controller,
+                                                    NULL);
        } else {
                base_hwirq = find_first_bit(ipi_resrv, gic_shared_intrs);
                if (base_hwirq == gic_shared_intrs) {
@@ -867,10 +873,14 @@ static int gic_dev_domain_alloc(struct irq_domain *d, unsigned int virq,
                                                    &gic_level_irq_controller,
                                                    NULL);
                if (ret)
-                       return ret;
+                       goto error;
        }
 
        return 0;
+
+error:
+       irq_domain_free_irqs_parent(d, virq, nr_irqs);
+       return ret;
 }
 
 void gic_dev_domain_free(struct irq_domain *d, unsigned int virq,
index e7155db..73addb4 100644 (file)
@@ -91,7 +91,7 @@ static int pic32_set_type_edge(struct irq_data *data,
        /* set polarity for external interrupts only */
        for (i = 0; i < ARRAY_SIZE(priv->ext_irqs); i++) {
                if (priv->ext_irqs[i] == data->hwirq) {
-                       ret = pic32_set_ext_polarity(i + 1, flow_type);
+                       ret = pic32_set_ext_polarity(i, flow_type);
                        if (ret)
                                return ret;
                }
index 3495d5d..3bce448 100644 (file)
@@ -53,11 +53,12 @@ static void led_timer_function(unsigned long data)
 
        if (!led_cdev->blink_delay_on || !led_cdev->blink_delay_off) {
                led_set_brightness_nosleep(led_cdev, LED_OFF);
+               led_cdev->flags &= ~LED_BLINK_SW;
                return;
        }
 
        if (led_cdev->flags & LED_BLINK_ONESHOT_STOP) {
-               led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP;
+               led_cdev->flags &=  ~(LED_BLINK_ONESHOT_STOP | LED_BLINK_SW);
                return;
        }
 
@@ -151,6 +152,7 @@ static void led_set_software_blink(struct led_classdev *led_cdev,
                return;
        }
 
+       led_cdev->flags |= LED_BLINK_SW;
        mod_timer(&led_cdev->blink_timer, jiffies + 1);
 }
 
@@ -219,6 +221,7 @@ void led_stop_software_blink(struct led_classdev *led_cdev)
        del_timer_sync(&led_cdev->blink_timer);
        led_cdev->blink_delay_on = 0;
        led_cdev->blink_delay_off = 0;
+       led_cdev->flags &= ~LED_BLINK_SW;
 }
 EXPORT_SYMBOL_GPL(led_stop_software_blink);
 
@@ -226,10 +229,10 @@ void led_set_brightness(struct led_classdev *led_cdev,
                        enum led_brightness brightness)
 {
        /*
-        * In case blinking is on delay brightness setting
+        * If software blink is active, delay brightness setting
         * until the next timer tick.
         */
-       if (led_cdev->blink_delay_on || led_cdev->blink_delay_off) {
+       if (led_cdev->flags & LED_BLINK_SW) {
                /*
                 * If we need to disable soft blinking delegate this to the
                 * work queue task to avoid problems in case we are called
index 410c39c..c9f3862 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/sched.h>
 #include <linux/leds.h>
 #include <linux/reboot.h>
+#include <linux/suspend.h>
 #include "../leds.h"
 
 static int panic_heartbeats;
@@ -154,6 +155,30 @@ static struct led_trigger heartbeat_led_trigger = {
        .deactivate = heartbeat_trig_deactivate,
 };
 
+static int heartbeat_pm_notifier(struct notifier_block *nb,
+                                unsigned long pm_event, void *unused)
+{
+       int rc;
+
+       switch (pm_event) {
+       case PM_SUSPEND_PREPARE:
+       case PM_HIBERNATION_PREPARE:
+       case PM_RESTORE_PREPARE:
+               led_trigger_unregister(&heartbeat_led_trigger);
+               break;
+       case PM_POST_SUSPEND:
+       case PM_POST_HIBERNATION:
+       case PM_POST_RESTORE:
+               rc = led_trigger_register(&heartbeat_led_trigger);
+               if (rc)
+                       pr_err("could not re-register heartbeat trigger\n");
+               break;
+       default:
+               break;
+       }
+       return NOTIFY_DONE;
+}
+
 static int heartbeat_reboot_notifier(struct notifier_block *nb,
                                     unsigned long code, void *unused)
 {
@@ -168,6 +193,10 @@ static int heartbeat_panic_notifier(struct notifier_block *nb,
        return NOTIFY_DONE;
 }
 
+static struct notifier_block heartbeat_pm_nb = {
+       .notifier_call = heartbeat_pm_notifier,
+};
+
 static struct notifier_block heartbeat_reboot_nb = {
        .notifier_call = heartbeat_reboot_notifier,
 };
@@ -184,12 +213,14 @@ static int __init heartbeat_trig_init(void)
                atomic_notifier_chain_register(&panic_notifier_list,
                                               &heartbeat_panic_nb);
                register_reboot_notifier(&heartbeat_reboot_nb);
+               register_pm_notifier(&heartbeat_pm_nb);
        }
        return rc;
 }
 
 static void __exit heartbeat_trig_exit(void)
 {
+       unregister_pm_notifier(&heartbeat_pm_nb);
        unregister_reboot_notifier(&heartbeat_reboot_nb);
        atomic_notifier_chain_unregister(&panic_notifier_list,
                                         &heartbeat_panic_nb);
index b73c6e7..6f2c852 100644 (file)
@@ -61,21 +61,36 @@ static int mcb_probe(struct device *dev)
        struct mcb_driver *mdrv = to_mcb_driver(dev->driver);
        struct mcb_device *mdev = to_mcb_device(dev);
        const struct mcb_device_id *found_id;
+       struct module *carrier_mod;
+       int ret;
 
        found_id = mcb_match_id(mdrv->id_table, mdev);
        if (!found_id)
                return -ENODEV;
 
-       return mdrv->probe(mdev, found_id);
+       carrier_mod = mdev->dev.parent->driver->owner;
+       if (!try_module_get(carrier_mod))
+               return -EINVAL;
+
+       get_device(dev);
+       ret = mdrv->probe(mdev, found_id);
+       if (ret)
+               module_put(carrier_mod);
+
+       return ret;
 }
 
 static int mcb_remove(struct device *dev)
 {
        struct mcb_driver *mdrv = to_mcb_driver(dev->driver);
        struct mcb_device *mdev = to_mcb_device(dev);
+       struct module *carrier_mod;
 
        mdrv->remove(mdev);
 
+       carrier_mod = mdev->dev.parent->driver->owner;
+       module_put(carrier_mod);
+
        put_device(&mdev->dev);
 
        return 0;
index d7723ce..c04bc6a 100644 (file)
@@ -1274,8 +1274,6 @@ struct uvc_xu_control_mapping32 {
 static int uvc_v4l2_get_xu_mapping(struct uvc_xu_control_mapping *kp,
                        const struct uvc_xu_control_mapping32 __user *up)
 {
-       struct uvc_menu_info __user *umenus;
-       struct uvc_menu_info __user *kmenus;
        compat_caddr_t p;
 
        if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
@@ -1292,17 +1290,7 @@ static int uvc_v4l2_get_xu_mapping(struct uvc_xu_control_mapping *kp,
 
        if (__get_user(p, &up->menu_info))
                return -EFAULT;
-       umenus = compat_ptr(p);
-       if (!access_ok(VERIFY_READ, umenus, kp->menu_count * sizeof(*umenus)))
-               return -EFAULT;
-
-       kmenus = compat_alloc_user_space(kp->menu_count * sizeof(*kmenus));
-       if (kmenus == NULL)
-               return -EFAULT;
-       kp->menu_info = kmenus;
-
-       if (copy_in_user(kmenus, umenus, kp->menu_count * sizeof(*umenus)))
-               return -EFAULT;
+       kp->menu_info = compat_ptr(p);
 
        return 0;
 }
@@ -1310,10 +1298,6 @@ static int uvc_v4l2_get_xu_mapping(struct uvc_xu_control_mapping *kp,
 static int uvc_v4l2_put_xu_mapping(const struct uvc_xu_control_mapping *kp,
                        struct uvc_xu_control_mapping32 __user *up)
 {
-       struct uvc_menu_info __user *umenus;
-       struct uvc_menu_info __user *kmenus = kp->menu_info;
-       compat_caddr_t p;
-
        if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
            __copy_to_user(up, kp, offsetof(typeof(*up), menu_info)) ||
            __put_user(kp->menu_count, &up->menu_count))
@@ -1322,16 +1306,6 @@ static int uvc_v4l2_put_xu_mapping(const struct uvc_xu_control_mapping *kp,
        if (__clear_user(up->reserved, sizeof(up->reserved)))
                return -EFAULT;
 
-       if (kp->menu_count == 0)
-               return 0;
-
-       if (get_user(p, &up->menu_info))
-               return -EFAULT;
-       umenus = compat_ptr(p);
-
-       if (copy_in_user(umenus, kmenus, kp->menu_count * sizeof(*umenus)))
-               return -EFAULT;
-
        return 0;
 }
 
@@ -1346,8 +1320,6 @@ struct uvc_xu_control_query32 {
 static int uvc_v4l2_get_xu_query(struct uvc_xu_control_query *kp,
                        const struct uvc_xu_control_query32 __user *up)
 {
-       u8 __user *udata;
-       u8 __user *kdata;
        compat_caddr_t p;
 
        if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
@@ -1361,17 +1333,7 @@ static int uvc_v4l2_get_xu_query(struct uvc_xu_control_query *kp,
 
        if (__get_user(p, &up->data))
                return -EFAULT;
-       udata = compat_ptr(p);
-       if (!access_ok(VERIFY_READ, udata, kp->size))
-               return -EFAULT;
-
-       kdata = compat_alloc_user_space(kp->size);
-       if (kdata == NULL)
-               return -EFAULT;
-       kp->data = kdata;
-
-       if (copy_in_user(kdata, udata, kp->size))
-               return -EFAULT;
+       kp->data = compat_ptr(p);
 
        return 0;
 }
@@ -1379,26 +1341,10 @@ static int uvc_v4l2_get_xu_query(struct uvc_xu_control_query *kp,
 static int uvc_v4l2_put_xu_query(const struct uvc_xu_control_query *kp,
                        struct uvc_xu_control_query32 __user *up)
 {
-       u8 __user *udata;
-       u8 __user *kdata = kp->data;
-       compat_caddr_t p;
-
        if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
            __copy_to_user(up, kp, offsetof(typeof(*up), data)))
                return -EFAULT;
 
-       if (kp->size == 0)
-               return 0;
-
-       if (get_user(p, &up->data))
-               return -EFAULT;
-       udata = compat_ptr(p);
-       if (!access_ok(VERIFY_READ, udata, kp->size))
-               return -EFAULT;
-
-       if (copy_in_user(udata, kdata, kp->size))
-               return -EFAULT;
-
        return 0;
 }
 
@@ -1408,47 +1354,44 @@ static int uvc_v4l2_put_xu_query(const struct uvc_xu_control_query *kp,
 static long uvc_v4l2_compat_ioctl32(struct file *file,
                     unsigned int cmd, unsigned long arg)
 {
+       struct uvc_fh *handle = file->private_data;
        union {
                struct uvc_xu_control_mapping xmap;
                struct uvc_xu_control_query xqry;
        } karg;
        void __user *up = compat_ptr(arg);
-       mm_segment_t old_fs;
        long ret;
 
        switch (cmd) {
        case UVCIOC_CTRL_MAP32:
-               cmd = UVCIOC_CTRL_MAP;
                ret = uvc_v4l2_get_xu_mapping(&karg.xmap, up);
+               if (ret)
+                       return ret;
+               ret = uvc_ioctl_ctrl_map(handle->chain, &karg.xmap);
+               if (ret)
+                       return ret;
+               ret = uvc_v4l2_put_xu_mapping(&karg.xmap, up);
+               if (ret)
+                       return ret;
+
                break;
 
        case UVCIOC_CTRL_QUERY32:
-               cmd = UVCIOC_CTRL_QUERY;
                ret = uvc_v4l2_get_xu_query(&karg.xqry, up);
+               if (ret)
+                       return ret;
+               ret = uvc_xu_ctrl_query(handle->chain, &karg.xqry);
+               if (ret)
+                       return ret;
+               ret = uvc_v4l2_put_xu_query(&karg.xqry, up);
+               if (ret)
+                       return ret;
                break;
 
        default:
                return -ENOIOCTLCMD;
        }
 
-       old_fs = get_fs();
-       set_fs(KERNEL_DS);
-       ret = video_ioctl2(file, cmd, (unsigned long)&karg);
-       set_fs(old_fs);
-
-       if (ret < 0)
-               return ret;
-
-       switch (cmd) {
-       case UVCIOC_CTRL_MAP:
-               ret = uvc_v4l2_put_xu_mapping(&karg.xmap, up);
-               break;
-
-       case UVCIOC_CTRL_QUERY:
-               ret = uvc_v4l2_put_xu_query(&karg.xqry, up);
-               break;
-       }
-
        return ret;
 }
 #endif
index ca94bde..8bef433 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Media Controller ancillary functions
  *
- * Copyright (c) 2016 Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+ * Copyright (c) 2016 Mauro Carvalho Chehab <mchehab@kernel.org>
  * Copyright (C) 2016 Shuah Khan <shuahkh@osg.samsung.com>
  * Copyright (C) 2006-2010 Nokia Corporation
  * Copyright (c) 2016 Intel Corporation.
index af4884b..15508df 100644 (file)
@@ -398,7 +398,7 @@ static void gpmc_cs_bool_timings(int cs, const struct gpmc_bool_timings *p)
        gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG4,
                           GPMC_CONFIG4_OEEXTRADELAY, p->oe_extra_delay);
        gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG4,
-                          GPMC_CONFIG4_OEEXTRADELAY, p->we_extra_delay);
+                          GPMC_CONFIG4_WEEXTRADELAY, p->we_extra_delay);
        gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG6,
                           GPMC_CONFIG6_CYCLE2CYCLESAMECSEN,
                           p->cycle2cyclesamecsen);
index eed254d..641c1a5 100644 (file)
@@ -730,7 +730,7 @@ static void mei_cl_wake_all(struct mei_cl *cl)
        /* synchronized under device mutex */
        if (waitqueue_active(&cl->wait)) {
                cl_dbg(dev, cl, "Waking up ctrl write clients!\n");
-               wake_up_interruptible(&cl->wait);
+               wake_up(&cl->wait);
        }
 }
 
index c984321..5d438ad 100644 (file)
@@ -1276,7 +1276,7 @@ static int mmc_select_hs200(struct mmc_card *card)
         * switch to HS200 mode if bus width is set successfully.
         */
        err = mmc_select_bus_width(card);
-       if (!err) {
+       if (err >= 0) {
                val = EXT_CSD_TIMING_HS200 |
                      card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
                err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
@@ -1583,7 +1583,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
        } else if (mmc_card_hs(card)) {
                /* Select the desired bus width optionally */
                err = mmc_select_bus_width(card);
-               if (!err) {
+               if (err >= 0) {
                        err = mmc_select_hs_ddr(card);
                        if (err)
                                goto free_card;
index 7fc8b7a..2ee4c21 100644 (file)
@@ -970,8 +970,8 @@ 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 },
-       [SDXC_CLK_50M_DDR_8BIT] = { .output =  90, .sample = 120 },
+       [SDXC_CLK_50M_DDR]      = { .output =  54, .sample =  36 },
+       [SDXC_CLK_50M_DDR_8BIT] = { .output =  72, .sample =  72 },
 };
 
 static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,
@@ -1129,11 +1129,6 @@ static int sunxi_mmc_probe(struct platform_device *pdev)
                                  MMC_CAP_1_8V_DDR |
                                  MMC_CAP_ERASE | MMC_CAP_SDIO_IRQ;
 
-       /* TODO MMC DDR is not working on A80 */
-       if (of_device_is_compatible(pdev->dev.of_node,
-                                   "allwinner,sun9i-a80-mmc"))
-               mmc->caps &= ~MMC_CAP_1_8V_DDR;
-
        ret = mmc_of_parse(mmc);
        if (ret)
                goto error_free_dma;
index 16baeb5..ef36182 100644 (file)
@@ -1147,11 +1147,17 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
  */
 static struct mtd_info * __init open_mtd_by_chdev(const char *mtd_dev)
 {
-       struct kstat stat;
        int err, minor;
+       struct path path;
+       struct kstat stat;
 
        /* Probably this is an MTD character device node path */
-       err = vfs_stat(mtd_dev, &stat);
+       err = kern_path(mtd_dev, LOOKUP_FOLLOW, &path);
+       if (err)
+               return ERR_PTR(err);
+
+       err = vfs_getattr(&path, &stat);
+       path_put(&path);
        if (err)
                return ERR_PTR(err);
 
@@ -1160,6 +1166,7 @@ static struct mtd_info * __init open_mtd_by_chdev(const char *mtd_dev)
                return ERR_PTR(-EINVAL);
 
        minor = MINOR(stat.rdev);
+
        if (minor & 1)
                /*
                 * Just do not think the "/dev/mtdrX" devices support is need,
index 5780dd1..ebf5172 100644 (file)
@@ -575,6 +575,7 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
        int err, idx = vol_id2idx(ubi, vol_id), new_pnum, data_size, tries = 0;
        struct ubi_volume *vol = ubi->volumes[idx];
        struct ubi_vid_hdr *vid_hdr;
+       uint32_t crc;
 
        vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
        if (!vid_hdr)
@@ -599,14 +600,8 @@ retry:
                goto out_put;
        }
 
-       vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi));
-       err = ubi_io_write_vid_hdr(ubi, new_pnum, vid_hdr);
-       if (err) {
-               up_read(&ubi->fm_eba_sem);
-               goto write_error;
-       }
+       ubi_assert(vid_hdr->vol_type == UBI_VID_DYNAMIC);
 
-       data_size = offset + len;
        mutex_lock(&ubi->buf_mutex);
        memset(ubi->peb_buf + offset, 0xFF, len);
 
@@ -621,6 +616,19 @@ retry:
 
        memcpy(ubi->peb_buf + offset, buf, len);
 
+       data_size = offset + len;
+       crc = crc32(UBI_CRC32_INIT, ubi->peb_buf, data_size);
+       vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi));
+       vid_hdr->copy_flag = 1;
+       vid_hdr->data_size = cpu_to_be32(data_size);
+       vid_hdr->data_crc = cpu_to_be32(crc);
+       err = ubi_io_write_vid_hdr(ubi, new_pnum, vid_hdr);
+       if (err) {
+               mutex_unlock(&ubi->buf_mutex);
+               up_read(&ubi->fm_eba_sem);
+               goto write_error;
+       }
+
        err = ubi_io_write_data(ubi, ubi->peb_buf, new_pnum, 0, data_size);
        if (err) {
                mutex_unlock(&ubi->buf_mutex);
index 348dbbc..a9e2cef 100644 (file)
@@ -302,6 +302,7 @@ EXPORT_SYMBOL_GPL(ubi_open_volume_nm);
 struct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode)
 {
        int error, ubi_num, vol_id;
+       struct path path;
        struct kstat stat;
 
        dbg_gen("open volume %s, mode %d", pathname, mode);
@@ -309,7 +310,12 @@ struct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode)
        if (!pathname || !*pathname)
                return ERR_PTR(-EINVAL);
 
-       error = vfs_stat(pathname, &stat);
+       error = kern_path(pathname, LOOKUP_FOLLOW, &path);
+       if (error)
+               return ERR_PTR(error);
+
+       error = vfs_getattr(&path, &stat);
+       path_put(&path);
        if (error)
                return ERR_PTR(error);
 
index 16419f5..058460b 100644 (file)
@@ -141,7 +141,7 @@ int arc_mdio_probe(struct arc_emac_priv *priv)
        priv->bus = bus;
        bus->priv = priv;
        bus->parent = priv->dev;
-       bus->name = "Synopsys MII Bus",
+       bus->name = "Synopsys MII Bus";
        bus->read = &arc_mdio_read;
        bus->write = &arc_mdio_write;
        bus->reset = &arc_mdio_reset;
index 8fc93c5..d02c424 100644 (file)
@@ -96,6 +96,10 @@ struct alx_priv {
        unsigned int rx_ringsz;
        unsigned int rxbuf_size;
 
+       struct page  *rx_page;
+       unsigned int rx_page_offset;
+       unsigned int rx_frag_size;
+
        struct napi_struct napi;
        struct alx_tx_queue txq;
        struct alx_rx_queue rxq;
index 9fe8b5e..c98acdc 100644 (file)
@@ -70,6 +70,35 @@ static void alx_free_txbuf(struct alx_priv *alx, int entry)
        }
 }
 
+static struct sk_buff *alx_alloc_skb(struct alx_priv *alx, gfp_t gfp)
+{
+       struct sk_buff *skb;
+       struct page *page;
+
+       if (alx->rx_frag_size > PAGE_SIZE)
+               return __netdev_alloc_skb(alx->dev, alx->rxbuf_size, gfp);
+
+       page = alx->rx_page;
+       if (!page) {
+               alx->rx_page = page = alloc_page(gfp);
+               if (unlikely(!page))
+                       return NULL;
+               alx->rx_page_offset = 0;
+       }
+
+       skb = build_skb(page_address(page) + alx->rx_page_offset,
+                       alx->rx_frag_size);
+       if (likely(skb)) {
+               alx->rx_page_offset += alx->rx_frag_size;
+               if (alx->rx_page_offset >= PAGE_SIZE)
+                       alx->rx_page = NULL;
+               else
+                       get_page(page);
+       }
+       return skb;
+}
+
+
 static int alx_refill_rx_ring(struct alx_priv *alx, gfp_t gfp)
 {
        struct alx_rx_queue *rxq = &alx->rxq;
@@ -86,7 +115,7 @@ static int alx_refill_rx_ring(struct alx_priv *alx, gfp_t gfp)
        while (!cur_buf->skb && next != rxq->read_idx) {
                struct alx_rfd *rfd = &rxq->rfd[cur];
 
-               skb = __netdev_alloc_skb(alx->dev, alx->rxbuf_size, gfp);
+               skb = alx_alloc_skb(alx, gfp);
                if (!skb)
                        break;
                dma = dma_map_single(&alx->hw.pdev->dev,
@@ -124,6 +153,7 @@ static int alx_refill_rx_ring(struct alx_priv *alx, gfp_t gfp)
                alx_write_mem16(&alx->hw, ALX_RFD_PIDX, cur);
        }
 
+
        return count;
 }
 
@@ -592,6 +622,11 @@ static void alx_free_rings(struct alx_priv *alx)
        kfree(alx->txq.bufs);
        kfree(alx->rxq.bufs);
 
+       if (alx->rx_page) {
+               put_page(alx->rx_page);
+               alx->rx_page = NULL;
+       }
+
        dma_free_coherent(&alx->hw.pdev->dev,
                          alx->descmem.size,
                          alx->descmem.virt,
@@ -646,6 +681,7 @@ static int alx_request_irq(struct alx_priv *alx)
                                  alx->dev->name, alx);
                if (!err)
                        goto out;
+
                /* fall back to legacy interrupt */
                pci_disable_msi(alx->hw.pdev);
        }
@@ -689,6 +725,7 @@ static int alx_init_sw(struct alx_priv *alx)
        struct pci_dev *pdev = alx->hw.pdev;
        struct alx_hw *hw = &alx->hw;
        int err;
+       unsigned int head_size;
 
        err = alx_identify_hw(alx);
        if (err) {
@@ -704,7 +741,12 @@ static int alx_init_sw(struct alx_priv *alx)
 
        hw->smb_timer = 400;
        hw->mtu = alx->dev->mtu;
+
        alx->rxbuf_size = ALX_MAX_FRAME_LEN(hw->mtu);
+       head_size = SKB_DATA_ALIGN(alx->rxbuf_size + NET_SKB_PAD) +
+                   SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+       alx->rx_frag_size = roundup_pow_of_two(head_size);
+
        alx->tx_ringsz = 256;
        alx->rx_ringsz = 512;
        hw->imt = 200;
@@ -806,6 +848,7 @@ static int alx_change_mtu(struct net_device *netdev, int mtu)
 {
        struct alx_priv *alx = netdev_priv(netdev);
        int max_frame = ALX_MAX_FRAME_LEN(mtu);
+       unsigned int head_size;
 
        if ((max_frame < ALX_MIN_FRAME_SIZE) ||
            (max_frame > ALX_MAX_FRAME_SIZE))
@@ -817,6 +860,9 @@ static int alx_change_mtu(struct net_device *netdev, int mtu)
        netdev->mtu = mtu;
        alx->hw.mtu = mtu;
        alx->rxbuf_size = max(max_frame, ALX_DEF_RXBUF_SIZE);
+       head_size = SKB_DATA_ALIGN(alx->rxbuf_size + NET_SKB_PAD) +
+                   SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+       alx->rx_frag_size = roundup_pow_of_two(head_size);
        netdev_update_features(netdev);
        if (netif_running(netdev))
                alx_reinit(alx);
index 0a5b770..a59d55e 100644 (file)
@@ -12895,52 +12895,71 @@ static int __bnx2x_vlan_configure_vid(struct bnx2x *bp, u16 vid, bool add)
        return rc;
 }
 
-int bnx2x_vlan_reconfigure_vid(struct bnx2x *bp)
+static int bnx2x_vlan_configure_vid_list(struct bnx2x *bp)
 {
        struct bnx2x_vlan_entry *vlan;
        int rc = 0;
 
-       if (!bp->vlan_cnt) {
-               DP(NETIF_MSG_IFUP, "No need to re-configure vlan filters\n");
-               return 0;
-       }
-
+       /* Configure all non-configured entries */
        list_for_each_entry(vlan, &bp->vlan_reg, link) {
-               /* Prepare for cleanup in case of errors */
-               if (rc) {
-                       vlan->hw = false;
-                       continue;
-               }
-
-               if (!vlan->hw)
+               if (vlan->hw)
                        continue;
 
-               DP(NETIF_MSG_IFUP, "Re-configuring vlan 0x%04x\n", vlan->vid);
+               if (bp->vlan_cnt >= bp->vlan_credit)
+                       return -ENOBUFS;
 
                rc = __bnx2x_vlan_configure_vid(bp, vlan->vid, true);
                if (rc) {
-                       BNX2X_ERR("Unable to configure VLAN %d\n", vlan->vid);
-                       vlan->hw = false;
-                       rc = -EINVAL;
-                       continue;
+                       BNX2X_ERR("Unable to config VLAN %d\n", vlan->vid);
+                       return rc;
                }
+
+               DP(NETIF_MSG_IFUP, "HW configured for VLAN %d\n", vlan->vid);
+               vlan->hw = true;
+               bp->vlan_cnt++;
        }
 
-       return rc;
+       return 0;
+}
+
+static void bnx2x_vlan_configure(struct bnx2x *bp, bool set_rx_mode)
+{
+       bool need_accept_any_vlan;
+
+       need_accept_any_vlan = !!bnx2x_vlan_configure_vid_list(bp);
+
+       if (bp->accept_any_vlan != need_accept_any_vlan) {
+               bp->accept_any_vlan = need_accept_any_vlan;
+               DP(NETIF_MSG_IFUP, "Accept all VLAN %s\n",
+                  bp->accept_any_vlan ? "raised" : "cleared");
+               if (set_rx_mode) {
+                       if (IS_PF(bp))
+                               bnx2x_set_rx_mode_inner(bp);
+                       else
+                               bnx2x_vfpf_storm_rx_mode(bp);
+               }
+       }
+}
+
+int bnx2x_vlan_reconfigure_vid(struct bnx2x *bp)
+{
+       struct bnx2x_vlan_entry *vlan;
+
+       /* The hw forgot all entries after reload */
+       list_for_each_entry(vlan, &bp->vlan_reg, link)
+               vlan->hw = false;
+       bp->vlan_cnt = 0;
+
+       /* Don't set rx mode here. Our caller will do it. */
+       bnx2x_vlan_configure(bp, false);
+
+       return 0;
 }
 
 static int bnx2x_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid)
 {
        struct bnx2x *bp = netdev_priv(dev);
        struct bnx2x_vlan_entry *vlan;
-       bool hw = false;
-       int rc = 0;
-
-       if (!netif_running(bp->dev)) {
-               DP(NETIF_MSG_IFUP,
-                  "Ignoring VLAN configuration the interface is down\n");
-               return -EFAULT;
-       }
 
        DP(NETIF_MSG_IFUP, "Adding VLAN %d\n", vid);
 
@@ -12948,93 +12967,47 @@ static int bnx2x_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid)
        if (!vlan)
                return -ENOMEM;
 
-       bp->vlan_cnt++;
-       if (bp->vlan_cnt > bp->vlan_credit && !bp->accept_any_vlan) {
-               DP(NETIF_MSG_IFUP, "Accept all VLAN raised\n");
-               bp->accept_any_vlan = true;
-               if (IS_PF(bp))
-                       bnx2x_set_rx_mode_inner(bp);
-               else
-                       bnx2x_vfpf_storm_rx_mode(bp);
-       } else if (bp->vlan_cnt <= bp->vlan_credit) {
-               rc = __bnx2x_vlan_configure_vid(bp, vid, true);
-               hw = true;
-       }
-
        vlan->vid = vid;
-       vlan->hw = hw;
+       vlan->hw = false;
+       list_add_tail(&vlan->link, &bp->vlan_reg);
 
-       if (!rc) {
-               list_add(&vlan->link, &bp->vlan_reg);
-       } else {
-               bp->vlan_cnt--;
-               kfree(vlan);
-       }
-
-       DP(NETIF_MSG_IFUP, "Adding VLAN result %d\n", rc);
+       if (netif_running(dev))
+               bnx2x_vlan_configure(bp, true);
 
-       return rc;
+       return 0;
 }
 
 static int bnx2x_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, u16 vid)
 {
        struct bnx2x *bp = netdev_priv(dev);
        struct bnx2x_vlan_entry *vlan;
+       bool found = false;
        int rc = 0;
 
-       if (!netif_running(bp->dev)) {
-               DP(NETIF_MSG_IFUP,
-                  "Ignoring VLAN configuration the interface is down\n");
-               return -EFAULT;
-       }
-
        DP(NETIF_MSG_IFUP, "Removing VLAN %d\n", vid);
 
-       if (!bp->vlan_cnt) {
-               BNX2X_ERR("Unable to kill VLAN %d\n", vid);
-               return -EINVAL;
-       }
-
        list_for_each_entry(vlan, &bp->vlan_reg, link)
-               if (vlan->vid == vid)
+               if (vlan->vid == vid) {
+                       found = true;
                        break;
+               }
 
-       if (vlan->vid != vid) {
+       if (!found) {
                BNX2X_ERR("Unable to kill VLAN %d - not found\n", vid);
                return -EINVAL;
        }
 
-       if (vlan->hw)
+       if (netif_running(dev) && vlan->hw) {
                rc = __bnx2x_vlan_configure_vid(bp, vid, false);
+               DP(NETIF_MSG_IFUP, "HW deconfigured for VLAN %d\n", vid);
+               bp->vlan_cnt--;
+       }
 
        list_del(&vlan->link);
        kfree(vlan);
 
-       bp->vlan_cnt--;
-
-       if (bp->vlan_cnt <= bp->vlan_credit && bp->accept_any_vlan) {
-               /* Configure all non-configured entries */
-               list_for_each_entry(vlan, &bp->vlan_reg, link) {
-                       if (vlan->hw)
-                               continue;
-
-                       rc = __bnx2x_vlan_configure_vid(bp, vlan->vid, true);
-                       if (rc) {
-                               BNX2X_ERR("Unable to config VLAN %d\n",
-                                         vlan->vid);
-                               continue;
-                       }
-                       DP(NETIF_MSG_IFUP, "HW configured for VLAN %d\n",
-                          vlan->vid);
-                       vlan->hw = true;
-               }
-               DP(NETIF_MSG_IFUP, "Accept all VLAN Removed\n");
-               bp->accept_any_vlan = false;
-               if (IS_PF(bp))
-                       bnx2x_set_rx_mode_inner(bp);
-               else
-                       bnx2x_vfpf_storm_rx_mode(bp);
-       }
+       if (netif_running(dev))
+               bnx2x_vlan_configure(bp, true);
 
        DP(NETIF_MSG_IFUP, "Removing VLAN result %d\n", rc);
 
@@ -13941,14 +13914,14 @@ static int bnx2x_init_one(struct pci_dev *pdev,
                bp->doorbells = bnx2x_vf_doorbells(bp);
                rc = bnx2x_vf_pci_alloc(bp);
                if (rc)
-                       goto init_one_exit;
+                       goto init_one_freemem;
        } else {
                doorbell_size = BNX2X_L2_MAX_CID(bp) * (1 << BNX2X_DB_SHIFT);
                if (doorbell_size > pci_resource_len(pdev, 2)) {
                        dev_err(&bp->pdev->dev,
                                "Cannot map doorbells, bar size too small, aborting\n");
                        rc = -ENOMEM;
-                       goto init_one_exit;
+                       goto init_one_freemem;
                }
                bp->doorbells = ioremap_nocache(pci_resource_start(pdev, 2),
                                                doorbell_size);
@@ -13957,19 +13930,19 @@ static int bnx2x_init_one(struct pci_dev *pdev,
                dev_err(&bp->pdev->dev,
                        "Cannot map doorbell space, aborting\n");
                rc = -ENOMEM;
-               goto init_one_exit;
+               goto init_one_freemem;
        }
 
        if (IS_VF(bp)) {
                rc = bnx2x_vfpf_acquire(bp, tx_count, rx_count);
                if (rc)
-                       goto init_one_exit;
+                       goto init_one_freemem;
        }
 
        /* Enable SRIOV if capability found in configuration space */
        rc = bnx2x_iov_init_one(bp, int_mode, BNX2X_MAX_NUM_OF_VFS);
        if (rc)
-               goto init_one_exit;
+               goto init_one_freemem;
 
        /* calc qm_cid_count */
        bp->qm_cid_count = bnx2x_set_qm_cid_count(bp);
@@ -13988,7 +13961,7 @@ static int bnx2x_init_one(struct pci_dev *pdev,
        rc = bnx2x_set_int_mode(bp);
        if (rc) {
                dev_err(&pdev->dev, "Cannot set interrupts\n");
-               goto init_one_exit;
+               goto init_one_freemem;
        }
        BNX2X_DEV_INFO("set interrupts successfully\n");
 
@@ -13996,7 +13969,7 @@ static int bnx2x_init_one(struct pci_dev *pdev,
        rc = register_netdev(dev);
        if (rc) {
                dev_err(&pdev->dev, "Cannot register net device\n");
-               goto init_one_exit;
+               goto init_one_freemem;
        }
        BNX2X_DEV_INFO("device name after netdev register %s\n", dev->name);
 
@@ -14029,6 +14002,9 @@ static int bnx2x_init_one(struct pci_dev *pdev,
 
        return 0;
 
+init_one_freemem:
+       bnx2x_free_mem_bp(bp);
+
 init_one_exit:
        bnx2x_disable_pcie_error_reporting(bp);
 
index 72a2eff..c777cde 100644 (file)
@@ -286,7 +286,9 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        cpu_to_le32(DB_KEY_TX_PUSH | DB_LONG_TX_PUSH | prod);
                txr->tx_prod = prod;
 
+               tx_buf->is_push = 1;
                netdev_tx_sent_queue(txq, skb->len);
+               wmb();  /* Sync is_push and byte queue before pushing data */
 
                push_len = (length + sizeof(*tx_push) + 7) / 8;
                if (push_len > 16) {
@@ -298,7 +300,6 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
                                         push_len);
                }
 
-               tx_buf->is_push = 1;
                goto tx_done;
        }
 
@@ -1112,19 +1113,13 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
        if (tpa_info->hash_type != PKT_HASH_TYPE_NONE)
                skb_set_hash(skb, tpa_info->rss_hash, tpa_info->hash_type);
 
-       if (tpa_info->flags2 & RX_CMP_FLAGS2_META_FORMAT_VLAN) {
-               netdev_features_t features = skb->dev->features;
+       if ((tpa_info->flags2 & RX_CMP_FLAGS2_META_FORMAT_VLAN) &&
+           (skb->dev->features & NETIF_F_HW_VLAN_CTAG_RX)) {
                u16 vlan_proto = tpa_info->metadata >>
                        RX_CMP_FLAGS2_METADATA_TPID_SFT;
+               u16 vtag = tpa_info->metadata & RX_CMP_FLAGS2_METADATA_VID_MASK;
 
-               if (((features & NETIF_F_HW_VLAN_CTAG_RX) &&
-                    vlan_proto == ETH_P_8021Q) ||
-                   ((features & NETIF_F_HW_VLAN_STAG_RX) &&
-                    vlan_proto == ETH_P_8021AD)) {
-                       __vlan_hwaccel_put_tag(skb, htons(vlan_proto),
-                                              tpa_info->metadata &
-                                              RX_CMP_FLAGS2_METADATA_VID_MASK);
-               }
+               __vlan_hwaccel_put_tag(skb, htons(vlan_proto), vtag);
        }
 
        skb_checksum_none_assert(skb);
@@ -1277,19 +1272,14 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_napi *bnapi, u32 *raw_cons,
 
        skb->protocol = eth_type_trans(skb, dev);
 
-       if (rxcmp1->rx_cmp_flags2 &
-           cpu_to_le32(RX_CMP_FLAGS2_META_FORMAT_VLAN)) {
-               netdev_features_t features = skb->dev->features;
+       if ((rxcmp1->rx_cmp_flags2 &
+            cpu_to_le32(RX_CMP_FLAGS2_META_FORMAT_VLAN)) &&
+           (skb->dev->features & NETIF_F_HW_VLAN_CTAG_RX)) {
                u32 meta_data = le32_to_cpu(rxcmp1->rx_cmp_meta_data);
+               u16 vtag = meta_data & RX_CMP_FLAGS2_METADATA_VID_MASK;
                u16 vlan_proto = meta_data >> RX_CMP_FLAGS2_METADATA_TPID_SFT;
 
-               if (((features & NETIF_F_HW_VLAN_CTAG_RX) &&
-                    vlan_proto == ETH_P_8021Q) ||
-                   ((features & NETIF_F_HW_VLAN_STAG_RX) &&
-                    vlan_proto == ETH_P_8021AD))
-                       __vlan_hwaccel_put_tag(skb, htons(vlan_proto),
-                                              meta_data &
-                                              RX_CMP_FLAGS2_METADATA_VID_MASK);
+               __vlan_hwaccel_put_tag(skb, htons(vlan_proto), vtag);
        }
 
        skb_checksum_none_assert(skb);
@@ -5466,6 +5456,20 @@ static netdev_features_t bnxt_fix_features(struct net_device *dev,
 
        if (!bnxt_rfs_capable(bp))
                features &= ~NETIF_F_NTUPLE;
+
+       /* Both CTAG and STAG VLAN accelaration on the RX side have to be
+        * turned on or off together.
+        */
+       if ((features & (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX)) !=
+           (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX)) {
+               if (dev->features & NETIF_F_HW_VLAN_CTAG_RX)
+                       features &= ~(NETIF_F_HW_VLAN_CTAG_RX |
+                                     NETIF_F_HW_VLAN_STAG_RX);
+               else
+                       features |= NETIF_F_HW_VLAN_CTAG_RX |
+                                   NETIF_F_HW_VLAN_STAG_RX;
+       }
+
        return features;
 }
 
index a2cdfc1..50812a1 100644 (file)
@@ -144,6 +144,7 @@ CH_PCI_DEVICE_ID_TABLE_DEFINE_BEGIN
        CH_PCI_ID_TABLE_FENTRY(0x5015), /* T502-bt */
        CH_PCI_ID_TABLE_FENTRY(0x5016), /* T580-OCP-SO */
        CH_PCI_ID_TABLE_FENTRY(0x5017), /* T520-OCP-SO */
+       CH_PCI_ID_TABLE_FENTRY(0x5018), /* T540-BT */
        CH_PCI_ID_TABLE_FENTRY(0x5080), /* Custom T540-cr */
        CH_PCI_ID_TABLE_FENTRY(0x5081), /* Custom T540-LL-cr */
        CH_PCI_ID_TABLE_FENTRY(0x5082), /* Custom T504-cr */
index 41b0106..4edb98c 100644 (file)
@@ -1195,7 +1195,7 @@ static int ethoc_probe(struct platform_device *pdev)
        priv->mdio = mdiobus_alloc();
        if (!priv->mdio) {
                ret = -ENOMEM;
-               goto free;
+               goto free2;
        }
 
        priv->mdio->name = "ethoc-mdio";
@@ -1208,7 +1208,7 @@ static int ethoc_probe(struct platform_device *pdev)
        ret = mdiobus_register(priv->mdio);
        if (ret) {
                dev_err(&netdev->dev, "failed to register MDIO bus\n");
-               goto free;
+               goto free2;
        }
 
        ret = ethoc_mdio_probe(netdev);
@@ -1241,9 +1241,10 @@ error2:
 error:
        mdiobus_unregister(priv->mdio);
        mdiobus_free(priv->mdio);
-free:
+free2:
        if (priv->clk)
                clk_disable_unprepare(priv->clk);
+free:
        free_netdev(netdev);
 out:
        return ret;
index 085f912..06f0317 100644 (file)
@@ -205,8 +205,10 @@ static int nps_enet_poll(struct napi_struct *napi, int budget)
                 * re-adding ourselves to the poll list.
                 */
 
-               if (priv->tx_skb && !tx_ctrl_ct)
+               if (priv->tx_skb && !tx_ctrl_ct) {
+                       nps_enet_reg_set(priv, NPS_ENET_REG_BUF_INT_ENABLE, 0);
                        napi_reschedule(napi);
+               }
        }
 
        return work_done;
index ca2cccc..fea0f33 100644 (file)
@@ -1197,10 +1197,8 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
                                         fec16_to_cpu(bdp->cbd_datlen),
                                         DMA_TO_DEVICE);
                bdp->cbd_bufaddr = cpu_to_fec32(0);
-               if (!skb) {
-                       bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
-                       continue;
-               }
+               if (!skb)
+                       goto skb_done;
 
                /* Check for errors. */
                if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC |
@@ -1239,7 +1237,7 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
 
                /* Free the sk buffer associated with this last transmit */
                dev_kfree_skb_any(skb);
-
+skb_done:
                /* Make sure the update to bdp and tx_skbuff are performed
                 * before dirty_tx
                 */
@@ -2418,24 +2416,24 @@ fec_enet_set_coalesce(struct net_device *ndev, struct ethtool_coalesce *ec)
                return -EOPNOTSUPP;
 
        if (ec->rx_max_coalesced_frames > 255) {
-               pr_err("Rx coalesced frames exceed hardware limiation");
+               pr_err("Rx coalesced frames exceed hardware limitation\n");
                return -EINVAL;
        }
 
        if (ec->tx_max_coalesced_frames > 255) {
-               pr_err("Tx coalesced frame exceed hardware limiation");
+               pr_err("Tx coalesced frame exceed hardware limitation\n");
                return -EINVAL;
        }
 
        cycle = fec_enet_us_to_itr_clock(ndev, fep->rx_time_itr);
        if (cycle > 0xFFFF) {
-               pr_err("Rx coalesed usec exceeed hardware limiation");
+               pr_err("Rx coalesced usec exceed hardware limitation\n");
                return -EINVAL;
        }
 
        cycle = fec_enet_us_to_itr_clock(ndev, fep->tx_time_itr);
        if (cycle > 0xFFFF) {
-               pr_err("Rx coalesed usec exceeed hardware limiation");
+               pr_err("Rx coalesced usec exceed hardware limitation\n");
                return -EINVAL;
        }
 
index 7615e06..2e6785b 100644 (file)
@@ -2440,7 +2440,8 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
                                                 tx_queue->tx_ring_size);
 
        if (likely(!nr_frags)) {
-               lstatus |= BD_LFLAG(TXBD_LAST | TXBD_INTERRUPT);
+               if (likely(!do_tstamp))
+                       lstatus |= BD_LFLAG(TXBD_LAST | TXBD_INTERRUPT);
        } else {
                u32 lstatus_start = lstatus;
 
index 3d746c8..67a648c 100644 (file)
@@ -46,7 +46,6 @@ static u32 hns_nic_get_link(struct net_device *net_dev)
        u32 link_stat = priv->link;
        struct hnae_handle *h;
 
-       assert(priv && priv->ae_handle);
        h = priv->ae_handle;
 
        if (priv->phy) {
@@ -646,8 +645,6 @@ static void hns_nic_get_drvinfo(struct net_device *net_dev,
 {
        struct hns_nic_priv *priv = netdev_priv(net_dev);
 
-       assert(priv);
-
        strncpy(drvinfo->version, HNAE_DRIVER_VERSION,
                sizeof(drvinfo->version));
        drvinfo->version[sizeof(drvinfo->version) - 1] = '\0';
@@ -720,8 +717,6 @@ static int hns_set_pauseparam(struct net_device *net_dev,
        struct hnae_handle *h;
        struct hnae_ae_ops *ops;
 
-       assert(priv || priv->ae_handle);
-
        h = priv->ae_handle;
        ops = h->dev->ops;
 
@@ -780,8 +775,6 @@ static int hns_set_coalesce(struct net_device *net_dev,
        struct hnae_ae_ops *ops;
        int ret;
 
-       assert(priv || priv->ae_handle);
-
        ops = priv->ae_handle->dev->ops;
 
        if (ec->tx_coalesce_usecs != ec->rx_coalesce_usecs)
@@ -1111,8 +1104,6 @@ void hns_get_regs(struct net_device *net_dev, struct ethtool_regs *cmd,
        struct hns_nic_priv *priv = netdev_priv(net_dev);
        struct hnae_ae_ops *ops;
 
-       assert(priv || priv->ae_handle);
-
        ops = priv->ae_handle->dev->ops;
 
        cmd->version = HNS_CHIP_VERSION;
@@ -1135,8 +1126,6 @@ static int hns_get_regs_len(struct net_device *net_dev)
        struct hns_nic_priv *priv = netdev_priv(net_dev);
        struct hnae_ae_ops *ops;
 
-       assert(priv || priv->ae_handle);
-
        ops = priv->ae_handle->dev->ops;
        if (!ops->get_regs_len) {
                netdev_err(net_dev, "ops->get_regs_len is null!\n");
index 01fccec..466939f 100644 (file)
@@ -189,6 +189,7 @@ struct mvneta_bm_pool *mvneta_bm_pool_use(struct mvneta_bm *priv, u8 pool_id,
                        SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
                hwbm_pool->construct = mvneta_bm_construct;
                hwbm_pool->priv = new_pool;
+               spin_lock_init(&hwbm_pool->lock);
 
                /* Create new pool */
                err = mvneta_bm_pool_create(priv, new_pool);
index c984462..4763252 100644 (file)
@@ -133,6 +133,8 @@ static int mtk_mdio_read(struct mii_bus *bus, int phy_addr, int phy_reg)
 static void mtk_phy_link_adjust(struct net_device *dev)
 {
        struct mtk_mac *mac = netdev_priv(dev);
+       u16 lcl_adv = 0, rmt_adv = 0;
+       u8 flowctrl;
        u32 mcr = MAC_MCR_MAX_RX_1536 | MAC_MCR_IPG_CFG |
                  MAC_MCR_FORCE_MODE | MAC_MCR_TX_EN |
                  MAC_MCR_RX_EN | MAC_MCR_BACKOFF_EN |
@@ -150,11 +152,30 @@ static void mtk_phy_link_adjust(struct net_device *dev)
        if (mac->phy_dev->link)
                mcr |= MAC_MCR_FORCE_LINK;
 
-       if (mac->phy_dev->duplex)
+       if (mac->phy_dev->duplex) {
                mcr |= MAC_MCR_FORCE_DPX;
 
-       if (mac->phy_dev->pause)
-               mcr |= MAC_MCR_FORCE_RX_FC | MAC_MCR_FORCE_TX_FC;
+               if (mac->phy_dev->pause)
+                       rmt_adv = LPA_PAUSE_CAP;
+               if (mac->phy_dev->asym_pause)
+                       rmt_adv |= LPA_PAUSE_ASYM;
+
+               if (mac->phy_dev->advertising & ADVERTISED_Pause)
+                       lcl_adv |= ADVERTISE_PAUSE_CAP;
+               if (mac->phy_dev->advertising & ADVERTISED_Asym_Pause)
+                       lcl_adv |= ADVERTISE_PAUSE_ASYM;
+
+               flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv);
+
+               if (flowctrl & FLOW_CTRL_TX)
+                       mcr |= MAC_MCR_FORCE_TX_FC;
+               if (flowctrl & FLOW_CTRL_RX)
+                       mcr |= MAC_MCR_FORCE_RX_FC;
+
+               netif_dbg(mac->hw, link, dev, "rx pause %s, tx pause %s\n",
+                         flowctrl & FLOW_CTRL_RX ? "enabled" : "disabled",
+                         flowctrl & FLOW_CTRL_TX ? "enabled" : "disabled");
+       }
 
        mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
 
@@ -208,10 +229,16 @@ static int mtk_phy_connect(struct mtk_mac *mac)
        u32 val, ge_mode;
 
        np = of_parse_phandle(mac->of_node, "phy-handle", 0);
+       if (!np && of_phy_is_fixed_link(mac->of_node))
+               if (!of_phy_register_fixed_link(mac->of_node))
+                       np = of_node_get(mac->of_node);
        if (!np)
                return -ENODEV;
 
        switch (of_get_phy_mode(np)) {
+       case PHY_INTERFACE_MODE_RGMII_TXID:
+       case PHY_INTERFACE_MODE_RGMII_RXID:
+       case PHY_INTERFACE_MODE_RGMII_ID:
        case PHY_INTERFACE_MODE_RGMII:
                ge_mode = 0;
                break;
@@ -236,7 +263,8 @@ static int mtk_phy_connect(struct mtk_mac *mac)
        mac->phy_dev->autoneg = AUTONEG_ENABLE;
        mac->phy_dev->speed = 0;
        mac->phy_dev->duplex = 0;
-       mac->phy_dev->supported &= PHY_BASIC_FEATURES;
+       mac->phy_dev->supported &= PHY_GBIT_FEATURES | SUPPORTED_Pause |
+                                  SUPPORTED_Asym_Pause;
        mac->phy_dev->advertising = mac->phy_dev->supported |
                                    ADVERTISED_Autoneg;
        phy_start_aneg(mac->phy_dev);
@@ -280,7 +308,7 @@ static int mtk_mdio_init(struct mtk_eth *eth)
        return 0;
 
 err_free_bus:
-       kfree(eth->mii_bus);
+       mdiobus_free(eth->mii_bus);
 
 err_put_node:
        of_node_put(mii_np);
@@ -295,7 +323,7 @@ static void mtk_mdio_cleanup(struct mtk_eth *eth)
 
        mdiobus_unregister(eth->mii_bus);
        of_node_put(eth->mii_bus->dev.of_node);
-       kfree(eth->mii_bus);
+       mdiobus_free(eth->mii_bus);
 }
 
 static inline void mtk_irq_disable(struct mtk_eth *eth, u32 mask)
index c761194..fc95aff 100644 (file)
@@ -362,7 +362,7 @@ static void mlx4_en_get_ethtool_stats(struct net_device *dev,
 
        for (i = 0; i < NUM_MAIN_STATS; i++, bitmap_iterator_inc(&it))
                if (bitmap_iterator_test(&it))
-                       data[index++] = ((unsigned long *)&priv->stats)[i];
+                       data[index++] = ((unsigned long *)&dev->stats)[i];
 
        for (i = 0; i < NUM_PORT_STATS; i++, bitmap_iterator_inc(&it))
                if (bitmap_iterator_test(&it))
index 92e0624..19ceced 100644 (file)
@@ -1296,15 +1296,16 @@ static void mlx4_en_tx_timeout(struct net_device *dev)
 }
 
 
-static struct net_device_stats *mlx4_en_get_stats(struct net_device *dev)
+static struct rtnl_link_stats64 *
+mlx4_en_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
 {
        struct mlx4_en_priv *priv = netdev_priv(dev);
 
        spin_lock_bh(&priv->stats_lock);
-       memcpy(&priv->ret_stats, &priv->stats, sizeof(priv->stats));
+       netdev_stats_to_stats64(stats, &dev->stats);
        spin_unlock_bh(&priv->stats_lock);
 
-       return &priv->ret_stats;
+       return stats;
 }
 
 static void mlx4_en_set_default_moderation(struct mlx4_en_priv *priv)
@@ -1876,7 +1877,6 @@ static void mlx4_en_clear_stats(struct net_device *dev)
        if (mlx4_en_DUMP_ETH_STATS(mdev, priv->port, 1))
                en_dbg(HW, priv, "Failed dumping statistics\n");
 
-       memset(&priv->stats, 0, sizeof(priv->stats));
        memset(&priv->pstats, 0, sizeof(priv->pstats));
        memset(&priv->pkstats, 0, sizeof(priv->pkstats));
        memset(&priv->port_stats, 0, sizeof(priv->port_stats));
@@ -1892,6 +1892,11 @@ static void mlx4_en_clear_stats(struct net_device *dev)
                priv->tx_ring[i]->bytes = 0;
                priv->tx_ring[i]->packets = 0;
                priv->tx_ring[i]->tx_csum = 0;
+               priv->tx_ring[i]->tx_dropped = 0;
+               priv->tx_ring[i]->queue_stopped = 0;
+               priv->tx_ring[i]->wake_queue = 0;
+               priv->tx_ring[i]->tso_packets = 0;
+               priv->tx_ring[i]->xmit_more = 0;
        }
        for (i = 0; i < priv->rx_ring_num; i++) {
                priv->rx_ring[i]->bytes = 0;
@@ -2482,7 +2487,7 @@ static const struct net_device_ops mlx4_netdev_ops = {
        .ndo_stop               = mlx4_en_close,
        .ndo_start_xmit         = mlx4_en_xmit,
        .ndo_select_queue       = mlx4_en_select_queue,
-       .ndo_get_stats          = mlx4_en_get_stats,
+       .ndo_get_stats64        = mlx4_en_get_stats64,
        .ndo_set_rx_mode        = mlx4_en_set_rx_mode,
        .ndo_set_mac_address    = mlx4_en_set_mac,
        .ndo_validate_addr      = eth_validate_addr,
@@ -2514,7 +2519,7 @@ static const struct net_device_ops mlx4_netdev_ops_master = {
        .ndo_stop               = mlx4_en_close,
        .ndo_start_xmit         = mlx4_en_xmit,
        .ndo_select_queue       = mlx4_en_select_queue,
-       .ndo_get_stats          = mlx4_en_get_stats,
+       .ndo_get_stats64        = mlx4_en_get_stats64,
        .ndo_set_rx_mode        = mlx4_en_set_rx_mode,
        .ndo_set_mac_address    = mlx4_en_set_mac,
        .ndo_validate_addr      = eth_validate_addr,
index 20b6c2e..5aa8b75 100644 (file)
@@ -152,8 +152,9 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
        struct mlx4_counter tmp_counter_stats;
        struct mlx4_en_stat_out_mbox *mlx4_en_stats;
        struct mlx4_en_stat_out_flow_control_mbox *flowstats;
-       struct mlx4_en_priv *priv = netdev_priv(mdev->pndev[port]);
-       struct net_device_stats *stats = &priv->stats;
+       struct net_device *dev = mdev->pndev[port];
+       struct mlx4_en_priv *priv = netdev_priv(dev);
+       struct net_device_stats *stats = &dev->stats;
        struct mlx4_cmd_mailbox *mailbox;
        u64 in_mod = reset << 8 | port;
        int err;
@@ -188,6 +189,7 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
        }
        stats->tx_packets = 0;
        stats->tx_bytes = 0;
+       stats->tx_dropped = 0;
        priv->port_stats.tx_chksum_offload = 0;
        priv->port_stats.queue_stopped = 0;
        priv->port_stats.wake_queue = 0;
@@ -199,6 +201,7 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
 
                stats->tx_packets += ring->packets;
                stats->tx_bytes += ring->bytes;
+               stats->tx_dropped += ring->tx_dropped;
                priv->port_stats.tx_chksum_offload += ring->tx_csum;
                priv->port_stats.queue_stopped     += ring->queue_stopped;
                priv->port_stats.wake_queue        += ring->wake_queue;
@@ -237,21 +240,12 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
        stats->multicast = en_stats_adder(&mlx4_en_stats->MCAST_prio_0,
                                          &mlx4_en_stats->MCAST_prio_1,
                                          NUM_PRIORITIES);
-       stats->collisions = 0;
        stats->rx_dropped = be32_to_cpu(mlx4_en_stats->RDROP) +
                            sw_rx_dropped;
        stats->rx_length_errors = be32_to_cpu(mlx4_en_stats->RdropLength);
-       stats->rx_over_errors = 0;
        stats->rx_crc_errors = be32_to_cpu(mlx4_en_stats->RCRC);
-       stats->rx_frame_errors = 0;
        stats->rx_fifo_errors = be32_to_cpu(mlx4_en_stats->RdropOvflw);
-       stats->rx_missed_errors = 0;
-       stats->tx_aborted_errors = 0;
-       stats->tx_carrier_errors = 0;
-       stats->tx_fifo_errors = 0;
-       stats->tx_heartbeat_errors = 0;
-       stats->tx_window_errors = 0;
-       stats->tx_dropped = be32_to_cpu(mlx4_en_stats->TDROP);
+       stats->tx_dropped += be32_to_cpu(mlx4_en_stats->TDROP);
 
        /* RX stats */
        priv->pkstats.rx_multicast_packets = stats->multicast;
index f6e6157..76aa4d2 100644 (file)
@@ -726,12 +726,12 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
        bool inline_ok;
        u32 ring_cons;
 
-       if (!priv->port_up)
-               goto tx_drop;
-
        tx_ind = skb_get_queue_mapping(skb);
        ring = priv->tx_ring[tx_ind];
 
+       if (!priv->port_up)
+               goto tx_drop;
+
        /* fetch ring->cons far ahead before needing it to avoid stall */
        ring_cons = ACCESS_ONCE(ring->cons);
 
@@ -1030,7 +1030,7 @@ tx_drop_unmap:
 
 tx_drop:
        dev_kfree_skb_any(skb);
-       priv->stats.tx_dropped++;
+       ring->tx_dropped++;
        return NETDEV_TX_OK;
 }
 
index cc84e09..467d47e 100644 (file)
@@ -270,6 +270,7 @@ struct mlx4_en_tx_ring {
        unsigned long           tx_csum;
        unsigned long           tso_packets;
        unsigned long           xmit_more;
+       unsigned int            tx_dropped;
        struct mlx4_bf          bf;
        unsigned long           queue_stopped;
 
@@ -482,8 +483,6 @@ struct mlx4_en_priv {
        struct mlx4_en_port_profile *prof;
        struct net_device *dev;
        unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
-       struct net_device_stats stats;
-       struct net_device_stats ret_stats;
        struct mlx4_en_port_state port_state;
        spinlock_t stats_lock;
        struct ethtool_flow_id ethtool_rules[MAX_NUM_OF_FS_RULES];
index fd43929..f5c8d5d 100644 (file)
@@ -3192,10 +3192,7 @@ static void mlx5e_destroy_netdev(struct mlx5_core_dev *mdev, void *vpriv)
        flush_workqueue(priv->wq);
        if (test_bit(MLX5_INTERFACE_STATE_SHUTDOWN, &mdev->intf_state)) {
                netif_device_detach(netdev);
-               mutex_lock(&priv->state_lock);
-               if (test_bit(MLX5E_STATE_OPENED, &priv->state))
-                       mlx5e_close_locked(netdev);
-               mutex_unlock(&priv->state_lock);
+               mlx5e_close(netdev);
        } else {
                unregister_netdev(netdev);
        }
index 229ab16..b000ddc 100644 (file)
@@ -317,7 +317,8 @@ static netdev_tx_t mlx5e_sq_xmit(struct mlx5e_sq *sq, struct sk_buff *skb)
        while ((sq->pc & wq->sz_m1) > sq->edge)
                mlx5e_send_nop(sq, false);
 
-       sq->bf_budget = bf ? sq->bf_budget - 1 : 0;
+       if (bf)
+               sq->bf_budget--;
 
        sq->stats.packets++;
        sq->stats.bytes += num_bytes;
index b84a691..aebbd6c 100644 (file)
@@ -383,7 +383,7 @@ __esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u32 vport, bool rx_rule,
                                   match_v,
                                   MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
                                   0, &dest);
-       if (IS_ERR_OR_NULL(flow_rule)) {
+       if (IS_ERR(flow_rule)) {
                pr_warn(
                        "FDB: Failed to add flow rule: dmac_v(%pM) dmac_c(%pM) -> vport(%d), err(%ld)\n",
                         dmac_v, dmac_c, vport, PTR_ERR(flow_rule));
@@ -457,7 +457,7 @@ static int esw_create_fdb_table(struct mlx5_eswitch *esw, int nvports)
 
        table_size = BIT(MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size));
        fdb = mlx5_create_flow_table(root_ns, 0, table_size, 0);
-       if (IS_ERR_OR_NULL(fdb)) {
+       if (IS_ERR(fdb)) {
                err = PTR_ERR(fdb);
                esw_warn(dev, "Failed to create FDB Table err %d\n", err);
                goto out;
@@ -474,7 +474,7 @@ static int esw_create_fdb_table(struct mlx5_eswitch *esw, int nvports)
        MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 3);
        eth_broadcast_addr(dmac);
        g = mlx5_create_flow_group(fdb, flow_group_in);
-       if (IS_ERR_OR_NULL(g)) {
+       if (IS_ERR(g)) {
                err = PTR_ERR(g);
                esw_warn(dev, "Failed to create flow group err(%d)\n", err);
                goto out;
@@ -489,7 +489,7 @@ static int esw_create_fdb_table(struct mlx5_eswitch *esw, int nvports)
        eth_zero_addr(dmac);
        dmac[0] = 0x01;
        g = mlx5_create_flow_group(fdb, flow_group_in);
-       if (IS_ERR_OR_NULL(g)) {
+       if (IS_ERR(g)) {
                err = PTR_ERR(g);
                esw_warn(dev, "Failed to create allmulti flow group err(%d)\n", err);
                goto out;
@@ -506,7 +506,7 @@ static int esw_create_fdb_table(struct mlx5_eswitch *esw, int nvports)
        MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, table_size - 1);
        MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 1);
        g = mlx5_create_flow_group(fdb, flow_group_in);
-       if (IS_ERR_OR_NULL(g)) {
+       if (IS_ERR(g)) {
                err = PTR_ERR(g);
                esw_warn(dev, "Failed to create promisc flow group err(%d)\n", err);
                goto out;
@@ -529,7 +529,7 @@ out:
                }
        }
 
-       kfree(flow_group_in);
+       kvfree(flow_group_in);
        return err;
 }
 
@@ -651,6 +651,7 @@ static void update_allmulti_vports(struct mlx5_eswitch *esw,
                                        esw_fdb_set_vport_rule(esw,
                                                               mac,
                                                               vport_idx);
+                       iter_vaddr->mc_promisc = true;
                        break;
                case MLX5_ACTION_DEL:
                        if (!iter_vaddr)
@@ -1060,7 +1061,7 @@ static void esw_vport_enable_egress_acl(struct mlx5_eswitch *esw,
                return;
 
        acl = mlx5_create_vport_flow_table(root_ns, 0, table_size, 0, vport->vport);
-       if (IS_ERR_OR_NULL(acl)) {
+       if (IS_ERR(acl)) {
                err = PTR_ERR(acl);
                esw_warn(dev, "Failed to create E-Switch vport[%d] egress flow Table, err(%d)\n",
                         vport->vport, err);
@@ -1075,7 +1076,7 @@ static void esw_vport_enable_egress_acl(struct mlx5_eswitch *esw,
        MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 0);
 
        vlan_grp = mlx5_create_flow_group(acl, flow_group_in);
-       if (IS_ERR_OR_NULL(vlan_grp)) {
+       if (IS_ERR(vlan_grp)) {
                err = PTR_ERR(vlan_grp);
                esw_warn(dev, "Failed to create E-Switch vport[%d] egress allowed vlans flow group, err(%d)\n",
                         vport->vport, err);
@@ -1086,7 +1087,7 @@ static void esw_vport_enable_egress_acl(struct mlx5_eswitch *esw,
        MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 1);
        MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 1);
        drop_grp = mlx5_create_flow_group(acl, flow_group_in);
-       if (IS_ERR_OR_NULL(drop_grp)) {
+       if (IS_ERR(drop_grp)) {
                err = PTR_ERR(drop_grp);
                esw_warn(dev, "Failed to create E-Switch vport[%d] egress drop flow group, err(%d)\n",
                         vport->vport, err);
@@ -1097,7 +1098,7 @@ static void esw_vport_enable_egress_acl(struct mlx5_eswitch *esw,
        vport->egress.drop_grp = drop_grp;
        vport->egress.allowed_vlans_grp = vlan_grp;
 out:
-       kfree(flow_group_in);
+       kvfree(flow_group_in);
        if (err && !IS_ERR_OR_NULL(vlan_grp))
                mlx5_destroy_flow_group(vlan_grp);
        if (err && !IS_ERR_OR_NULL(acl))
@@ -1174,7 +1175,7 @@ static void esw_vport_enable_ingress_acl(struct mlx5_eswitch *esw,
                return;
 
        acl = mlx5_create_vport_flow_table(root_ns, 0, table_size, 0, vport->vport);
-       if (IS_ERR_OR_NULL(acl)) {
+       if (IS_ERR(acl)) {
                err = PTR_ERR(acl);
                esw_warn(dev, "Failed to create E-Switch vport[%d] ingress flow Table, err(%d)\n",
                         vport->vport, err);
@@ -1192,7 +1193,7 @@ static void esw_vport_enable_ingress_acl(struct mlx5_eswitch *esw,
        MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 0);
 
        g = mlx5_create_flow_group(acl, flow_group_in);
-       if (IS_ERR_OR_NULL(g)) {
+       if (IS_ERR(g)) {
                err = PTR_ERR(g);
                esw_warn(dev, "Failed to create E-Switch vport[%d] ingress untagged spoofchk flow group, err(%d)\n",
                         vport->vport, err);
@@ -1207,7 +1208,7 @@ static void esw_vport_enable_ingress_acl(struct mlx5_eswitch *esw,
        MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 1);
 
        g = mlx5_create_flow_group(acl, flow_group_in);
-       if (IS_ERR_OR_NULL(g)) {
+       if (IS_ERR(g)) {
                err = PTR_ERR(g);
                esw_warn(dev, "Failed to create E-Switch vport[%d] ingress untagged flow group, err(%d)\n",
                         vport->vport, err);
@@ -1223,7 +1224,7 @@ static void esw_vport_enable_ingress_acl(struct mlx5_eswitch *esw,
        MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 2);
 
        g = mlx5_create_flow_group(acl, flow_group_in);
-       if (IS_ERR_OR_NULL(g)) {
+       if (IS_ERR(g)) {
                err = PTR_ERR(g);
                esw_warn(dev, "Failed to create E-Switch vport[%d] ingress spoofchk flow group, err(%d)\n",
                         vport->vport, err);
@@ -1236,7 +1237,7 @@ static void esw_vport_enable_ingress_acl(struct mlx5_eswitch *esw,
        MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 3);
 
        g = mlx5_create_flow_group(acl, flow_group_in);
-       if (IS_ERR_OR_NULL(g)) {
+       if (IS_ERR(g)) {
                err = PTR_ERR(g);
                esw_warn(dev, "Failed to create E-Switch vport[%d] ingress drop flow group, err(%d)\n",
                         vport->vport, err);
@@ -1259,7 +1260,7 @@ out:
                        mlx5_destroy_flow_table(vport->ingress.acl);
        }
 
-       kfree(flow_group_in);
+       kvfree(flow_group_in);
 }
 
 static void esw_vport_cleanup_ingress_rules(struct mlx5_eswitch *esw,
@@ -1363,7 +1364,7 @@ static int esw_vport_ingress_config(struct mlx5_eswitch *esw,
                                   match_v,
                                   MLX5_FLOW_CONTEXT_ACTION_ALLOW,
                                   0, NULL);
-       if (IS_ERR_OR_NULL(vport->ingress.allow_rule)) {
+       if (IS_ERR(vport->ingress.allow_rule)) {
                err = PTR_ERR(vport->ingress.allow_rule);
                pr_warn("vport[%d] configure ingress allow rule, err(%d)\n",
                        vport->vport, err);
@@ -1380,7 +1381,7 @@ static int esw_vport_ingress_config(struct mlx5_eswitch *esw,
                                   match_v,
                                   MLX5_FLOW_CONTEXT_ACTION_DROP,
                                   0, NULL);
-       if (IS_ERR_OR_NULL(vport->ingress.drop_rule)) {
+       if (IS_ERR(vport->ingress.drop_rule)) {
                err = PTR_ERR(vport->ingress.drop_rule);
                pr_warn("vport[%d] configure ingress drop rule, err(%d)\n",
                        vport->vport, err);
@@ -1439,7 +1440,7 @@ static int esw_vport_egress_config(struct mlx5_eswitch *esw,
                                   match_v,
                                   MLX5_FLOW_CONTEXT_ACTION_ALLOW,
                                   0, NULL);
-       if (IS_ERR_OR_NULL(vport->egress.allowed_vlan)) {
+       if (IS_ERR(vport->egress.allowed_vlan)) {
                err = PTR_ERR(vport->egress.allowed_vlan);
                pr_warn("vport[%d] configure egress allowed vlan rule failed, err(%d)\n",
                        vport->vport, err);
@@ -1457,7 +1458,7 @@ static int esw_vport_egress_config(struct mlx5_eswitch *esw,
                                   match_v,
                                   MLX5_FLOW_CONTEXT_ACTION_DROP,
                                   0, NULL);
-       if (IS_ERR_OR_NULL(vport->egress.drop_rule)) {
+       if (IS_ERR(vport->egress.drop_rule)) {
                err = PTR_ERR(vport->egress.drop_rule);
                pr_warn("vport[%d] configure egress drop rule failed, err(%d)\n",
                        vport->vport, err);
@@ -1491,14 +1492,11 @@ static void esw_enable_vport(struct mlx5_eswitch *esw, int vport_num,
 
        /* Sync with current vport context */
        vport->enabled_events = enable_events;
-       esw_vport_change_handle_locked(vport);
-
        vport->enabled = true;
 
        /* only PF is trusted by default */
        vport->trusted = (vport_num) ? false : true;
-
-       arm_vport_context_events_cmd(esw->dev, vport_num, enable_events);
+       esw_vport_change_handle_locked(vport);
 
        esw->enabled_vports++;
        esw_debug(esw->dev, "Enabled VPORT(%d)\n", vport_num);
@@ -1728,11 +1726,24 @@ void mlx5_eswitch_vport_event(struct mlx5_eswitch *esw, struct mlx5_eqe *eqe)
        (esw && MLX5_CAP_GEN(esw->dev, vport_group_manager) && mlx5_core_is_pf(esw->dev))
 #define LEGAL_VPORT(esw, vport) (vport >= 0 && vport < esw->total_vports)
 
+static void node_guid_gen_from_mac(u64 *node_guid, u8 mac[ETH_ALEN])
+{
+       ((u8 *)node_guid)[7] = mac[0];
+       ((u8 *)node_guid)[6] = mac[1];
+       ((u8 *)node_guid)[5] = mac[2];
+       ((u8 *)node_guid)[4] = 0xff;
+       ((u8 *)node_guid)[3] = 0xfe;
+       ((u8 *)node_guid)[2] = mac[3];
+       ((u8 *)node_guid)[1] = mac[4];
+       ((u8 *)node_guid)[0] = mac[5];
+}
+
 int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw,
                               int vport, u8 mac[ETH_ALEN])
 {
-       int err = 0;
        struct mlx5_vport *evport;
+       u64 node_guid;
+       int err = 0;
 
        if (!ESW_ALLOWED(esw))
                return -EPERM;
@@ -1756,11 +1767,17 @@ int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw,
                return err;
        }
 
+       node_guid_gen_from_mac(&node_guid, mac);
+       err = mlx5_modify_nic_vport_node_guid(esw->dev, vport, node_guid);
+       if (err)
+               mlx5_core_warn(esw->dev,
+                              "Failed to set vport %d node guid, err = %d. RDMA_CM will not function properly for this VF.\n",
+                              vport, err);
+
        mutex_lock(&esw->state_lock);
        if (evport->enabled)
                err = esw_vport_ingress_config(esw, evport);
        mutex_unlock(&esw->state_lock);
-
        return err;
 }
 
index 8b5f0b2..e912a3d 100644 (file)
@@ -1292,8 +1292,8 @@ static int update_root_ft_destroy(struct mlx5_flow_table *ft)
                                       ft->id);
                        return err;
                }
-               root->root_ft = new_root_ft;
        }
+       root->root_ft = new_root_ft;
        return 0;
 }
 
@@ -1767,6 +1767,9 @@ static void cleanup_root_ns(struct mlx5_core_dev *dev)
 
 void mlx5_cleanup_fs(struct mlx5_core_dev *dev)
 {
+       if (MLX5_CAP_GEN(dev, port_type) != MLX5_CAP_PORT_TYPE_ETH)
+               return;
+
        cleanup_root_ns(dev);
        cleanup_single_prio_root_ns(dev, dev->priv.fdb_root_ns);
        cleanup_single_prio_root_ns(dev, dev->priv.esw_egress_root_ns);
@@ -1828,29 +1831,36 @@ int mlx5_init_fs(struct mlx5_core_dev *dev)
 {
        int err = 0;
 
+       if (MLX5_CAP_GEN(dev, port_type) != MLX5_CAP_PORT_TYPE_ETH)
+               return 0;
+
        err = mlx5_init_fc_stats(dev);
        if (err)
                return err;
 
-       if (MLX5_CAP_GEN(dev, nic_flow_table)) {
+       if (MLX5_CAP_GEN(dev, nic_flow_table) &&
+           MLX5_CAP_FLOWTABLE_NIC_RX(dev, ft_support)) {
                err = init_root_ns(dev);
                if (err)
                        goto err;
        }
+
        if (MLX5_CAP_GEN(dev, eswitch_flow_table)) {
-               err = init_fdb_root_ns(dev);
-               if (err)
-                       goto err;
-       }
-       if (MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support)) {
-               err = init_egress_acl_root_ns(dev);
-               if (err)
-                       goto err;
-       }
-       if (MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support)) {
-               err = init_ingress_acl_root_ns(dev);
-               if (err)
-                       goto err;
+               if (MLX5_CAP_ESW_FLOWTABLE_FDB(dev, ft_support)) {
+                       err = init_fdb_root_ns(dev);
+                       if (err)
+                               goto err;
+               }
+               if (MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support)) {
+                       err = init_egress_acl_root_ns(dev);
+                       if (err)
+                               goto err;
+               }
+               if (MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support)) {
+                       err = init_ingress_acl_root_ns(dev);
+                       if (err)
+                               goto err;
+               }
        }
 
        return 0;
index b720a27..b82d658 100644 (file)
@@ -418,7 +418,7 @@ int mlx5_core_xrcd_alloc(struct mlx5_core_dev *dev, u32 *xrcdn)
        if (out.hdr.status)
                err = mlx5_cmd_status_to_err(&out.hdr);
        else
-               *xrcdn = be32_to_cpu(out.xrcdn);
+               *xrcdn = be32_to_cpu(out.xrcdn) & 0xffffff;
 
        return err;
 }
index b69dadc..daf44cd 100644 (file)
@@ -508,6 +508,44 @@ int mlx5_query_nic_vport_node_guid(struct mlx5_core_dev *mdev, u64 *node_guid)
 }
 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_node_guid);
 
+int mlx5_modify_nic_vport_node_guid(struct mlx5_core_dev *mdev,
+                                   u32 vport, u64 node_guid)
+{
+       int inlen = MLX5_ST_SZ_BYTES(modify_nic_vport_context_in);
+       void *nic_vport_context;
+       u8 *guid;
+       void *in;
+       int err;
+
+       if (!vport)
+               return -EINVAL;
+       if (!MLX5_CAP_GEN(mdev, vport_group_manager))
+               return -EACCES;
+       if (!MLX5_CAP_ESW(mdev, nic_vport_node_guid_modify))
+               return -ENOTSUPP;
+
+       in = mlx5_vzalloc(inlen);
+       if (!in)
+               return -ENOMEM;
+
+       MLX5_SET(modify_nic_vport_context_in, in,
+                field_select.node_guid, 1);
+       MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport);
+       MLX5_SET(modify_nic_vport_context_in, in, other_vport, !!vport);
+
+       nic_vport_context = MLX5_ADDR_OF(modify_nic_vport_context_in,
+                                        in, nic_vport_context);
+       guid = MLX5_ADDR_OF(nic_vport_context, nic_vport_context,
+                           node_guid);
+       MLX5_SET64(nic_vport_context, nic_vport_context, node_guid, node_guid);
+
+       err = mlx5_modify_nic_vport_context(mdev, in, inlen);
+
+       kvfree(in);
+
+       return err;
+}
+
 int mlx5_query_nic_vport_qkey_viol_cntr(struct mlx5_core_dev *mdev,
                                        u16 *qkey_viol_cntr)
 {
index 4a72737..6f9e3dd 100644 (file)
@@ -247,15 +247,23 @@ static int mlxsw_sp_port_mtu_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 mtu)
        return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pmtu), pmtu_pl);
 }
 
-static int mlxsw_sp_port_swid_set(struct mlxsw_sp_port *mlxsw_sp_port, u8 swid)
+static int __mlxsw_sp_port_swid_set(struct mlxsw_sp *mlxsw_sp, u8 local_port,
+                                   u8 swid)
 {
-       struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
        char pspa_pl[MLXSW_REG_PSPA_LEN];
 
-       mlxsw_reg_pspa_pack(pspa_pl, swid, mlxsw_sp_port->local_port);
+       mlxsw_reg_pspa_pack(pspa_pl, swid, local_port);
        return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pspa), pspa_pl);
 }
 
+static int mlxsw_sp_port_swid_set(struct mlxsw_sp_port *mlxsw_sp_port, u8 swid)
+{
+       struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
+
+       return __mlxsw_sp_port_swid_set(mlxsw_sp, mlxsw_sp_port->local_port,
+                                       swid);
+}
+
 static int mlxsw_sp_port_vp_mode_set(struct mlxsw_sp_port *mlxsw_sp_port,
                                     bool enable)
 {
@@ -305,9 +313,9 @@ mlxsw_sp_port_system_port_mapping_set(struct mlxsw_sp_port *mlxsw_sp_port)
        return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sspr), sspr_pl);
 }
 
-static int __mlxsw_sp_port_module_info_get(struct mlxsw_sp *mlxsw_sp,
-                                          u8 local_port, u8 *p_module,
-                                          u8 *p_width, u8 *p_lane)
+static int mlxsw_sp_port_module_info_get(struct mlxsw_sp *mlxsw_sp,
+                                        u8 local_port, u8 *p_module,
+                                        u8 *p_width, u8 *p_lane)
 {
        char pmlp_pl[MLXSW_REG_PMLP_LEN];
        int err;
@@ -322,16 +330,6 @@ static int __mlxsw_sp_port_module_info_get(struct mlxsw_sp *mlxsw_sp,
        return 0;
 }
 
-static int mlxsw_sp_port_module_info_get(struct mlxsw_sp *mlxsw_sp,
-                                        u8 local_port, u8 *p_module,
-                                        u8 *p_width)
-{
-       u8 lane;
-
-       return __mlxsw_sp_port_module_info_get(mlxsw_sp, local_port, p_module,
-                                              p_width, &lane);
-}
-
 static int mlxsw_sp_port_module_map(struct mlxsw_sp *mlxsw_sp, u8 local_port,
                                    u8 module, u8 width, u8 lane)
 {
@@ -949,17 +947,11 @@ static int mlxsw_sp_port_get_phys_port_name(struct net_device *dev, char *name,
                                            size_t len)
 {
        struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
-       u8 module, width, lane;
+       u8 module = mlxsw_sp_port->mapping.module;
+       u8 width = mlxsw_sp_port->mapping.width;
+       u8 lane = mlxsw_sp_port->mapping.lane;
        int err;
 
-       err = __mlxsw_sp_port_module_info_get(mlxsw_sp_port->mlxsw_sp,
-                                             mlxsw_sp_port->local_port,
-                                             &module, &width, &lane);
-       if (err) {
-               netdev_err(dev, "Failed to retrieve module information\n");
-               return err;
-       }
-
        if (!mlxsw_sp_port->split)
                err = snprintf(name, len, "p%d", module + 1);
        else
@@ -1681,8 +1673,8 @@ static int mlxsw_sp_port_ets_init(struct mlxsw_sp_port *mlxsw_sp_port)
        return 0;
 }
 
-static int __mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
-                                 bool split, u8 module, u8 width)
+static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
+                               bool split, u8 module, u8 width, u8 lane)
 {
        struct mlxsw_sp_port *mlxsw_sp_port;
        struct net_device *dev;
@@ -1697,6 +1689,9 @@ static int __mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
        mlxsw_sp_port->mlxsw_sp = mlxsw_sp;
        mlxsw_sp_port->local_port = local_port;
        mlxsw_sp_port->split = split;
+       mlxsw_sp_port->mapping.module = module;
+       mlxsw_sp_port->mapping.width = width;
+       mlxsw_sp_port->mapping.lane = lane;
        bytes = DIV_ROUND_UP(VLAN_N_VID, BITS_PER_BYTE);
        mlxsw_sp_port->active_vlans = kzalloc(bytes, GFP_KERNEL);
        if (!mlxsw_sp_port->active_vlans) {
@@ -1839,28 +1834,6 @@ err_port_active_vlans_alloc:
        return err;
 }
 
-static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
-                               bool split, u8 module, u8 width, u8 lane)
-{
-       int err;
-
-       err = mlxsw_sp_port_module_map(mlxsw_sp, local_port, module, width,
-                                      lane);
-       if (err)
-               return err;
-
-       err = __mlxsw_sp_port_create(mlxsw_sp, local_port, split, module,
-                                    width);
-       if (err)
-               goto err_port_create;
-
-       return 0;
-
-err_port_create:
-       mlxsw_sp_port_module_unmap(mlxsw_sp, local_port);
-       return err;
-}
-
 static void mlxsw_sp_port_vports_fini(struct mlxsw_sp_port *mlxsw_sp_port)
 {
        struct net_device *dev = mlxsw_sp_port->dev;
@@ -1909,8 +1882,8 @@ static void mlxsw_sp_ports_remove(struct mlxsw_sp *mlxsw_sp)
 
 static int mlxsw_sp_ports_create(struct mlxsw_sp *mlxsw_sp)
 {
+       u8 module, width, lane;
        size_t alloc_size;
-       u8 module, width;
        int i;
        int err;
 
@@ -1921,13 +1894,14 @@ static int mlxsw_sp_ports_create(struct mlxsw_sp *mlxsw_sp)
 
        for (i = 1; i < MLXSW_PORT_MAX_PORTS; i++) {
                err = mlxsw_sp_port_module_info_get(mlxsw_sp, i, &module,
-                                                   &width);
+                                                   &width, &lane);
                if (err)
                        goto err_port_module_info_get;
                if (!width)
                        continue;
                mlxsw_sp->port_to_module[i] = module;
-               err = __mlxsw_sp_port_create(mlxsw_sp, i, false, module, width);
+               err = mlxsw_sp_port_create(mlxsw_sp, i, false, module, width,
+                                          lane);
                if (err)
                        goto err_port_create;
        }
@@ -1948,12 +1922,85 @@ static u8 mlxsw_sp_cluster_base_port_get(u8 local_port)
        return local_port - offset;
 }
 
+static int mlxsw_sp_port_split_create(struct mlxsw_sp *mlxsw_sp, u8 base_port,
+                                     u8 module, unsigned int count)
+{
+       u8 width = MLXSW_PORT_MODULE_MAX_WIDTH / count;
+       int err, i;
+
+       for (i = 0; i < count; i++) {
+               err = mlxsw_sp_port_module_map(mlxsw_sp, base_port + i, module,
+                                              width, i * width);
+               if (err)
+                       goto err_port_module_map;
+       }
+
+       for (i = 0; i < count; i++) {
+               err = __mlxsw_sp_port_swid_set(mlxsw_sp, base_port + i, 0);
+               if (err)
+                       goto err_port_swid_set;
+       }
+
+       for (i = 0; i < count; i++) {
+               err = mlxsw_sp_port_create(mlxsw_sp, base_port + i, true,
+                                          module, width, i * width);
+               if (err)
+                       goto err_port_create;
+       }
+
+       return 0;
+
+err_port_create:
+       for (i--; i >= 0; i--)
+               mlxsw_sp_port_remove(mlxsw_sp, base_port + i);
+       i = count;
+err_port_swid_set:
+       for (i--; i >= 0; i--)
+               __mlxsw_sp_port_swid_set(mlxsw_sp, base_port + i,
+                                        MLXSW_PORT_SWID_DISABLED_PORT);
+       i = count;
+err_port_module_map:
+       for (i--; i >= 0; i--)
+               mlxsw_sp_port_module_unmap(mlxsw_sp, base_port + i);
+       return err;
+}
+
+static void mlxsw_sp_port_unsplit_create(struct mlxsw_sp *mlxsw_sp,
+                                        u8 base_port, unsigned int count)
+{
+       u8 local_port, module, width = MLXSW_PORT_MODULE_MAX_WIDTH;
+       int i;
+
+       /* Split by four means we need to re-create two ports, otherwise
+        * only one.
+        */
+       count = count / 2;
+
+       for (i = 0; i < count; i++) {
+               local_port = base_port + i * 2;
+               module = mlxsw_sp->port_to_module[local_port];
+
+               mlxsw_sp_port_module_map(mlxsw_sp, local_port, module, width,
+                                        0);
+       }
+
+       for (i = 0; i < count; i++)
+               __mlxsw_sp_port_swid_set(mlxsw_sp, base_port + i * 2, 0);
+
+       for (i = 0; i < count; i++) {
+               local_port = base_port + i * 2;
+               module = mlxsw_sp->port_to_module[local_port];
+
+               mlxsw_sp_port_create(mlxsw_sp, local_port, false, module,
+                                    width, 0);
+       }
+}
+
 static int mlxsw_sp_port_split(struct mlxsw_core *mlxsw_core, u8 local_port,
                               unsigned int count)
 {
        struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
        struct mlxsw_sp_port *mlxsw_sp_port;
-       u8 width = MLXSW_PORT_MODULE_MAX_WIDTH / count;
        u8 module, cur_width, base_port;
        int i;
        int err;
@@ -1965,18 +2012,14 @@ static int mlxsw_sp_port_split(struct mlxsw_core *mlxsw_core, u8 local_port,
                return -EINVAL;
        }
 
+       module = mlxsw_sp_port->mapping.module;
+       cur_width = mlxsw_sp_port->mapping.width;
+
        if (count != 2 && count != 4) {
                netdev_err(mlxsw_sp_port->dev, "Port can only be split into 2 or 4 ports\n");
                return -EINVAL;
        }
 
-       err = mlxsw_sp_port_module_info_get(mlxsw_sp, local_port, &module,
-                                           &cur_width);
-       if (err) {
-               netdev_err(mlxsw_sp_port->dev, "Failed to get port's width\n");
-               return err;
-       }
-
        if (cur_width != MLXSW_PORT_MODULE_MAX_WIDTH) {
                netdev_err(mlxsw_sp_port->dev, "Port cannot be split further\n");
                return -EINVAL;
@@ -2001,25 +2044,16 @@ static int mlxsw_sp_port_split(struct mlxsw_core *mlxsw_core, u8 local_port,
        for (i = 0; i < count; i++)
                mlxsw_sp_port_remove(mlxsw_sp, base_port + i);
 
-       for (i = 0; i < count; i++) {
-               err = mlxsw_sp_port_create(mlxsw_sp, base_port + i, true,
-                                          module, width, i * width);
-               if (err) {
-                       dev_err(mlxsw_sp->bus_info->dev, "Failed to create split port\n");
-                       goto err_port_create;
-               }
+       err = mlxsw_sp_port_split_create(mlxsw_sp, base_port, module, count);
+       if (err) {
+               dev_err(mlxsw_sp->bus_info->dev, "Failed to create split ports\n");
+               goto err_port_split_create;
        }
 
        return 0;
 
-err_port_create:
-       for (i--; i >= 0; i--)
-               mlxsw_sp_port_remove(mlxsw_sp, base_port + i);
-       for (i = 0; i < count / 2; i++) {
-               module = mlxsw_sp->port_to_module[base_port + i * 2];
-               mlxsw_sp_port_create(mlxsw_sp, base_port + i * 2, false,
-                                    module, MLXSW_PORT_MODULE_MAX_WIDTH, 0);
-       }
+err_port_split_create:
+       mlxsw_sp_port_unsplit_create(mlxsw_sp, base_port, count);
        return err;
 }
 
@@ -2027,10 +2061,9 @@ static int mlxsw_sp_port_unsplit(struct mlxsw_core *mlxsw_core, u8 local_port)
 {
        struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
        struct mlxsw_sp_port *mlxsw_sp_port;
-       u8 module, cur_width, base_port;
+       u8 cur_width, base_port;
        unsigned int count;
        int i;
-       int err;
 
        mlxsw_sp_port = mlxsw_sp->ports[local_port];
        if (!mlxsw_sp_port) {
@@ -2044,12 +2077,7 @@ static int mlxsw_sp_port_unsplit(struct mlxsw_core *mlxsw_core, u8 local_port)
                return -EINVAL;
        }
 
-       err = mlxsw_sp_port_module_info_get(mlxsw_sp, local_port, &module,
-                                           &cur_width);
-       if (err) {
-               netdev_err(mlxsw_sp_port->dev, "Failed to get port's width\n");
-               return err;
-       }
+       cur_width = mlxsw_sp_port->mapping.width;
        count = cur_width == 1 ? 4 : 2;
 
        base_port = mlxsw_sp_cluster_base_port_get(local_port);
@@ -2061,14 +2089,7 @@ static int mlxsw_sp_port_unsplit(struct mlxsw_core *mlxsw_core, u8 local_port)
        for (i = 0; i < count; i++)
                mlxsw_sp_port_remove(mlxsw_sp, base_port + i);
 
-       for (i = 0; i < count / 2; i++) {
-               module = mlxsw_sp->port_to_module[base_port + i * 2];
-               err = mlxsw_sp_port_create(mlxsw_sp, base_port + i * 2, false,
-                                          module, MLXSW_PORT_MODULE_MAX_WIDTH,
-                                          0);
-               if (err)
-                       dev_err(mlxsw_sp->bus_info->dev, "Failed to reinstantiate port\n");
-       }
+       mlxsw_sp_port_unsplit_create(mlxsw_sp, base_port, count);
 
        return 0;
 }
index e2c022d..13b30ea 100644 (file)
@@ -229,6 +229,11 @@ struct mlxsw_sp_port {
                struct ieee_maxrate *maxrate;
                struct ieee_pfc *pfc;
        } dcb;
+       struct {
+               u8 module;
+               u8 width;
+               u8 lane;
+       } mapping;
        /* 802.1Q bridge VLANs */
        unsigned long *active_vlans;
        unsigned long *untagged_vlans;
index cbf58e1..21ec1c2 100644 (file)
@@ -192,9 +192,10 @@ qed_dcbx_process_tlv(struct qed_hwfn *p_hwfn,
                     struct dcbx_app_priority_entry *p_tbl,
                     u32 pri_tc_tbl, int count, bool dcbx_enabled)
 {
-       u8 tc, priority, priority_map;
+       u8 tc, priority_map;
        enum dcbx_protocol_type type;
        u16 protocol_id;
+       int priority;
        bool enable;
        int i;
 
@@ -221,7 +222,7 @@ qed_dcbx_process_tlv(struct qed_hwfn *p_hwfn,
                         * indication, but we only got here if there was an
                         * app tlv for the protocol, so dcbx must be enabled.
                         */
-                       enable = !!(type == DCBX_PROTOCOL_ETH);
+                       enable = !(type == DCBX_PROTOCOL_ETH);
 
                        qed_dcbx_update_app_info(p_data, p_hwfn, enable, true,
                                                 priority, tc, type);
index 089016f..2d89e8c 100644 (file)
@@ -155,12 +155,14 @@ void qed_resc_free(struct qed_dev *cdev)
        }
 }
 
-static int qed_init_qm_info(struct qed_hwfn *p_hwfn)
+static int qed_init_qm_info(struct qed_hwfn *p_hwfn, bool b_sleepable)
 {
        u8 num_vports, vf_offset = 0, i, vport_id, num_ports, curr_queue = 0;
        struct qed_qm_info *qm_info = &p_hwfn->qm_info;
        struct init_qm_port_params *p_qm_port;
        u16 num_pqs, multi_cos_tcs = 1;
+       u8 pf_wfq = qm_info->pf_wfq;
+       u32 pf_rl = qm_info->pf_rl;
        u16 num_vfs = 0;
 
 #ifdef CONFIG_QED_SRIOV
@@ -182,23 +184,28 @@ static int qed_init_qm_info(struct qed_hwfn *p_hwfn)
 
        /* PQs will be arranged as follows: First per-TC PQ then pure-LB quete.
         */
-       qm_info->qm_pq_params = kzalloc(sizeof(*qm_info->qm_pq_params) *
-                                       num_pqs, GFP_KERNEL);
+       qm_info->qm_pq_params = kcalloc(num_pqs,
+                                       sizeof(struct init_qm_pq_params),
+                                       b_sleepable ? GFP_KERNEL : GFP_ATOMIC);
        if (!qm_info->qm_pq_params)
                goto alloc_err;
 
-       qm_info->qm_vport_params = kzalloc(sizeof(*qm_info->qm_vport_params) *
-                                          num_vports, GFP_KERNEL);
+       qm_info->qm_vport_params = kcalloc(num_vports,
+                                          sizeof(struct init_qm_vport_params),
+                                          b_sleepable ? GFP_KERNEL
+                                                      : GFP_ATOMIC);
        if (!qm_info->qm_vport_params)
                goto alloc_err;
 
-       qm_info->qm_port_params = kzalloc(sizeof(*qm_info->qm_port_params) *
-                                         MAX_NUM_PORTS, GFP_KERNEL);
+       qm_info->qm_port_params = kcalloc(MAX_NUM_PORTS,
+                                         sizeof(struct init_qm_port_params),
+                                         b_sleepable ? GFP_KERNEL
+                                                     : GFP_ATOMIC);
        if (!qm_info->qm_port_params)
                goto alloc_err;
 
-       qm_info->wfq_data = kcalloc(num_vports, sizeof(*qm_info->wfq_data),
-                                   GFP_KERNEL);
+       qm_info->wfq_data = kcalloc(num_vports, sizeof(struct qed_wfq_data),
+                                   b_sleepable ? GFP_KERNEL : GFP_ATOMIC);
        if (!qm_info->wfq_data)
                goto alloc_err;
 
@@ -264,10 +271,10 @@ static int qed_init_qm_info(struct qed_hwfn *p_hwfn)
        for (i = 0; i < qm_info->num_vports; i++)
                qm_info->qm_vport_params[i].vport_wfq = 1;
 
-       qm_info->pf_wfq = 0;
-       qm_info->pf_rl = 0;
        qm_info->vport_rl_en = 1;
        qm_info->vport_wfq_en = 1;
+       qm_info->pf_rl = pf_rl;
+       qm_info->pf_wfq = pf_wfq;
 
        return 0;
 
@@ -299,7 +306,7 @@ int qed_qm_reconf(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
        qed_qm_info_free(p_hwfn);
 
        /* initialize qed's qm data structure */
-       rc = qed_init_qm_info(p_hwfn);
+       rc = qed_init_qm_info(p_hwfn, false);
        if (rc)
                return rc;
 
@@ -388,7 +395,7 @@ int qed_resc_alloc(struct qed_dev *cdev)
                        goto alloc_err;
 
                /* Prepare and process QM requirements */
-               rc = qed_init_qm_info(p_hwfn);
+               rc = qed_init_qm_info(p_hwfn, true);
                if (rc)
                        goto alloc_err;
 
@@ -581,7 +588,14 @@ static void qed_calc_hw_mode(struct qed_hwfn *p_hwfn)
 
        hw_mode |= 1 << MODE_ASIC;
 
+       if (p_hwfn->cdev->num_hwfns > 1)
+               hw_mode |= 1 << MODE_100G;
+
        p_hwfn->hw_info.hw_mode = hw_mode;
+
+       DP_VERBOSE(p_hwfn, (NETIF_MSG_PROBE | NETIF_MSG_IFUP),
+                  "Configuring function for hw_mode: 0x%08x\n",
+                  p_hwfn->hw_info.hw_mode);
 }
 
 /* Init run time data for all PFs on an engine. */
@@ -821,6 +835,11 @@ int qed_hw_init(struct qed_dev *cdev,
        u32 load_code, param;
        int rc, mfw_rc, i;
 
+       if ((int_mode == QED_INT_MODE_MSI) && (cdev->num_hwfns > 1)) {
+               DP_NOTICE(cdev, "MSI mode is not supported for CMT devices\n");
+               return -EINVAL;
+       }
+
        if (IS_PF(cdev)) {
                rc = qed_init_fw_data(cdev, bin_fw_data);
                if (rc != 0)
@@ -2086,6 +2105,13 @@ void qed_configure_vp_wfq_on_link_change(struct qed_dev *cdev, u32 min_pf_rate)
 {
        int i;
 
+       if (cdev->num_hwfns > 1) {
+               DP_VERBOSE(cdev,
+                          NETIF_MSG_LINK,
+                          "WFQ configuration is not supported for this device\n");
+               return;
+       }
+
        for_each_hwfn(cdev, i) {
                struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
 
index 8b22f87..61cc686 100644 (file)
@@ -413,15 +413,17 @@ static int qed_set_int_mode(struct qed_dev *cdev, bool force_mode)
                /* Fallthrough */
 
        case QED_INT_MODE_MSI:
-               rc = pci_enable_msi(cdev->pdev);
-               if (!rc) {
-                       int_params->out.int_mode = QED_INT_MODE_MSI;
-                       goto out;
-               }
+               if (cdev->num_hwfns == 1) {
+                       rc = pci_enable_msi(cdev->pdev);
+                       if (!rc) {
+                               int_params->out.int_mode = QED_INT_MODE_MSI;
+                               goto out;
+                       }
 
-               DP_NOTICE(cdev, "Failed to enable MSI\n");
-               if (force_mode)
-                       goto out;
+                       DP_NOTICE(cdev, "Failed to enable MSI\n");
+                       if (force_mode)
+                               goto out;
+               }
                /* Fallthrough */
 
        case QED_INT_MODE_INTA:
@@ -1103,6 +1105,39 @@ static int qed_get_port_type(u32 media_type)
        return port_type;
 }
 
+static int qed_get_link_data(struct qed_hwfn *hwfn,
+                            struct qed_mcp_link_params *params,
+                            struct qed_mcp_link_state *link,
+                            struct qed_mcp_link_capabilities *link_caps)
+{
+       void *p;
+
+       if (!IS_PF(hwfn->cdev)) {
+               qed_vf_get_link_params(hwfn, params);
+               qed_vf_get_link_state(hwfn, link);
+               qed_vf_get_link_caps(hwfn, link_caps);
+
+               return 0;
+       }
+
+       p = qed_mcp_get_link_params(hwfn);
+       if (!p)
+               return -ENXIO;
+       memcpy(params, p, sizeof(*params));
+
+       p = qed_mcp_get_link_state(hwfn);
+       if (!p)
+               return -ENXIO;
+       memcpy(link, p, sizeof(*link));
+
+       p = qed_mcp_get_link_capabilities(hwfn);
+       if (!p)
+               return -ENXIO;
+       memcpy(link_caps, p, sizeof(*link_caps));
+
+       return 0;
+}
+
 static void qed_fill_link(struct qed_hwfn *hwfn,
                          struct qed_link_output *if_link)
 {
@@ -1114,15 +1149,9 @@ static void qed_fill_link(struct qed_hwfn *hwfn,
        memset(if_link, 0, sizeof(*if_link));
 
        /* Prepare source inputs */
-       if (IS_PF(hwfn->cdev)) {
-               memcpy(&params, qed_mcp_get_link_params(hwfn), sizeof(params));
-               memcpy(&link, qed_mcp_get_link_state(hwfn), sizeof(link));
-               memcpy(&link_caps, qed_mcp_get_link_capabilities(hwfn),
-                      sizeof(link_caps));
-       } else {
-               qed_vf_get_link_params(hwfn, &params);
-               qed_vf_get_link_state(hwfn, &link);
-               qed_vf_get_link_caps(hwfn, &link_caps);
+       if (qed_get_link_data(hwfn, &params, &link, &link_caps)) {
+               dev_warn(&hwfn->cdev->pdev->dev, "no link data available\n");
+               return;
        }
 
        /* Set the link parameters to pass to protocol driver */
index c8667c6..c90b2b6 100644 (file)
 #include "qed_vf.h"
 #define QED_VF_ARRAY_LENGTH (3)
 
+#ifdef CONFIG_QED_SRIOV
 #define IS_VF(cdev)             ((cdev)->b_is_vf)
 #define IS_PF(cdev)             (!((cdev)->b_is_vf))
-#ifdef CONFIG_QED_SRIOV
 #define IS_PF_SRIOV(p_hwfn)     (!!((p_hwfn)->cdev->p_iov_info))
 #else
+#define IS_VF(cdev)             (0)
+#define IS_PF(cdev)             (1)
 #define IS_PF_SRIOV(p_hwfn)     (0)
 #endif
 #define IS_PF_SRIOV_ALLOC(p_hwfn)       (!!((p_hwfn)->pf_iov_info))
index 1bc7535..ad3cae3 100644 (file)
@@ -230,7 +230,10 @@ static int qede_get_sset_count(struct net_device *dev, int stringset)
        case ETH_SS_PRIV_FLAGS:
                return QEDE_PRI_FLAG_LEN;
        case ETH_SS_TEST:
-               return QEDE_ETHTOOL_TEST_MAX;
+               if (!IS_VF(edev))
+                       return QEDE_ETHTOOL_TEST_MAX;
+               else
+                       return 0;
        default:
                DP_VERBOSE(edev, QED_MSG_DEBUG,
                           "Unsupported stringset 0x%08x\n", stringset);
index 337e839..5733d18 100644 (file)
@@ -87,7 +87,9 @@ static const struct pci_device_id qede_pci_tbl[] = {
        {PCI_VDEVICE(QLOGIC, PCI_DEVICE_ID_57980S_100), QEDE_PRIVATE_PF},
        {PCI_VDEVICE(QLOGIC, PCI_DEVICE_ID_57980S_50), QEDE_PRIVATE_PF},
        {PCI_VDEVICE(QLOGIC, PCI_DEVICE_ID_57980S_25), QEDE_PRIVATE_PF},
+#ifdef CONFIG_QED_SRIOV
        {PCI_VDEVICE(QLOGIC, PCI_DEVICE_ID_57980S_IOV), QEDE_PRIVATE_VF},
+#endif
        { 0 }
 };
 
@@ -1824,7 +1826,7 @@ static int qede_set_vf_rate(struct net_device *dev, int vfidx,
 {
        struct qede_dev *edev = netdev_priv(dev);
 
-       return edev->ops->iov->set_rate(edev->cdev, vfidx, max_tx_rate,
+       return edev->ops->iov->set_rate(edev->cdev, vfidx, min_tx_rate,
                                        max_tx_rate);
 }
 
@@ -2091,6 +2093,29 @@ static void qede_vlan_mark_nonconfigured(struct qede_dev *edev)
        edev->accept_any_vlan = false;
 }
 
+int qede_set_features(struct net_device *dev, netdev_features_t features)
+{
+       struct qede_dev *edev = netdev_priv(dev);
+       netdev_features_t changes = features ^ dev->features;
+       bool need_reload = false;
+
+       /* No action needed if hardware GRO is disabled during driver load */
+       if (changes & NETIF_F_GRO) {
+               if (dev->features & NETIF_F_GRO)
+                       need_reload = !edev->gro_disable;
+               else
+                       need_reload = edev->gro_disable;
+       }
+
+       if (need_reload && netif_running(edev->ndev)) {
+               dev->features = features;
+               qede_reload(edev, NULL, NULL);
+               return 1;
+       }
+
+       return 0;
+}
+
 #ifdef CONFIG_QEDE_VXLAN
 static void qede_add_vxlan_port(struct net_device *dev,
                                sa_family_t sa_family, __be16 port)
@@ -2175,6 +2200,7 @@ static const struct net_device_ops qede_netdev_ops = {
 #endif
        .ndo_vlan_rx_add_vid = qede_vlan_rx_add_vid,
        .ndo_vlan_rx_kill_vid = qede_vlan_rx_kill_vid,
+       .ndo_set_features = qede_set_features,
        .ndo_get_stats64 = qede_get_stats64,
 #ifdef CONFIG_QED_SRIOV
        .ndo_set_vf_link_state = qede_set_vf_link_state,
index 83d7210..fd5d1c9 100644 (file)
@@ -4846,7 +4846,6 @@ static void ql_eeh_close(struct net_device *ndev)
        }
 
        /* Disabling the timer */
-       del_timer_sync(&qdev->timer);
        ql_cancel_all_work_sync(qdev);
 
        for (i = 0; i < qdev->rss_ring_count; i++)
@@ -4873,6 +4872,7 @@ static pci_ers_result_t qlge_io_error_detected(struct pci_dev *pdev,
                return PCI_ERS_RESULT_CAN_RECOVER;
        case pci_channel_io_frozen:
                netif_device_detach(ndev);
+               del_timer_sync(&qdev->timer);
                if (netif_running(ndev))
                        ql_eeh_close(ndev);
                pci_disable_device(pdev);
@@ -4880,6 +4880,7 @@ static pci_ers_result_t qlge_io_error_detected(struct pci_dev *pdev,
        case pci_channel_io_perm_failure:
                dev_err(&pdev->dev,
                        "%s: pci_channel_io_perm_failure.\n", __func__);
+               del_timer_sync(&qdev->timer);
                ql_eeh_close(ndev);
                set_bit(QL_EEH_FATAL, &qdev->flags);
                return PCI_ERS_RESULT_DISCONNECT;
index 1681084..1f30912 100644 (file)
@@ -619,6 +619,17 @@ fail:
        return rc;
 }
 
+static void efx_ef10_forget_old_piobufs(struct efx_nic *efx)
+{
+       struct efx_channel *channel;
+       struct efx_tx_queue *tx_queue;
+
+       /* All our existing PIO buffers went away */
+       efx_for_each_channel(channel, efx)
+               efx_for_each_channel_tx_queue(tx_queue, channel)
+                       tx_queue->piobuf = NULL;
+}
+
 #else /* !EFX_USE_PIO */
 
 static int efx_ef10_alloc_piobufs(struct efx_nic *efx, unsigned int n)
@@ -635,6 +646,10 @@ static void efx_ef10_free_piobufs(struct efx_nic *efx)
 {
 }
 
+static void efx_ef10_forget_old_piobufs(struct efx_nic *efx)
+{
+}
+
 #endif /* EFX_USE_PIO */
 
 static void efx_ef10_remove(struct efx_nic *efx)
@@ -1018,6 +1033,7 @@ static void efx_ef10_reset_mc_allocations(struct efx_nic *efx)
        nic_data->must_realloc_vis = true;
        nic_data->must_restore_filters = true;
        nic_data->must_restore_piobufs = true;
+       efx_ef10_forget_old_piobufs(efx);
        nic_data->rx_rss_context = EFX_EF10_RSS_CONTEXT_INVALID;
 
        /* Driver-created vswitches and vports must be re-created */
index 0705ec8..097f363 100644 (file)
@@ -1726,14 +1726,33 @@ static int efx_probe_filters(struct efx_nic *efx)
 
 #ifdef CONFIG_RFS_ACCEL
        if (efx->type->offload_features & NETIF_F_NTUPLE) {
-               efx->rps_flow_id = kcalloc(efx->type->max_rx_ip_filters,
-                                          sizeof(*efx->rps_flow_id),
-                                          GFP_KERNEL);
-               if (!efx->rps_flow_id) {
+               struct efx_channel *channel;
+               int i, success = 1;
+
+               efx_for_each_channel(channel, efx) {
+                       channel->rps_flow_id =
+                               kcalloc(efx->type->max_rx_ip_filters,
+                                       sizeof(*channel->rps_flow_id),
+                                       GFP_KERNEL);
+                       if (!channel->rps_flow_id)
+                               success = 0;
+                       else
+                               for (i = 0;
+                                    i < efx->type->max_rx_ip_filters;
+                                    ++i)
+                                       channel->rps_flow_id[i] =
+                                               RPS_FLOW_ID_INVALID;
+               }
+
+               if (!success) {
+                       efx_for_each_channel(channel, efx)
+                               kfree(channel->rps_flow_id);
                        efx->type->filter_table_remove(efx);
                        rc = -ENOMEM;
                        goto out_unlock;
                }
+
+               efx->rps_expire_index = efx->rps_expire_channel = 0;
        }
 #endif
 out_unlock:
@@ -1744,7 +1763,10 @@ out_unlock:
 static void efx_remove_filters(struct efx_nic *efx)
 {
 #ifdef CONFIG_RFS_ACCEL
-       kfree(efx->rps_flow_id);
+       struct efx_channel *channel;
+
+       efx_for_each_channel(channel, efx)
+               kfree(channel->rps_flow_id);
 #endif
        down_write(&efx->filter_sem);
        efx->type->filter_table_remove(efx);
index 7f295c4..2a9228a 100644 (file)
@@ -189,11 +189,12 @@ static u32 mcdi_to_ethtool_cap(u32 media, u32 cap)
 
        case MC_CMD_MEDIA_XFP:
        case MC_CMD_MEDIA_SFP_PLUS:
-               result |= SUPPORTED_FIBRE;
-               break;
-
        case MC_CMD_MEDIA_QSFP_PLUS:
                result |= SUPPORTED_FIBRE;
+               if (cap & (1 << MC_CMD_PHY_CAP_1000FDX_LBN))
+                       result |= SUPPORTED_1000baseT_Full;
+               if (cap & (1 << MC_CMD_PHY_CAP_10000FDX_LBN))
+                       result |= SUPPORTED_10000baseT_Full;
                if (cap & (1 << MC_CMD_PHY_CAP_40000FDX_LBN))
                        result |= SUPPORTED_40000baseCR4_Full;
                break;
index 38c4223..d13ddf9 100644 (file)
@@ -403,6 +403,8 @@ enum efx_sync_events_state {
  * @event_test_cpu: Last CPU to handle interrupt or test event for this channel
  * @irq_count: Number of IRQs since last adaptive moderation decision
  * @irq_mod_score: IRQ moderation score
+ * @rps_flow_id: Flow IDs of filters allocated for accelerated RFS,
+ *      indexed by filter ID
  * @n_rx_tobe_disc: Count of RX_TOBE_DISC errors
  * @n_rx_ip_hdr_chksum_err: Count of RX IP header checksum errors
  * @n_rx_tcp_udp_chksum_err: Count of RX TCP and UDP checksum errors
@@ -446,6 +448,8 @@ struct efx_channel {
        unsigned int irq_mod_score;
 #ifdef CONFIG_RFS_ACCEL
        unsigned int rfs_filters_added;
+#define RPS_FLOW_ID_INVALID 0xFFFFFFFF
+       u32 *rps_flow_id;
 #endif
 
        unsigned n_rx_tobe_disc;
@@ -889,9 +893,9 @@ struct vfdi_status;
  * @filter_sem: Filter table rw_semaphore, for freeing the table
  * @filter_lock: Filter table lock, for mere content changes
  * @filter_state: Architecture-dependent filter table state
- * @rps_flow_id: Flow IDs of filters allocated for accelerated RFS,
- *     indexed by filter ID
- * @rps_expire_index: Next index to check for expiry in @rps_flow_id
+ * @rps_expire_channel: Next channel to check for expiry
+ * @rps_expire_index: Next index to check for expiry in
+ *     @rps_expire_channel's @rps_flow_id
  * @active_queues: Count of RX and TX queues that haven't been flushed and drained.
  * @rxq_flush_pending: Count of number of receive queues that need to be flushed.
  *     Decremented when the efx_flush_rx_queue() is called.
@@ -1035,7 +1039,7 @@ struct efx_nic {
        spinlock_t filter_lock;
        void *filter_state;
 #ifdef CONFIG_RFS_ACCEL
-       u32 *rps_flow_id;
+       unsigned int rps_expire_channel;
        unsigned int rps_expire_index;
 #endif
 
index 8956995..02b0b52 100644 (file)
@@ -842,33 +842,18 @@ int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
        struct efx_nic *efx = netdev_priv(net_dev);
        struct efx_channel *channel;
        struct efx_filter_spec spec;
-       const __be16 *ports;
-       __be16 ether_type;
-       int nhoff;
+       struct flow_keys fk;
        int rc;
 
-       /* The core RPS/RFS code has already parsed and validated
-        * VLAN, IP and transport headers.  We assume they are in the
-        * header area.
-        */
-
-       if (skb->protocol == htons(ETH_P_8021Q)) {
-               const struct vlan_hdr *vh =
-                       (const struct vlan_hdr *)skb->data;
+       if (flow_id == RPS_FLOW_ID_INVALID)
+               return -EINVAL;
 
-               /* We can't filter on the IP 5-tuple and the vlan
-                * together, so just strip the vlan header and filter
-                * on the IP part.
-                */
-               EFX_BUG_ON_PARANOID(skb_headlen(skb) < sizeof(*vh));
-               ether_type = vh->h_vlan_encapsulated_proto;
-               nhoff = sizeof(struct vlan_hdr);
-       } else {
-               ether_type = skb->protocol;
-               nhoff = 0;
-       }
+       if (!skb_flow_dissect_flow_keys(skb, &fk, 0))
+               return -EPROTONOSUPPORT;
 
-       if (ether_type != htons(ETH_P_IP) && ether_type != htons(ETH_P_IPV6))
+       if (fk.basic.n_proto != htons(ETH_P_IP) && fk.basic.n_proto != htons(ETH_P_IPV6))
+               return -EPROTONOSUPPORT;
+       if (fk.control.flags & FLOW_DIS_IS_FRAGMENT)
                return -EPROTONOSUPPORT;
 
        efx_filter_init_rx(&spec, EFX_FILTER_PRI_HINT,
@@ -878,56 +863,41 @@ int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
                EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
                EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT |
                EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT;
-       spec.ether_type = ether_type;
-
-       if (ether_type == htons(ETH_P_IP)) {
-               const struct iphdr *ip =
-                       (const struct iphdr *)(skb->data + nhoff);
-
-               EFX_BUG_ON_PARANOID(skb_headlen(skb) < nhoff + sizeof(*ip));
-               if (ip_is_fragment(ip))
-                       return -EPROTONOSUPPORT;
-               spec.ip_proto = ip->protocol;
-               spec.rem_host[0] = ip->saddr;
-               spec.loc_host[0] = ip->daddr;
-               EFX_BUG_ON_PARANOID(skb_headlen(skb) < nhoff + 4 * ip->ihl + 4);
-               ports = (const __be16 *)(skb->data + nhoff + 4 * ip->ihl);
+       spec.ether_type = fk.basic.n_proto;
+       spec.ip_proto = fk.basic.ip_proto;
+
+       if (fk.basic.n_proto == htons(ETH_P_IP)) {
+               spec.rem_host[0] = fk.addrs.v4addrs.src;
+               spec.loc_host[0] = fk.addrs.v4addrs.dst;
        } else {
-               const struct ipv6hdr *ip6 =
-                       (const struct ipv6hdr *)(skb->data + nhoff);
-
-               EFX_BUG_ON_PARANOID(skb_headlen(skb) <
-                                   nhoff + sizeof(*ip6) + 4);
-               spec.ip_proto = ip6->nexthdr;
-               memcpy(spec.rem_host, &ip6->saddr, sizeof(ip6->saddr));
-               memcpy(spec.loc_host, &ip6->daddr, sizeof(ip6->daddr));
-               ports = (const __be16 *)(ip6 + 1);
+               memcpy(spec.rem_host, &fk.addrs.v6addrs.src, sizeof(struct in6_addr));
+               memcpy(spec.loc_host, &fk.addrs.v6addrs.dst, sizeof(struct in6_addr));
        }
 
-       spec.rem_port = ports[0];
-       spec.loc_port = ports[1];
+       spec.rem_port = fk.ports.src;
+       spec.loc_port = fk.ports.dst;
 
        rc = efx->type->filter_rfs_insert(efx, &spec);
        if (rc < 0)
                return rc;
 
        /* Remember this so we can check whether to expire the filter later */
-       efx->rps_flow_id[rc] = flow_id;
-       channel = efx_get_channel(efx, skb_get_rx_queue(skb));
+       channel = efx_get_channel(efx, rxq_index);
+       channel->rps_flow_id[rc] = flow_id;
        ++channel->rfs_filters_added;
 
-       if (ether_type == htons(ETH_P_IP))
+       if (spec.ether_type == htons(ETH_P_IP))
                netif_info(efx, rx_status, efx->net_dev,
                           "steering %s %pI4:%u:%pI4:%u to queue %u [flow %u filter %d]\n",
                           (spec.ip_proto == IPPROTO_TCP) ? "TCP" : "UDP",
-                          spec.rem_host, ntohs(ports[0]), spec.loc_host,
-                          ntohs(ports[1]), rxq_index, flow_id, rc);
+                          spec.rem_host, ntohs(spec.rem_port), spec.loc_host,
+                          ntohs(spec.loc_port), rxq_index, flow_id, rc);
        else
                netif_info(efx, rx_status, efx->net_dev,
                           "steering %s [%pI6]:%u:[%pI6]:%u to queue %u [flow %u filter %d]\n",
                           (spec.ip_proto == IPPROTO_TCP) ? "TCP" : "UDP",
-                          spec.rem_host, ntohs(ports[0]), spec.loc_host,
-                          ntohs(ports[1]), rxq_index, flow_id, rc);
+                          spec.rem_host, ntohs(spec.rem_port), spec.loc_host,
+                          ntohs(spec.loc_port), rxq_index, flow_id, rc);
 
        return rc;
 }
@@ -935,24 +905,34 @@ int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
 bool __efx_filter_rfs_expire(struct efx_nic *efx, unsigned int quota)
 {
        bool (*expire_one)(struct efx_nic *efx, u32 flow_id, unsigned int index);
-       unsigned int index, size;
+       unsigned int channel_idx, index, size;
        u32 flow_id;
 
        if (!spin_trylock_bh(&efx->filter_lock))
                return false;
 
        expire_one = efx->type->filter_rfs_expire_one;
+       channel_idx = efx->rps_expire_channel;
        index = efx->rps_expire_index;
        size = efx->type->max_rx_ip_filters;
        while (quota--) {
-               flow_id = efx->rps_flow_id[index];
-               if (expire_one(efx, flow_id, index))
+               struct efx_channel *channel = efx_get_channel(efx, channel_idx);
+               flow_id = channel->rps_flow_id[index];
+
+               if (flow_id != RPS_FLOW_ID_INVALID &&
+                   expire_one(efx, flow_id, index)) {
                        netif_info(efx, rx_status, efx->net_dev,
-                                  "expired filter %d [flow %u]\n",
-                                  index, flow_id);
-               if (++index == size)
+                                  "expired filter %d [queue %u flow %u]\n",
+                                  index, channel_idx, flow_id);
+                       channel->rps_flow_id[index] = RPS_FLOW_ID_INVALID;
+               }
+               if (++index == size) {
+                       if (++channel_idx == efx->n_channels)
+                               channel_idx = 0;
                        index = 0;
+               }
        }
+       efx->rps_expire_channel = channel_idx;
        efx->rps_expire_index = index;
 
        spin_unlock_bh(&efx->filter_lock);
index 4f7283d..44da877 100644 (file)
@@ -156,7 +156,7 @@ static void dwmac4_set_filter(struct mac_device_info *hw,
                struct netdev_hw_addr *ha;
 
                netdev_for_each_uc_addr(ha, dev) {
-                       dwmac4_set_umac_addr(ioaddr, ha->addr, reg);
+                       dwmac4_set_umac_addr(hw, ha->addr, reg);
                        reg++;
                }
        }
index eac45d0..a473c18 100644 (file)
@@ -3450,8 +3450,6 @@ int stmmac_resume(struct device *dev)
        if (!netif_running(ndev))
                return 0;
 
-       spin_lock_irqsave(&priv->lock, flags);
-
        /* Power Down bit, into the PM register, is cleared
         * automatically as soon as a magic packet or a Wake-up frame
         * is received. Anyway, it's better to manually clear
@@ -3459,7 +3457,9 @@ int stmmac_resume(struct device *dev)
         * from another devices (e.g. serial console).
         */
        if (device_may_wakeup(priv->device)) {
+               spin_lock_irqsave(&priv->lock, flags);
                priv->hw->mac->pmt(priv->hw, 0);
+               spin_unlock_irqrestore(&priv->lock, flags);
                priv->irq_wake = 0;
        } else {
                pinctrl_pm_select_default_state(priv->device);
@@ -3473,6 +3473,8 @@ int stmmac_resume(struct device *dev)
 
        netif_device_attach(ndev);
 
+       spin_lock_irqsave(&priv->lock, flags);
+
        priv->cur_rx = 0;
        priv->dirty_rx = 0;
        priv->dirty_tx = 0;
index 3f83c36..ec29585 100644 (file)
@@ -297,7 +297,7 @@ int stmmac_mdio_register(struct net_device *ndev)
                return -ENOMEM;
 
        if (mdio_bus_data->irqs)
-               memcpy(new_bus->irq, mdio_bus_data, sizeof(new_bus->irq));
+               memcpy(new_bus->irq, mdio_bus_data->irqs, sizeof(new_bus->irq));
 
 #ifdef CONFIG_OF
        if (priv->device->of_node)
index 4b08a2f..e6bb0ec 100644 (file)
@@ -1339,7 +1339,7 @@ static int cpsw_ndo_open(struct net_device *ndev)
        if (priv->coal_intvl != 0) {
                struct ethtool_coalesce coal;
 
-               coal.rx_coalesce_usecs = (priv->coal_intvl << 4);
+               coal.rx_coalesce_usecs = priv->coal_intvl;
                cpsw_set_coalesce(ndev, &coal);
        }
 
index a0f64cb..2ace126 100644 (file)
@@ -990,7 +990,7 @@ static void team_port_disable(struct team *team,
 #define TEAM_ENC_FEATURES      (NETIF_F_HW_CSUM | NETIF_F_SG | \
                                 NETIF_F_RXCSUM | NETIF_F_ALL_TSO)
 
-static void __team_compute_features(struct team *team)
+static void ___team_compute_features(struct team *team)
 {
        struct team_port *port;
        u32 vlan_features = TEAM_VLAN_FEATURES & NETIF_F_ALL_FOR_ALL;
@@ -1021,15 +1021,20 @@ static void __team_compute_features(struct team *team)
        team->dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
        if (dst_release_flag == (IFF_XMIT_DST_RELEASE | IFF_XMIT_DST_RELEASE_PERM))
                team->dev->priv_flags |= IFF_XMIT_DST_RELEASE;
+}
 
+static void __team_compute_features(struct team *team)
+{
+       ___team_compute_features(team);
        netdev_change_features(team->dev);
 }
 
 static void team_compute_features(struct team *team)
 {
        mutex_lock(&team->lock);
-       __team_compute_features(team);
+       ___team_compute_features(team);
        mutex_unlock(&team->lock);
+       netdev_change_features(team->dev);
 }
 
 static int team_port_enter(struct team *team, struct team_port *port)
index 36cd7f0..9bbe016 100644 (file)
@@ -473,7 +473,7 @@ static void read_bulk_callback(struct urb *urb)
                goto goon;
        }
 
-       if (!count || count < 4)
+       if (count < 4)
                goto goon;
 
        rx_status = buf[count - 2];
index d9d2806..dc989a8 100644 (file)
@@ -61,6 +61,8 @@
 #define SUSPEND_ALLMODES               (SUSPEND_SUSPEND0 | SUSPEND_SUSPEND1 | \
                                         SUSPEND_SUSPEND2 | SUSPEND_SUSPEND3)
 
+#define CARRIER_CHECK_DELAY (2 * HZ)
+
 struct smsc95xx_priv {
        u32 mac_cr;
        u32 hash_hi;
@@ -69,6 +71,9 @@ struct smsc95xx_priv {
        spinlock_t mac_cr_lock;
        u8 features;
        u8 suspend_flags;
+       bool link_ok;
+       struct delayed_work carrier_check;
+       struct usbnet *dev;
 };
 
 static bool turbo_mode = true;
@@ -624,6 +629,44 @@ static void smsc95xx_status(struct usbnet *dev, struct urb *urb)
                            intdata);
 }
 
+static void set_carrier(struct usbnet *dev, bool link)
+{
+       struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+
+       if (pdata->link_ok == link)
+               return;
+
+       pdata->link_ok = link;
+
+       if (link)
+               usbnet_link_change(dev, 1, 0);
+       else
+               usbnet_link_change(dev, 0, 0);
+}
+
+static void check_carrier(struct work_struct *work)
+{
+       struct smsc95xx_priv *pdata = container_of(work, struct smsc95xx_priv,
+                                               carrier_check.work);
+       struct usbnet *dev = pdata->dev;
+       int ret;
+
+       if (pdata->suspend_flags != 0)
+               return;
+
+       ret = smsc95xx_mdio_read(dev->net, dev->mii.phy_id, MII_BMSR);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to read MII_BMSR\n");
+               return;
+       }
+       if (ret & BMSR_LSTATUS)
+               set_carrier(dev, 1);
+       else
+               set_carrier(dev, 0);
+
+       schedule_delayed_work(&pdata->carrier_check, CARRIER_CHECK_DELAY);
+}
+
 /* Enable or disable Tx & Rx checksum offload engines */
 static int smsc95xx_set_features(struct net_device *netdev,
        netdev_features_t features)
@@ -1165,13 +1208,20 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
        dev->net->flags |= IFF_MULTICAST;
        dev->net->hard_header_len += SMSC95XX_TX_OVERHEAD_CSUM;
        dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
+
+       pdata->dev = dev;
+       INIT_DELAYED_WORK(&pdata->carrier_check, check_carrier);
+       schedule_delayed_work(&pdata->carrier_check, CARRIER_CHECK_DELAY);
+
        return 0;
 }
 
 static void smsc95xx_unbind(struct usbnet *dev, struct usb_interface *intf)
 {
        struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+
        if (pdata) {
+               cancel_delayed_work(&pdata->carrier_check);
                netif_dbg(dev, ifdown, dev->net, "free pdata\n");
                kfree(pdata);
                pdata = NULL;
@@ -1695,6 +1745,7 @@ static int smsc95xx_resume(struct usb_interface *intf)
 
        /* do this first to ensure it's cleared even in error case */
        pdata->suspend_flags = 0;
+       schedule_delayed_work(&pdata->carrier_check, CARRIER_CHECK_DELAY);
 
        if (suspend_flags & SUSPEND_ALLMODES) {
                /* clear wake-up sources */
index 49d84e5..e0638e5 100644 (file)
@@ -1925,24 +1925,11 @@ static int virtnet_probe(struct virtio_device *vdev)
 
        virtio_device_ready(vdev);
 
-       /* Last of all, set up some receive buffers. */
-       for (i = 0; i < vi->curr_queue_pairs; i++) {
-               try_fill_recv(vi, &vi->rq[i], GFP_KERNEL);
-
-               /* If we didn't even get one input buffer, we're useless. */
-               if (vi->rq[i].vq->num_free ==
-                   virtqueue_get_vring_size(vi->rq[i].vq)) {
-                       free_unused_bufs(vi);
-                       err = -ENOMEM;
-                       goto free_recv_bufs;
-               }
-       }
-
        vi->nb.notifier_call = &virtnet_cpu_callback;
        err = register_hotcpu_notifier(&vi->nb);
        if (err) {
                pr_debug("virtio_net: registering cpu notifier failed\n");
-               goto free_recv_bufs;
+               goto free_unregister_netdev;
        }
 
        /* Assume link up if device can't report link status,
@@ -1960,10 +1947,9 @@ static int virtnet_probe(struct virtio_device *vdev)
 
        return 0;
 
-free_recv_bufs:
+free_unregister_netdev:
        vi->vdev->config->reset(vdev);
 
-       free_receive_bufs(vi);
        unregister_netdev(dev);
 free_vqs:
        cancel_delayed_work_sync(&vi->refill);
index db8022a..08885bc 100644 (file)
@@ -1369,7 +1369,7 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
                                rcdlro = (struct Vmxnet3_RxCompDescExt *)rcd;
 
                                segCnt = rcdlro->segCnt;
-                               BUG_ON(segCnt <= 1);
+                               WARN_ON_ONCE(segCnt == 0);
                                mss = rcdlro->mss;
                                if (unlikely(segCnt <= 1))
                                        segCnt = 0;
index c482539..3d2b64e 100644 (file)
 /*
  * Version numbers
  */
-#define VMXNET3_DRIVER_VERSION_STRING   "1.4.7.0-k"
+#define VMXNET3_DRIVER_VERSION_STRING   "1.4.8.0-k"
 
 /* a 32-bit int, each byte encode a verion number in VMXNET3_DRIVER_VERSION */
-#define VMXNET3_DRIVER_VERSION_NUM      0x01040700
+#define VMXNET3_DRIVER_VERSION_NUM      0x01040800
 
 #if defined(CONFIG_PCI_MSI)
        /* RSS only makes sense if MSI-X is supported. */
index 8ff30c3..f999db2 100644 (file)
@@ -3086,6 +3086,9 @@ static int vxlan_newlink(struct net *src_net, struct net_device *dev,
        if (data[IFLA_VXLAN_REMCSUM_NOPARTIAL])
                conf.flags |= VXLAN_F_REMCSUM_NOPARTIAL;
 
+       if (tb[IFLA_MTU])
+               conf.mtu = nla_get_u32(tb[IFLA_MTU]);
+
        err = vxlan_dev_configure(src_net, dev, &conf);
        switch (err) {
        case -ENODEV:
index d0631b6..62f475e 100644 (file)
@@ -2540,12 +2540,14 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
                           const u8 *mac, struct station_info *sinfo)
 {
        struct brcmf_if *ifp = netdev_priv(ndev);
+       struct brcmf_scb_val_le scb_val;
        s32 err = 0;
        struct brcmf_sta_info_le sta_info_le;
        u32 sta_flags;
        u32 is_tdls_peer;
        s32 total_rssi;
        s32 count_rssi;
+       int rssi;
        u32 i;
 
        brcmf_dbg(TRACE, "Enter, MAC %pM\n", mac);
@@ -2629,6 +2631,20 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
                        sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
                        total_rssi /= count_rssi;
                        sinfo->signal = total_rssi;
+               } else if (test_bit(BRCMF_VIF_STATUS_CONNECTED,
+                       &ifp->vif->sme_state)) {
+                       memset(&scb_val, 0, sizeof(scb_val));
+                       err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_RSSI,
+                                                    &scb_val, sizeof(scb_val));
+                       if (err) {
+                               brcmf_err("Could not get rssi (%d)\n", err);
+                               goto done;
+                       } else {
+                               rssi = le32_to_cpu(scb_val.val);
+                               sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
+                               sinfo->signal = rssi;
+                               brcmf_dbg(CONN, "RSSI %d dBm\n", rssi);
+                       }
                }
        }
 done:
index 68f1ce0..2b9a2bc 100644 (file)
@@ -1157,6 +1157,8 @@ brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf)
                brcmu_pkt_buf_free_skb(skb);
                return;
        }
+
+       skb->protocol = eth_type_trans(skb, ifp->ndev);
        brcmf_netif_rx(ifp, skb);
 }
 
index 9ed0ed1..4dd5adc 100644 (file)
@@ -2776,6 +2776,7 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
        if (!info->attrs[HWSIM_ATTR_ADDR_TRANSMITTER] ||
            !info->attrs[HWSIM_ATTR_FLAGS] ||
            !info->attrs[HWSIM_ATTR_COOKIE] ||
+           !info->attrs[HWSIM_ATTR_SIGNAL] ||
            !info->attrs[HWSIM_ATTR_TX_INFO])
                goto out;
 
index 0f48048..3a0faa8 100644 (file)
@@ -54,7 +54,7 @@ EXPORT_SYMBOL(channel5g_80m);
 void rtl_addr_delay(u32 addr)
 {
        if (addr == 0xfe)
-               msleep(50);
+               mdelay(50);
        else if (addr == 0xfd)
                msleep(5);
        else if (addr == 0xfc)
@@ -75,7 +75,7 @@ void rtl_rfreg_delay(struct ieee80211_hw *hw, enum radio_path rfpath, u32 addr,
                rtl_addr_delay(addr);
        } else {
                rtl_set_rfreg(hw, rfpath, addr, mask, data);
-               usleep_range(1, 2);
+               udelay(1);
        }
 }
 EXPORT_SYMBOL(rtl_rfreg_delay);
@@ -86,7 +86,7 @@ void rtl_bb_delay(struct ieee80211_hw *hw, u32 addr, u32 data)
                rtl_addr_delay(addr);
        } else {
                rtl_set_bbreg(hw, addr, MASKDWORD, data);
-               usleep_range(1, 2);
+               udelay(1);
        }
 }
 EXPORT_SYMBOL(rtl_bb_delay);
index 78dca31..befac5b 100644 (file)
@@ -1679,9 +1679,14 @@ static int nvme_pci_enable(struct nvme_dev *dev)
 
 static void nvme_dev_unmap(struct nvme_dev *dev)
 {
+       struct pci_dev *pdev = to_pci_dev(dev->dev);
+       int bars;
+
        if (dev->bar)
                iounmap(dev->bar);
-       pci_release_regions(to_pci_dev(dev->dev));
+
+       bars = pci_select_bars(pdev, IORESOURCE_MEM);
+       pci_release_selected_regions(pdev, bars);
 }
 
 static void nvme_pci_disable(struct nvme_dev *dev)
@@ -1924,7 +1929,7 @@ static int nvme_dev_map(struct nvme_dev *dev)
 
        return 0;
   release:
-       pci_release_regions(pdev);
+       pci_release_selected_regions(pdev, bars);
        return -ENODEV;
 }
 
index 14f2f8c..33daffc 100644 (file)
@@ -395,7 +395,7 @@ static int unflatten_dt_nodes(const void *blob,
                              struct device_node **nodepp)
 {
        struct device_node *root;
-       int offset = 0, depth = 0;
+       int offset = 0, depth = 0, initial_depth = 0;
 #define FDT_MAX_DEPTH  64
        unsigned int fpsizes[FDT_MAX_DEPTH];
        struct device_node *nps[FDT_MAX_DEPTH];
@@ -405,11 +405,22 @@ static int unflatten_dt_nodes(const void *blob,
        if (nodepp)
                *nodepp = NULL;
 
+       /*
+        * We're unflattening device sub-tree if @dad is valid. There are
+        * possibly multiple nodes in the first level of depth. We need
+        * set @depth to 1 to make fdt_next_node() happy as it bails
+        * immediately when negative @depth is found. Otherwise, the device
+        * nodes except the first one won't be unflattened successfully.
+        */
+       if (dad)
+               depth = initial_depth = 1;
+
        root = dad;
        fpsizes[depth] = dad ? strlen(of_node_full_name(dad)) : 0;
        nps[depth] = dad;
+
        for (offset = 0;
-            offset >= 0 && depth >= 0;
+            offset >= 0 && depth >= initial_depth;
             offset = fdt_next_node(blob, offset, &depth)) {
                if (WARN_ON_ONCE(depth >= FDT_MAX_DEPTH))
                        continue;
index e7bfc17..6ec743f 100644 (file)
@@ -386,13 +386,13 @@ int of_irq_to_resource(struct device_node *dev, int index, struct resource *r)
 EXPORT_SYMBOL_GPL(of_irq_to_resource);
 
 /**
- * of_irq_get - Decode a node's IRQ and return it as a Linux irq number
+ * of_irq_get - Decode a node's IRQ and return it as a Linux IRQ number
  * @dev: pointer to device tree node
- * @index: zero-based index of the irq
- *
- * Returns Linux irq number on success, or -EPROBE_DEFER if the irq domain
- * is not yet created.
+ * @index: zero-based index of the IRQ
  *
+ * Returns Linux IRQ number on success, or 0 on the IRQ mapping failure, or
+ * -EPROBE_DEFER if the IRQ domain is not yet created, or error code in case
+ * of any other failure.
  */
 int of_irq_get(struct device_node *dev, int index)
 {
@@ -413,12 +413,13 @@ int of_irq_get(struct device_node *dev, int index)
 EXPORT_SYMBOL_GPL(of_irq_get);
 
 /**
- * of_irq_get_byname - Decode a node's IRQ and return it as a Linux irq number
+ * of_irq_get_byname - Decode a node's IRQ and return it as a Linux IRQ number
  * @dev: pointer to device tree node
- * @name: irq name
+ * @name: IRQ name
  *
- * Returns Linux irq number on success, or -EPROBE_DEFER if the irq domain
- * is not yet created, or error code in case of any other failure.
+ * Returns Linux IRQ number on success, or 0 on the IRQ mapping failure, or
+ * -EPROBE_DEFER if the IRQ domain is not yet created, or error code in case
+ * of any other failure.
  */
 int of_irq_get_byname(struct device_node *dev, const char *name)
 {
index ed01c01..2166482 100644 (file)
@@ -127,8 +127,15 @@ static int __init __reserved_mem_alloc_size(unsigned long node,
        }
 
        /* Need adjust the alignment to satisfy the CMA requirement */
-       if (IS_ENABLED(CONFIG_CMA) && of_flat_dt_is_compatible(node, "shared-dma-pool"))
-               align = max(align, (phys_addr_t)PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order));
+       if (IS_ENABLED(CONFIG_CMA)
+           && of_flat_dt_is_compatible(node, "shared-dma-pool")
+           && of_get_flat_dt_prop(node, "reusable", NULL)
+           && !of_get_flat_dt_prop(node, "no-map", NULL)) {
+               unsigned long order =
+                       max_t(unsigned long, MAX_ORDER - 1, pageblock_order);
+
+               align = max(align, (phys_addr_t)PAGE_SIZE << order);
+       }
 
        prop = of_get_flat_dt_prop(node, "alloc-ranges", &len);
        if (prop) {
index dfbab61..1fa3a32 100644 (file)
@@ -221,9 +221,9 @@ static int pci_vc_do_save_buffer(struct pci_dev *dev, int pos,
                else
                        pci_write_config_word(dev, pos + PCI_VC_PORT_CTRL,
                                              *(u16 *)buf);
-               buf += 2;
+               buf += 4;
        }
-       len += 2;
+       len += 4;
 
        /*
         * If we have any Low Priority VCs and a VC Arbitration Table Offset
index f2d01d4..140436a 100644 (file)
@@ -950,17 +950,14 @@ static int of_pmu_irq_cfg(struct arm_pmu *pmu)
 
                /* For SPIs, we need to track the affinity per IRQ */
                if (using_spi) {
-                       if (i >= pdev->num_resources) {
-                               of_node_put(dn);
+                       if (i >= pdev->num_resources)
                                break;
-                       }
 
                        irqs[i] = cpu;
                }
 
                /* Keep track of the CPUs containing this PMU type */
                cpumask_set_cpu(cpu, &pmu->supported_cpus);
-               of_node_put(dn);
                i++;
        } while (1);
 
@@ -995,9 +992,6 @@ int arm_pmu_device_probe(struct platform_device *pdev,
 
        armpmu_init(pmu);
 
-       if (!__oprofile_cpu_pmu)
-               __oprofile_cpu_pmu = pmu;
-
        pmu->plat_device = pdev;
 
        if (node && (of_id = of_match_node(of_table, pdev->dev.of_node))) {
@@ -1016,8 +1010,8 @@ int arm_pmu_device_probe(struct platform_device *pdev,
                if (!ret)
                        ret = init_fn(pmu);
        } else {
-               ret = probe_current_pmu(pmu, probe_table);
                cpumask_setall(&pmu->supported_cpus);
+               ret = probe_current_pmu(pmu, probe_table);
        }
 
        if (ret) {
@@ -1033,6 +1027,9 @@ int arm_pmu_device_probe(struct platform_device *pdev,
        if (ret)
                goto out_destroy;
 
+       if (!__oprofile_cpu_pmu)
+               __oprofile_cpu_pmu = pmu;
+
        pr_info("enabled with %s PMU driver, %d counters available\n",
                        pmu->name, pmu->num_events);
 
@@ -1043,6 +1040,7 @@ out_destroy:
 out_free:
        pr_info("%s: failed to register PMU devices!\n",
                of_node_full_name(node));
+       kfree(pmu->irq_affinity);
        kfree(pmu);
        return ret;
 }
index cc093eb..8b851f7 100644 (file)
@@ -233,8 +233,12 @@ static inline int __is_running(const struct exynos_mipi_phy_desc *data,
                        struct exynos_mipi_video_phy *state)
 {
        u32 val;
+       int ret;
+
+       ret = regmap_read(state->regmaps[data->resetn_map], data->resetn_reg, &val);
+       if (ret)
+               return 0;
 
-       regmap_read(state->regmaps[data->resetn_map], data->resetn_reg, &val);
        return val & data->resetn_val;
 }
 
index 0a477d2..bf46844 100644 (file)
@@ -293,11 +293,18 @@ static int ti_pipe3_init(struct phy *x)
                ret = ti_pipe3_dpll_wait_lock(phy);
        }
 
-       /* Program the DPLL only if not locked */
+       /* SATA has issues if re-programmed when locked */
        val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
-       if (!(val & PLL_LOCK))
-               if (ti_pipe3_dpll_program(phy))
-                       return -EINVAL;
+       if ((val & PLL_LOCK) && of_device_is_compatible(phy->dev->of_node,
+                                                       "ti,phy-pipe3-sata"))
+               return ret;
+
+       /* Program the DPLL */
+       ret = ti_pipe3_dpll_program(phy);
+       if (ret) {
+               ti_pipe3_disable_clocks(phy);
+               return -EINVAL;
+       }
 
        return ret;
 }
index 6b6af6c..d9b10a3 100644 (file)
@@ -463,7 +463,8 @@ static int twl4030_phy_power_on(struct phy *phy)
        twl4030_usb_set_mode(twl, twl->usb_mode);
        if (twl->usb_mode == T2_USB_MODE_ULPI)
                twl4030_i2c_access(twl, 0);
-       schedule_delayed_work(&twl->id_workaround_work, 0);
+       twl->linkstat = MUSB_UNKNOWN;
+       schedule_delayed_work(&twl->id_workaround_work, HZ);
 
        return 0;
 }
@@ -537,6 +538,7 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
        struct twl4030_usb *twl = _twl;
        enum musb_vbus_id_status status;
        bool status_changed = false;
+       int err;
 
        status = twl4030_usb_linkstat(twl);
 
@@ -567,7 +569,9 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
                        pm_runtime_mark_last_busy(twl->dev);
                        pm_runtime_put_autosuspend(twl->dev);
                }
-               musb_mailbox(status);
+               err = musb_mailbox(status);
+               if (err)
+                       twl->linkstat = MUSB_UNKNOWN;
        }
 
        /* don't schedule during sleep - irq works right then */
@@ -595,7 +599,8 @@ static int twl4030_phy_init(struct phy *phy)
        struct twl4030_usb *twl = phy_get_drvdata(phy);
 
        pm_runtime_get_sync(twl->dev);
-       schedule_delayed_work(&twl->id_workaround_work, 0);
+       twl->linkstat = MUSB_UNKNOWN;
+       schedule_delayed_work(&twl->id_workaround_work, HZ);
        pm_runtime_mark_last_busy(twl->dev);
        pm_runtime_put_autosuspend(twl->dev);
 
@@ -763,7 +768,8 @@ static int twl4030_usb_remove(struct platform_device *pdev)
        if (cable_present(twl->linkstat))
                pm_runtime_put_noidle(twl->dev);
        pm_runtime_mark_last_busy(twl->dev);
-       pm_runtime_put_sync_suspend(twl->dev);
+       pm_runtime_dont_use_autosuspend(&pdev->dev);
+       pm_runtime_put_sync(twl->dev);
        pm_runtime_disable(twl->dev);
 
        /* autogate 60MHz ULPI clock,
index 207b13b..a607655 100644 (file)
@@ -1256,9 +1256,10 @@ static void mtk_eint_irq_handler(struct irq_desc *desc)
        const struct mtk_desc_pin *pin;
 
        chained_irq_enter(chip, desc);
-       for (eint_num = 0; eint_num < pctl->devdata->ap_num; eint_num += 32) {
+       for (eint_num = 0;
+            eint_num < pctl->devdata->ap_num;
+            eint_num += 32, reg += 4) {
                status = readl(reg);
-               reg += 4;
                while (status) {
                        offset = __ffs(status);
                        index = eint_num + offset;
index ccbfc32..38facef 100644 (file)
@@ -854,7 +854,7 @@ static int nmk_gpio_get_dir(struct gpio_chip *chip, unsigned offset)
 
        clk_enable(nmk_chip->clk);
 
-       dir = !!(readl(nmk_chip->addr + NMK_GPIO_DIR) & BIT(offset));
+       dir = !(readl(nmk_chip->addr + NMK_GPIO_DIR) & BIT(offset));
 
        clk_disable(nmk_chip->clk);
 
index c06bb85..3ec0025 100644 (file)
@@ -103,7 +103,6 @@ config DELL_SMBIOS
 
 config DELL_LAPTOP
        tristate "Dell Laptop Extras"
-       depends on X86
        depends on DELL_SMBIOS
        depends on DMI
        depends on BACKLIGHT_CLASS_DEVICE
@@ -505,7 +504,7 @@ config THINKPAD_ACPI_HOTKEY_POLL
 
 config SENSORS_HDAPS
        tristate "Thinkpad Hard Drive Active Protection System (hdaps)"
-       depends on INPUT && X86
+       depends on INPUT
        select INPUT_POLLDEV
        default n
        help
@@ -749,7 +748,7 @@ config TOSHIBA_WMI
 
 config ACPI_CMPC
        tristate "CMPC Laptop Extras"
-       depends on X86 && ACPI
+       depends on ACPI
        depends on RFKILL || RFKILL=n
        select INPUT
        select BACKLIGHT_CLASS_DEVICE
@@ -848,7 +847,7 @@ config INTEL_IMR
 
 config INTEL_PMC_CORE
        bool "Intel PMC Core driver"
-       depends on X86 && PCI
+       depends on PCI
        ---help---
          The Intel Platform Controller Hub for Intel Core SoCs provides access
          to Power Management Controller registers via a PCI interface. This
@@ -860,7 +859,7 @@ config INTEL_PMC_CORE
 
 config IBM_RTL
        tristate "Device driver to enable PRTL support"
-       depends on X86 && PCI
+       depends on PCI
        ---help---
         Enable support for IBM Premium Real Time Mode (PRTM).
         This module will allow you the enter and exit PRTM in the BIOS via
@@ -894,7 +893,6 @@ config XO15_EBOOK
 
 config SAMSUNG_LAPTOP
        tristate "Samsung Laptop driver"
-       depends on X86
        depends on RFKILL || RFKILL = n
        depends on ACPI_VIDEO || ACPI_VIDEO = n
        depends on BACKLIGHT_CLASS_DEVICE
index 4a23fbc..d1a091b 100644 (file)
@@ -567,6 +567,7 @@ static void ideapad_sysfs_exit(struct ideapad_private *priv)
 static const struct key_entry ideapad_keymap[] = {
        { KE_KEY, 6,  { KEY_SWITCHVIDEOMODE } },
        { KE_KEY, 7,  { KEY_CAMERA } },
+       { KE_KEY, 8,  { KEY_MICMUTE } },
        { KE_KEY, 11, { KEY_F16 } },
        { KE_KEY, 13, { KEY_WLAN } },
        { KE_KEY, 16, { KEY_PROG1 } },
@@ -809,6 +810,7 @@ static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data)
                                break;
                        case 13:
                        case 11:
+                       case 8:
                        case 7:
                        case 6:
                                ideapad_input_report(priv, vpc_bit);
index c3bfa1f..b65ce75 100644 (file)
@@ -2043,6 +2043,7 @@ static int hotkey_autosleep_ack;
 
 static u32 hotkey_orig_mask;           /* events the BIOS had enabled */
 static u32 hotkey_all_mask;            /* all events supported in fw */
+static u32 hotkey_adaptive_all_mask;   /* all adaptive events supported in fw */
 static u32 hotkey_reserved_mask;       /* events better left disabled */
 static u32 hotkey_driver_mask;         /* events needed by the driver */
 static u32 hotkey_user_mask;           /* events visible to userspace */
@@ -2742,6 +2743,17 @@ static ssize_t hotkey_all_mask_show(struct device *dev,
 
 static DEVICE_ATTR_RO(hotkey_all_mask);
 
+/* sysfs hotkey all_mask ----------------------------------------------- */
+static ssize_t hotkey_adaptive_all_mask_show(struct device *dev,
+                          struct device_attribute *attr,
+                          char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "0x%08x\n",
+                       hotkey_adaptive_all_mask | hotkey_source_mask);
+}
+
+static DEVICE_ATTR_RO(hotkey_adaptive_all_mask);
+
 /* sysfs hotkey recommended_mask --------------------------------------- */
 static ssize_t hotkey_recommended_mask_show(struct device *dev,
                                            struct device_attribute *attr,
@@ -2985,6 +2997,7 @@ static struct attribute *hotkey_attributes[] __initdata = {
        &dev_attr_wakeup_hotunplug_complete.attr,
        &dev_attr_hotkey_mask.attr,
        &dev_attr_hotkey_all_mask.attr,
+       &dev_attr_hotkey_adaptive_all_mask.attr,
        &dev_attr_hotkey_recommended_mask.attr,
 #ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
        &dev_attr_hotkey_source_mask.attr,
@@ -3321,20 +3334,6 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
        if (!tp_features.hotkey)
                return 1;
 
-       /*
-        * Check if we have an adaptive keyboard, like on the
-        * Lenovo Carbon X1 2014 (2nd Gen).
-        */
-       if (acpi_evalf(hkey_handle, &hkeyv, "MHKV", "qd")) {
-               if ((hkeyv >> 8) == 2) {
-                       tp_features.has_adaptive_kbd = true;
-                       res = sysfs_create_group(&tpacpi_pdev->dev.kobj,
-                                       &adaptive_kbd_attr_group);
-                       if (res)
-                               goto err_exit;
-               }
-       }
-
        quirks = tpacpi_check_quirks(tpacpi_hotkey_qtable,
                                     ARRAY_SIZE(tpacpi_hotkey_qtable));
 
@@ -3357,30 +3356,70 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
           A30, R30, R31, T20-22, X20-21, X22-24.  Detected by checking
           for HKEY interface version 0x100 */
        if (acpi_evalf(hkey_handle, &hkeyv, "MHKV", "qd")) {
-               if ((hkeyv >> 8) != 1) {
-                       pr_err("unknown version of the HKEY interface: 0x%x\n",
-                              hkeyv);
-                       pr_err("please report this to %s\n", TPACPI_MAIL);
-               } else {
+               vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
+                           "firmware HKEY interface version: 0x%x\n",
+                           hkeyv);
+
+               switch (hkeyv >> 8) {
+               case 1:
                        /*
                         * MHKV 0x100 in A31, R40, R40e,
                         * T4x, X31, and later
                         */
-                       vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
-                               "firmware HKEY interface version: 0x%x\n",
-                               hkeyv);
 
                        /* Paranoia check AND init hotkey_all_mask */
                        if (!acpi_evalf(hkey_handle, &hotkey_all_mask,
                                        "MHKA", "qd")) {
-                               pr_err("missing MHKA handler, "
-                                      "please report this to %s\n",
+                               pr_err("missing MHKA handler, please report this to %s\n",
                                       TPACPI_MAIL);
                                /* Fallback: pre-init for FN+F3,F4,F12 */
                                hotkey_all_mask = 0x080cU;
                        } else {
                                tp_features.hotkey_mask = 1;
                        }
+                       break;
+
+               case 2:
+                       /*
+                        * MHKV 0x200 in X1, T460s, X260, T560, X1 Tablet (2016)
+                        */
+
+                       /* Paranoia check AND init hotkey_all_mask */
+                       if (!acpi_evalf(hkey_handle, &hotkey_all_mask,
+                                       "MHKA", "dd", 1)) {
+                               pr_err("missing MHKA handler, please report this to %s\n",
+                                      TPACPI_MAIL);
+                               /* Fallback: pre-init for FN+F3,F4,F12 */
+                               hotkey_all_mask = 0x080cU;
+                       } else {
+                               tp_features.hotkey_mask = 1;
+                       }
+
+                       /*
+                        * Check if we have an adaptive keyboard, like on the
+                        * Lenovo Carbon X1 2014 (2nd Gen).
+                        */
+                       if (acpi_evalf(hkey_handle, &hotkey_adaptive_all_mask,
+                                      "MHKA", "dd", 2)) {
+                               if (hotkey_adaptive_all_mask != 0) {
+                                       tp_features.has_adaptive_kbd = true;
+                                       res = sysfs_create_group(
+                                               &tpacpi_pdev->dev.kobj,
+                                               &adaptive_kbd_attr_group);
+                                       if (res)
+                                               goto err_exit;
+                               }
+                       } else {
+                               tp_features.has_adaptive_kbd = false;
+                               hotkey_adaptive_all_mask = 0x0U;
+                       }
+                       break;
+
+               default:
+                       pr_err("unknown version of the HKEY interface: 0x%x\n",
+                              hkeyv);
+                       pr_err("please report this to %s\n", TPACPI_MAIL);
+                       break;
                }
        }
 
index 579fd65..d637c93 100644 (file)
@@ -208,14 +208,10 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
                break;
 
        case PTP_SYS_OFFSET:
-               sysoff = kmalloc(sizeof(*sysoff), GFP_KERNEL);
-               if (!sysoff) {
-                       err = -ENOMEM;
-                       break;
-               }
-               if (copy_from_user(sysoff, (void __user *)arg,
-                                  sizeof(*sysoff))) {
-                       err = -EFAULT;
+               sysoff = memdup_user((void __user *)arg, sizeof(*sysoff));
+               if (IS_ERR(sysoff)) {
+                       err = PTR_ERR(sysoff);
+                       sysoff = NULL;
                        break;
                }
                if (sysoff->n_samples > PTP_MAX_SAMPLES) {
index dba3843..ed337a8 100644 (file)
@@ -457,7 +457,8 @@ int pwm_apply_state(struct pwm_device *pwm, struct pwm_state *state)
 {
        int err;
 
-       if (!pwm)
+       if (!pwm || !state || !state->period ||
+           state->duty_cycle > state->period)
                return -EINVAL;
 
        if (!memcmp(state, &pwm->state, sizeof(*state)))
index f994c7e..14fc011 100644 (file)
@@ -272,7 +272,7 @@ static int atmel_hlcdc_pwm_probe(struct platform_device *pdev)
        chip->chip.of_pwm_n_cells = 3;
        chip->chip.can_sleep = 1;
 
-       ret = pwmchip_add(&chip->chip);
+       ret = pwmchip_add_with_polarity(&chip->chip, PWM_POLARITY_INVERSED);
        if (ret) {
                clk_disable_unprepare(hlcdc->periph_clk);
                return ret;
index d985992..01695d4 100644 (file)
@@ -152,7 +152,7 @@ static ssize_t enable_store(struct device *child,
                goto unlock;
        }
 
-       pwm_apply_state(pwm, &state);
+       ret = pwm_apply_state(pwm, &state);
 
 unlock:
        mutex_unlock(&export->lock);
index 56a17ec..526bf23 100644 (file)
@@ -140,6 +140,19 @@ static const struct regulator_ops rpm_smps_ldo_ops = {
        .enable = rpm_reg_enable,
        .disable = rpm_reg_disable,
        .is_enabled = rpm_reg_is_enabled,
+       .list_voltage = regulator_list_voltage_linear_range,
+
+       .get_voltage = rpm_reg_get_voltage,
+       .set_voltage = rpm_reg_set_voltage,
+
+       .set_load = rpm_reg_set_load,
+};
+
+static const struct regulator_ops rpm_smps_ldo_ops_fixed = {
+       .enable = rpm_reg_enable,
+       .disable = rpm_reg_disable,
+       .is_enabled = rpm_reg_is_enabled,
+       .list_voltage = regulator_list_voltage_linear_range,
 
        .get_voltage = rpm_reg_get_voltage,
        .set_voltage = rpm_reg_set_voltage,
@@ -247,7 +260,7 @@ static const struct regulator_desc pm8941_nldo = {
 static const struct regulator_desc pm8941_lnldo = {
        .fixed_uV = 1740000,
        .n_voltages = 1,
-       .ops = &rpm_smps_ldo_ops,
+       .ops = &rpm_smps_ldo_ops_fixed,
 };
 
 static const struct regulator_desc pm8941_switch = {
index 572816e..c139890 100644 (file)
@@ -94,11 +94,14 @@ static int tps51632_dcdc_set_ramp_delay(struct regulator_dev *rdev,
                int ramp_delay)
 {
        struct tps51632_chip *tps = rdev_get_drvdata(rdev);
-       int bit = ramp_delay/6000;
+       int bit;
        int ret;
 
-       if (bit)
-               bit--;
+       if (ramp_delay == 0)
+               bit = 0;
+       else
+               bit = DIV_ROUND_UP(ramp_delay, 6000) - 1;
+
        ret = regmap_write(tps->regmap, TPS51632_SLEW_REGS, BIT(bit));
        if (ret < 0)
                dev_err(tps->dev, "SLEW reg write failed, err %d\n", ret);
index d4c2856..3ddc85e 100644 (file)
@@ -1122,7 +1122,7 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp,
                } else {
                        struct scsi_cmnd *SCp;
 
-                       SCp = scsi_host_find_tag(SDp->host, SCSI_NO_TAG);
+                       SCp = SDp->current_cmnd;
                        if(unlikely(SCp == NULL)) {
                                sdev_printk(KERN_ERR, SDp,
                                        "no saved request for untagged cmd\n");
@@ -1826,7 +1826,7 @@ NCR_700_queuecommand_lck(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *)
                       slot->tag, slot);
        } else {
                slot->tag = SCSI_NO_TAG;
-               /* must populate current_cmnd for scsi_host_find_tag to work */
+               /* save current command for reselection */
                SCp->device->current_cmnd = SCp;
        }
        /* sanity check: some of the commands generated by the mid-layer
index 8f90d9e..969c312 100644 (file)
@@ -620,6 +620,11 @@ struct aac_driver_ident
  */
 #define AAC_QUIRK_SCSI_32      0x0020
 
+/*
+ * SRC based adapters support the AifReqEvent functions
+ */
+#define AAC_QUIRK_SRC 0x0040
+
 /*
  *     The adapter interface specs all queues to be located in the same
  *     physically contiguous block. The host structure that defines the
index a943bd2..79871f3 100644 (file)
@@ -236,10 +236,10 @@ static struct aac_driver_ident aac_drivers[] = {
        { aac_rx_init, "aacraid",  "ADAPTEC ", "RAID            ", 2 }, /* Adaptec Catch All */
        { aac_rkt_init, "aacraid", "ADAPTEC ", "RAID            ", 2 }, /* Adaptec Rocket Catch All */
        { aac_nark_init, "aacraid", "ADAPTEC ", "RAID           ", 2 }, /* Adaptec NEMER/ARK Catch All */
-       { aac_src_init, "aacraid", "ADAPTEC ", "RAID            ", 2 }, /* Adaptec PMC Series 6 (Tupelo) */
-       { aac_srcv_init, "aacraid", "ADAPTEC ", "RAID            ", 2 }, /* Adaptec PMC Series 7 (Denali) */
-       { aac_srcv_init, "aacraid", "ADAPTEC ", "RAID            ", 2 }, /* Adaptec PMC Series 8 */
-       { aac_srcv_init, "aacraid", "ADAPTEC ", "RAID            ", 2 } /* Adaptec PMC Series 9 */
+       { aac_src_init, "aacraid", "ADAPTEC ", "RAID            ", 2, AAC_QUIRK_SRC }, /* Adaptec PMC Series 6 (Tupelo) */
+       { aac_srcv_init, "aacraid", "ADAPTEC ", "RAID            ", 2, AAC_QUIRK_SRC }, /* Adaptec PMC Series 7 (Denali) */
+       { aac_srcv_init, "aacraid", "ADAPTEC ", "RAID            ", 2, AAC_QUIRK_SRC }, /* Adaptec PMC Series 8 */
+       { aac_srcv_init, "aacraid", "ADAPTEC ", "RAID            ", 2, AAC_QUIRK_SRC } /* Adaptec PMC Series 9 */
 };
 
 /**
@@ -1299,7 +1299,8 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        else
                shost->this_id = shost->max_id;
 
-       aac_intr_normal(aac, 0, 2, 0, NULL);
+       if (aac_drivers[index].quirks & AAC_QUIRK_SRC)
+               aac_intr_normal(aac, 0, 2, 0, NULL);
 
        /*
         * dmb - we may need to move the setting of these parms somewhere else once
index 6a4df5a..6bff13e 100644 (file)
@@ -7975,13 +7975,14 @@ mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index,
                ActiveCableEventData =
                    (Mpi26EventDataActiveCableExcept_t *) mpi_reply->EventData;
                if (ActiveCableEventData->ReasonCode ==
-                               MPI26_EVENT_ACTIVE_CABLE_INSUFFICIENT_POWER)
+                               MPI26_EVENT_ACTIVE_CABLE_INSUFFICIENT_POWER) {
                        pr_info(MPT3SAS_FMT "Currently an active cable with ReceptacleID %d",
                            ioc->name, ActiveCableEventData->ReceptacleID);
                        pr_info("cannot be powered and devices connected to this active cable");
                        pr_info("will not be seen. This active cable");
                        pr_info("requires %d mW of power",
                            ActiveCableEventData->ActiveCablePowerRequirement);
+               }
                break;
 
        default: /* ignore the rest */
index 3408578..ff41c31 100644 (file)
@@ -230,6 +230,7 @@ static struct {
        {"PIONEER", "CD-ROM DRM-624X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
        {"Promise", "VTrak E610f", NULL, BLIST_SPARSELUN | BLIST_NO_RSOC},
        {"Promise", "", NULL, BLIST_SPARSELUN},
+       {"QEMU", "QEMU CD-ROM", NULL, BLIST_SKIP_VPD_PAGES},
        {"QNAP", "iSCSI Storage", NULL, BLIST_MAX_1024},
        {"SYNOLOGY", "iSCSI Storage", NULL, BLIST_MAX_1024},
        {"QUANTUM", "XP34301", "1071", BLIST_NOTQ},
index a8b610e..106a6ad 100644 (file)
@@ -1128,7 +1128,6 @@ static int scsi_eh_action(struct scsi_cmnd *scmd, int rtn)
  */
 void scsi_eh_finish_cmd(struct scsi_cmnd *scmd, struct list_head *done_q)
 {
-       scmd->device->host->host_failed--;
        scmd->eh_eflags = 0;
        list_move_tail(&scmd->eh_entry, done_q);
 }
@@ -2227,6 +2226,9 @@ int scsi_error_handler(void *data)
                else
                        scsi_unjam_host(shost);
 
+               /* All scmds have been handled */
+               shost->host_failed = 0;
+
                /*
                 * Note - if the above fails completely, the action is to take
                 * individual devices offline and flush the queue of any
index b2e332a..c71344a 100644 (file)
@@ -821,9 +821,12 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
        }
 
        /*
-        * If we finished all bytes in the request we are done now.
+        * special case: failed zero length commands always need to
+        * drop down into the retry code. Otherwise, if we finished
+        * all bytes in the request we are done now.
         */
-       if (!scsi_end_request(req, error, good_bytes, 0))
+       if (!(blk_rq_bytes(req) == 0 && error) &&
+           !scsi_end_request(req, error, good_bytes, 0))
                return;
 
        /*
index 428c03e..60bff78 100644 (file)
@@ -1398,11 +1398,15 @@ static int media_not_present(struct scsi_disk *sdkp,
  **/
 static unsigned int sd_check_events(struct gendisk *disk, unsigned int clearing)
 {
-       struct scsi_disk *sdkp = scsi_disk(disk);
-       struct scsi_device *sdp = sdkp->device;
+       struct scsi_disk *sdkp = scsi_disk_get(disk);
+       struct scsi_device *sdp;
        struct scsi_sense_hdr *sshdr = NULL;
        int retval;
 
+       if (!sdkp)
+               return 0;
+
+       sdp = sdkp->device;
        SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_check_events\n"));
 
        /*
@@ -1459,6 +1463,7 @@ out:
        kfree(sshdr);
        retval = sdp->changed ? DISK_EVENT_MEDIA_CHANGE : 0;
        sdp->changed = 0;
+       scsi_disk_put(sdkp);
        return retval;
 }
 
@@ -2862,10 +2867,10 @@ static int sd_revalidate_disk(struct gendisk *disk)
        if (sdkp->opt_xfer_blocks &&
            sdkp->opt_xfer_blocks <= dev_max &&
            sdkp->opt_xfer_blocks <= SD_DEF_XFER_BLOCKS &&
-           sdkp->opt_xfer_blocks * sdp->sector_size >= PAGE_SIZE)
-               rw_max = q->limits.io_opt =
-                       sdkp->opt_xfer_blocks * sdp->sector_size;
-       else
+           logical_to_bytes(sdp, sdkp->opt_xfer_blocks) >= PAGE_SIZE) {
+               q->limits.io_opt = logical_to_bytes(sdp, sdkp->opt_xfer_blocks);
+               rw_max = logical_to_sectors(sdp, sdkp->opt_xfer_blocks);
+       else
                rw_max = BLK_DEF_MAX_SECTORS;
 
        /* Combine with controller limits */
index 654630b..765a6f1 100644 (file)
@@ -151,6 +151,11 @@ static inline sector_t logical_to_sectors(struct scsi_device *sdev, sector_t blo
        return blocks << (ilog2(sdev->sector_size) - 9);
 }
 
+static inline unsigned int logical_to_bytes(struct scsi_device *sdev, sector_t blocks)
+{
+       return blocks * sdev->sector_size;
+}
+
 /*
  * A DIF-capable target device can be formatted with different
  * protection schemes.  Currently 0 through 3 are defined:
index 1ddd9e2..cf007f3 100644 (file)
@@ -173,13 +173,17 @@ static int sun4i_spi_transfer_one(struct spi_master *master,
 {
        struct sun4i_spi *sspi = spi_master_get_devdata(master);
        unsigned int mclk_rate, div, timeout;
+       unsigned int start, end, tx_time;
        unsigned int tx_len = 0;
        int ret = 0;
        u32 reg;
 
        /* We don't support transfer larger than the FIFO */
        if (tfr->len > SUN4I_FIFO_DEPTH)
-               return -EINVAL;
+               return -EMSGSIZE;
+
+       if (tfr->tx_buf && tfr->len >= SUN4I_FIFO_DEPTH)
+               return -EMSGSIZE;
 
        reinit_completion(&sspi->done);
        sspi->tx_buf = tfr->tx_buf;
@@ -269,8 +273,12 @@ static int sun4i_spi_transfer_one(struct spi_master *master,
        sun4i_spi_write(sspi, SUN4I_BURST_CNT_REG, SUN4I_BURST_CNT(tfr->len));
        sun4i_spi_write(sspi, SUN4I_XMIT_CNT_REG, SUN4I_XMIT_CNT(tx_len));
 
-       /* Fill the TX FIFO */
-       sun4i_spi_fill_fifo(sspi, SUN4I_FIFO_DEPTH);
+       /*
+        * Fill the TX FIFO
+        * Filling the FIFO fully causes timeout for some reason
+        * at least on spi2 on A10s
+        */
+       sun4i_spi_fill_fifo(sspi, SUN4I_FIFO_DEPTH - 1);
 
        /* Enable the interrupts */
        sun4i_spi_write(sspi, SUN4I_INT_CTL_REG, SUN4I_INT_CTL_TC);
@@ -279,9 +287,16 @@ static int sun4i_spi_transfer_one(struct spi_master *master,
        reg = sun4i_spi_read(sspi, SUN4I_CTL_REG);
        sun4i_spi_write(sspi, SUN4I_CTL_REG, reg | SUN4I_CTL_XCH);
 
+       tx_time = max(tfr->len * 8 * 2 / (tfr->speed_hz / 1000), 100U);
+       start = jiffies;
        timeout = wait_for_completion_timeout(&sspi->done,
-                                             msecs_to_jiffies(1000));
+                                             msecs_to_jiffies(tx_time));
+       end = jiffies;
        if (!timeout) {
+               dev_warn(&master->dev,
+                        "%s: timeout transferring %u bytes@%iHz for %i(%i)ms",
+                        dev_name(&spi->dev), tfr->len, tfr->speed_hz,
+                        jiffies_to_msecs(end - start), tx_time);
                ret = -ETIMEDOUT;
                goto out;
        }
index 42e2c4b..7fce79a 100644 (file)
@@ -160,6 +160,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
 {
        struct sun6i_spi *sspi = spi_master_get_devdata(master);
        unsigned int mclk_rate, div, timeout;
+       unsigned int start, end, tx_time;
        unsigned int tx_len = 0;
        int ret = 0;
        u32 reg;
@@ -269,9 +270,16 @@ static int sun6i_spi_transfer_one(struct spi_master *master,
        reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG);
        sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg | SUN6I_TFR_CTL_XCH);
 
+       tx_time = max(tfr->len * 8 * 2 / (tfr->speed_hz / 1000), 100U);
+       start = jiffies;
        timeout = wait_for_completion_timeout(&sspi->done,
-                                             msecs_to_jiffies(1000));
+                                             msecs_to_jiffies(tx_time));
+       end = jiffies;
        if (!timeout) {
+               dev_warn(&master->dev,
+                        "%s: timeout transferring %u bytes@%iHz for %i(%i)ms",
+                        dev_name(&spi->dev), tfr->len, tfr->speed_hz,
+                        jiffies_to_msecs(end - start), tx_time);
                ret = -ETIMEDOUT;
                goto out;
        }
index 443f664..29ea8d2 100644 (file)
@@ -646,6 +646,13 @@ free_master:
 
 static int ti_qspi_remove(struct platform_device *pdev)
 {
+       struct ti_qspi *qspi = platform_get_drvdata(pdev);
+       int rc;
+
+       rc = spi_master_suspend(qspi->master);
+       if (rc)
+               return rc;
+
        pm_runtime_put_sync(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
 
index bbfee53..845e49a 100644 (file)
@@ -2521,12 +2521,13 @@ kiblnd_passive_connect(struct rdma_cm_id *cmid, void *priv, int priv_nob)
        return 0;
 
  failed:
-       if (ni)
+       if (ni) {
                lnet_ni_decref(ni);
+               rej.ibr_cp.ibcp_queue_depth = kiblnd_msg_queue_size(version, ni);
+               rej.ibr_cp.ibcp_max_frags = kiblnd_rdma_frags(version, ni);
+       }
 
        rej.ibr_version             = version;
-       rej.ibr_cp.ibcp_queue_depth = kiblnd_msg_queue_size(version, ni);
-       rej.ibr_cp.ibcp_max_frags = kiblnd_rdma_frags(version, ni);
        kiblnd_reject(cmid, &rej);
 
        return -ECONNREFUSED;
index c17870c..fbce1f7 100644 (file)
@@ -102,7 +102,7 @@ efuse_phymap_to_logical(u8 *phymap, u16 _offset, u16 _size_byte, u8  *pbuf)
        if (!efuseTbl)
                return;
 
-       eFuseWord = (u16 **)rtw_malloc2d(EFUSE_MAX_SECTION_88E, EFUSE_MAX_WORD_UNIT, sizeof(*eFuseWord));
+       eFuseWord = (u16 **)rtw_malloc2d(EFUSE_MAX_SECTION_88E, EFUSE_MAX_WORD_UNIT, sizeof(u16));
        if (!eFuseWord) {
                DBG_88E("%s: alloc eFuseWord fail!\n", __func__);
                goto eFuseWord_failed;
index 87ea3b8..363f3a3 100644 (file)
@@ -2072,7 +2072,8 @@ void rtl8188eu_set_hal_ops(struct adapter *adapt)
 {
        struct hal_ops  *halfunc = &adapt->HalFunc;
 
-       adapt->HalData = kzalloc(sizeof(*adapt->HalData), GFP_KERNEL);
+
+       adapt->HalData = kzalloc(sizeof(struct hal_data_8188e), GFP_KERNEL);
        if (!adapt->HalData)
                DBG_88E("cant not alloc memory for HAL DATA\n");
 
index 6ceac4f..5b4b47e 100644 (file)
@@ -857,14 +857,6 @@ __cpufreq_cooling_register(struct device_node *np,
                goto free_power_table;
        }
 
-       snprintf(dev_name, sizeof(dev_name), "thermal-cpufreq-%d",
-                cpufreq_dev->id);
-
-       cool_dev = thermal_of_cooling_device_register(np, dev_name, cpufreq_dev,
-                                                     &cpufreq_cooling_ops);
-       if (IS_ERR(cool_dev))
-               goto remove_idr;
-
        /* Fill freq-table in descending order of frequencies */
        for (i = 0, freq = -1; i <= cpufreq_dev->max_level; i++) {
                freq = find_next_max(table, freq);
@@ -877,6 +869,14 @@ __cpufreq_cooling_register(struct device_node *np,
                        pr_debug("%s: freq:%u KHz\n", __func__, freq);
        }
 
+       snprintf(dev_name, sizeof(dev_name), "thermal-cpufreq-%d",
+                cpufreq_dev->id);
+
+       cool_dev = thermal_of_cooling_device_register(np, dev_name, cpufreq_dev,
+                                                     &cpufreq_cooling_ops);
+       if (IS_ERR(cool_dev))
+               goto remove_idr;
+
        cpufreq_dev->clipped_freq = cpufreq_dev->freq_table[0];
        cpufreq_dev->cool_dev = cool_dev;
 
index 13d431c..a578cd2 100644 (file)
@@ -177,7 +177,7 @@ static int int3406_thermal_probe(struct platform_device *pdev)
                return -ENODEV;
        d->raw_bd = bd;
 
-       ret = acpi_video_get_levels(ACPI_COMPANION(&pdev->dev), &d->br);
+       ret = acpi_video_get_levels(ACPI_COMPANION(&pdev->dev), &d->br, NULL);
        if (ret)
                return ret;
 
index 82c4d2e..9510305 100644 (file)
@@ -120,17 +120,6 @@ config UNIX98_PTYS
          All modern Linux systems use the Unix98 ptys.  Say Y unless
          you're on an embedded system and want to conserve memory.
 
-config DEVPTS_MULTIPLE_INSTANCES
-       bool "Support multiple instances of devpts"
-       depends on UNIX98_PTYS
-       default n
-       ---help---
-         Enable support for multiple instances of devpts filesystem.
-         If you want to have isolated PTY namespaces (eg: in containers),
-         say Y here.  Otherwise, say N. If enabled, each mount of devpts
-         filesystem with the '-o newinstance' option will create an
-         independent PTY namespace.
-
 config LEGACY_PTYS
        bool "Legacy (BSD) PTY support"
        default y
index dd4b841..f856c45 100644 (file)
@@ -668,7 +668,7 @@ static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
        else
                fsi = tty->link->driver_data;
        devpts_kill_index(fsi, tty->index);
-       devpts_put_ref(fsi);
+       devpts_release(fsi);
 }
 
 static const struct tty_operations ptm_unix98_ops = {
@@ -733,10 +733,11 @@ static int ptmx_open(struct inode *inode, struct file *filp)
        if (retval)
                return retval;
 
-       fsi = devpts_get_ref(inode, filp);
-       retval = -ENODEV;
-       if (!fsi)
+       fsi = devpts_acquire(filp);
+       if (IS_ERR(fsi)) {
+               retval = PTR_ERR(fsi);
                goto out_free_file;
+       }
 
        /* find a device that is not in use. */
        mutex_lock(&devpts_mutex);
@@ -745,7 +746,7 @@ static int ptmx_open(struct inode *inode, struct file *filp)
 
        retval = index;
        if (index < 0)
-               goto out_put_ref;
+               goto out_put_fsi;
 
 
        mutex_lock(&tty_mutex);
@@ -789,8 +790,8 @@ err_release:
        return retval;
 out:
        devpts_kill_index(fsi, index);
-out_put_ref:
-       devpts_put_ref(fsi);
+out_put_fsi:
+       devpts_release(fsi);
 out_free_file:
        tty_free_file(filp);
        return retval;
index 6dc810b..944a6dc 100644 (file)
@@ -44,6 +44,9 @@ static const struct usb_device_id usb_quirk_list[] = {
        /* Creative SB Audigy 2 NX */
        { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME },
 
+       /* USB3503 */
+       { USB_DEVICE(0x0424, 0x3503), .driver_info = USB_QUIRK_RESET_RESUME },
+
        /* Microsoft Wireless Laser Mouse 6000 Receiver */
        { USB_DEVICE(0x045e, 0x00e1), .driver_info = USB_QUIRK_RESET_RESUME },
 
@@ -173,6 +176,10 @@ static const struct usb_device_id usb_quirk_list[] = {
        /* MAYA44USB sound device */
        { USB_DEVICE(0x0a92, 0x0091), .driver_info = USB_QUIRK_RESET_RESUME },
 
+       /* ASUS Base Station(T100) */
+       { USB_DEVICE(0x0b05, 0x17e0), .driver_info =
+                       USB_QUIRK_IGNORE_REMOTE_WAKEUP },
+
        /* Action Semiconductor flash disk */
        { USB_DEVICE(0x10d6, 0x2200), .driver_info =
                        USB_QUIRK_STRING_FETCH_255 },
@@ -188,26 +195,22 @@ static const struct usb_device_id usb_quirk_list[] = {
        { USB_DEVICE(0x1908, 0x1315), .driver_info =
                        USB_QUIRK_HONOR_BNUMINTERFACES },
 
-       /* INTEL VALUE SSD */
-       { USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME },
-
-       /* USB3503 */
-       { USB_DEVICE(0x0424, 0x3503), .driver_info = USB_QUIRK_RESET_RESUME },
-
-       /* ASUS Base Station(T100) */
-       { USB_DEVICE(0x0b05, 0x17e0), .driver_info =
-                       USB_QUIRK_IGNORE_REMOTE_WAKEUP },
-
        /* Protocol and OTG Electrical Test Device */
        { USB_DEVICE(0x1a0a, 0x0200), .driver_info =
                        USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL },
 
+       /* Acer C120 LED Projector */
+       { USB_DEVICE(0x1de1, 0xc102), .driver_info = USB_QUIRK_NO_LPM },
+
        /* Blackmagic Design Intensity Shuttle */
        { USB_DEVICE(0x1edb, 0xbd3b), .driver_info = USB_QUIRK_NO_LPM },
 
        /* Blackmagic Design UltraStudio SDI */
        { USB_DEVICE(0x1edb, 0xbd4f), .driver_info = USB_QUIRK_NO_LPM },
 
+       /* INTEL VALUE SSD */
+       { USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME },
+
        { }  /* terminating entry must be last */
 };
 
index 3c58d63..dec0b21 100644 (file)
        DWC2_TRACE_SCHEDULER_VB(pr_fmt("%s: SCH: " fmt),                \
                                dev_name(hsotg->dev), ##__VA_ARGS__)
 
+#ifdef CONFIG_MIPS
+/*
+ * There are some MIPS machines that can run in either big-endian
+ * or little-endian mode and that use the dwc2 register without
+ * a byteswap in both ways.
+ * Unlike other architectures, MIPS apparently does not require a
+ * barrier before the __raw_writel() to synchronize with DMA but does
+ * require the barrier after the __raw_writel() to serialize a set of
+ * writes. This set of operations was added specifically for MIPS and
+ * should only be used there.
+ */
 static inline u32 dwc2_readl(const void __iomem *addr)
 {
        u32 value = __raw_readl(addr);
@@ -90,6 +101,22 @@ static inline void dwc2_writel(u32 value, void __iomem *addr)
        pr_info("INFO:: wrote %08x to %p\n", value, addr);
 #endif
 }
+#else
+/* Normal architectures just use readl/write */
+static inline u32 dwc2_readl(const void __iomem *addr)
+{
+       return readl(addr);
+}
+
+static inline void dwc2_writel(u32 value, void __iomem *addr)
+{
+       writel(value, addr);
+
+#ifdef DWC2_LOG_WRITES
+       pr_info("info:: wrote %08x to %p\n", value, addr);
+#endif
+}
+#endif
 
 /* Maximum number of Endpoints/HostChannels */
 #define MAX_EPS_CHANNELS       16
index 4c5e300..26cf09d 100644 (file)
@@ -1018,7 +1018,7 @@ static int dwc2_hsotg_process_req_status(struct dwc2_hsotg *hsotg,
        return 1;
 }
 
-static int dwc2_hsotg_ep_sethalt(struct usb_ep *ep, int value);
+static int dwc2_hsotg_ep_sethalt(struct usb_ep *ep, int value, bool now);
 
 /**
  * get_ep_head - return the first request on the endpoint
@@ -1094,7 +1094,7 @@ static int dwc2_hsotg_process_req_feature(struct dwc2_hsotg *hsotg,
                case USB_ENDPOINT_HALT:
                        halted = ep->halted;
 
-                       dwc2_hsotg_ep_sethalt(&ep->ep, set);
+                       dwc2_hsotg_ep_sethalt(&ep->ep, set, true);
 
                        ret = dwc2_hsotg_send_reply(hsotg, ep0, NULL, 0);
                        if (ret) {
@@ -2948,8 +2948,13 @@ static int dwc2_hsotg_ep_dequeue(struct usb_ep *ep, struct usb_request *req)
  * dwc2_hsotg_ep_sethalt - set halt on a given endpoint
  * @ep: The endpoint to set halt.
  * @value: Set or unset the halt.
+ * @now: If true, stall the endpoint now. Otherwise return -EAGAIN if
+ *       the endpoint is busy processing requests.
+ *
+ * We need to stall the endpoint immediately if request comes from set_feature
+ * protocol command handler.
  */
-static int dwc2_hsotg_ep_sethalt(struct usb_ep *ep, int value)
+static int dwc2_hsotg_ep_sethalt(struct usb_ep *ep, int value, bool now)
 {
        struct dwc2_hsotg_ep *hs_ep = our_ep(ep);
        struct dwc2_hsotg *hs = hs_ep->parent;
@@ -2969,6 +2974,17 @@ static int dwc2_hsotg_ep_sethalt(struct usb_ep *ep, int value)
                return 0;
        }
 
+       if (hs_ep->isochronous) {
+               dev_err(hs->dev, "%s is Isochronous Endpoint\n", ep->name);
+               return -EINVAL;
+       }
+
+       if (!now && value && !list_empty(&hs_ep->queue)) {
+               dev_dbg(hs->dev, "%s request is pending, cannot halt\n",
+                       ep->name);
+               return -EAGAIN;
+       }
+
        if (hs_ep->dir_in) {
                epreg = DIEPCTL(index);
                epctl = dwc2_readl(hs->regs + epreg);
@@ -3020,7 +3036,7 @@ static int dwc2_hsotg_ep_sethalt_lock(struct usb_ep *ep, int value)
        int ret = 0;
 
        spin_lock_irqsave(&hs->lock, flags);
-       ret = dwc2_hsotg_ep_sethalt(ep, value);
+       ret = dwc2_hsotg_ep_sethalt(ep, value, false);
        spin_unlock_irqrestore(&hs->lock, flags);
 
        return ret;
index 7ddf944..6540506 100644 (file)
 #define DWC3_DEPCMD_GET_RSC_IDX(x)     (((x) >> DWC3_DEPCMD_PARAM_SHIFT) & 0x7f)
 #define DWC3_DEPCMD_STATUS(x)          (((x) >> 12) & 0x0F)
 #define DWC3_DEPCMD_HIPRI_FORCERM      (1 << 11)
+#define DWC3_DEPCMD_CLEARPENDIN                (1 << 11)
 #define DWC3_DEPCMD_CMDACT             (1 << 10)
 #define DWC3_DEPCMD_CMDIOC             (1 << 8)
 
index dd5cb55..2f1fb7e 100644 (file)
@@ -128,12 +128,6 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, exynos);
 
-       ret = dwc3_exynos_register_phys(exynos);
-       if (ret) {
-               dev_err(dev, "couldn't register PHYs\n");
-               return ret;
-       }
-
        exynos->dev     = dev;
 
        exynos->clk = devm_clk_get(dev, "usbdrd30");
@@ -183,20 +177,29 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
                goto err3;
        }
 
+       ret = dwc3_exynos_register_phys(exynos);
+       if (ret) {
+               dev_err(dev, "couldn't register PHYs\n");
+               goto err4;
+       }
+
        if (node) {
                ret = of_platform_populate(node, NULL, NULL, dev);
                if (ret) {
                        dev_err(dev, "failed to add dwc3 core\n");
-                       goto err4;
+                       goto err5;
                }
        } else {
                dev_err(dev, "no device node, failed to add dwc3 core\n");
                ret = -ENODEV;
-               goto err4;
+               goto err5;
        }
 
        return 0;
 
+err5:
+       platform_device_unregister(exynos->usb2_phy);
+       platform_device_unregister(exynos->usb3_phy);
 err4:
        regulator_disable(exynos->vdd10);
 err3:
index 5c0adb9..50d6ae6 100644 (file)
@@ -129,12 +129,18 @@ static int st_dwc3_drd_init(struct st_dwc3 *dwc3_data)
        switch (dwc3_data->dr_mode) {
        case USB_DR_MODE_PERIPHERAL:
 
-               val &= ~(USB3_FORCE_VBUSVALID | USB3_DELAY_VBUSVALID
+               val &= ~(USB3_DELAY_VBUSVALID
                        | USB3_SEL_FORCE_OPMODE | USB3_FORCE_OPMODE(0x3)
                        | USB3_SEL_FORCE_DPPULLDOWN2 | USB3_FORCE_DPPULLDOWN2
                        | USB3_SEL_FORCE_DMPULLDOWN2 | USB3_FORCE_DMPULLDOWN2);
 
-               val |= USB3_DEVICE_NOT_HOST;
+               /*
+                * USB3_PORT2_FORCE_VBUSVALID When '1' and when
+                * USB3_PORT2_DEVICE_NOT_HOST = 1, forces VBUSVLDEXT2 input
+                * of the pico PHY to 1.
+                */
+
+               val |= USB3_DEVICE_NOT_HOST | USB3_FORCE_VBUSVALID;
                break;
 
        case USB_DR_MODE_HOST:
index 9a7d0bd..07248ff 100644 (file)
@@ -347,6 +347,28 @@ int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep,
        return ret;
 }
 
+static int dwc3_send_clear_stall_ep_cmd(struct dwc3_ep *dep)
+{
+       struct dwc3 *dwc = dep->dwc;
+       struct dwc3_gadget_ep_cmd_params params;
+       u32 cmd = DWC3_DEPCMD_CLEARSTALL;
+
+       /*
+        * As of core revision 2.60a the recommended programming model
+        * is to set the ClearPendIN bit when issuing a Clear Stall EP
+        * command for IN endpoints. This is to prevent an issue where
+        * some (non-compliant) hosts may not send ACK TPs for pending
+        * IN transfers due to a mishandled error condition. Synopsys
+        * STAR 9000614252.
+        */
+       if (dep->direction && (dwc->revision >= DWC3_REVISION_260A))
+               cmd |= DWC3_DEPCMD_CLEARPENDIN;
+
+       memset(&params, 0, sizeof(params));
+
+       return dwc3_send_gadget_ep_cmd(dwc, dep->number, cmd, &params);
+}
+
 static dma_addr_t dwc3_trb_dma_offset(struct dwc3_ep *dep,
                struct dwc3_trb *trb)
 {
@@ -1314,8 +1336,7 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol)
                else
                        dep->flags |= DWC3_EP_STALL;
        } else {
-               ret = dwc3_send_gadget_ep_cmd(dwc, dep->number,
-                       DWC3_DEPCMD_CLEARSTALL, &params);
+               ret = dwc3_send_clear_stall_ep_cmd(dep);
                if (ret)
                        dev_err(dwc->dev, "failed to clear STALL on %s\n",
                                        dep->name);
@@ -2247,7 +2268,6 @@ static void dwc3_clear_stall_all_ep(struct dwc3 *dwc)
 
        for (epnum = 1; epnum < DWC3_ENDPOINTS_NUM; epnum++) {
                struct dwc3_ep *dep;
-               struct dwc3_gadget_ep_cmd_params params;
                int ret;
 
                dep = dwc->eps[epnum];
@@ -2259,9 +2279,7 @@ static void dwc3_clear_stall_all_ep(struct dwc3 *dwc)
 
                dep->flags &= ~DWC3_EP_STALL;
 
-               memset(&params, 0, sizeof(params));
-               ret = dwc3_send_gadget_ep_cmd(dwc, dep->number,
-                               DWC3_DEPCMD_CLEARSTALL, &params);
+               ret = dwc3_send_clear_stall_ep_cmd(dep);
                WARN_ON_ONCE(ret);
        }
 }
index d67de0d..eb64848 100644 (file)
@@ -1868,14 +1868,19 @@ unknown:
                                }
                                break;
                        }
-                       req->length = value;
-                       req->context = cdev;
-                       req->zero = value < w_length;
-                       value = composite_ep0_queue(cdev, req, GFP_ATOMIC);
-                       if (value < 0) {
-                               DBG(cdev, "ep_queue --> %d\n", value);
-                               req->status = 0;
-                               composite_setup_complete(gadget->ep0, req);
+
+                       if (value >= 0) {
+                               req->length = value;
+                               req->context = cdev;
+                               req->zero = value < w_length;
+                               value = composite_ep0_queue(cdev, req,
+                                                           GFP_ATOMIC);
+                               if (value < 0) {
+                                       DBG(cdev, "ep_queue --> %d\n", value);
+                                       req->status = 0;
+                                       composite_setup_complete(gadget->ep0,
+                                                                req);
+                               }
                        }
                        return value;
                }
index b6f60ca..70cf347 100644 (file)
@@ -1401,6 +1401,7 @@ static const struct usb_gadget_driver configfs_driver_template = {
                .owner          = THIS_MODULE,
                .name           = "configfs-gadget",
        },
+       .match_existing_only = 1,
 };
 
 static struct config_group *gadgets_make(
index 73515d5..cc33d26 100644 (file)
@@ -2051,7 +2051,7 @@ static int __ffs_data_do_os_desc(enum ffs_os_desc_type type,
 
                if (len < sizeof(*d) ||
                    d->bFirstInterfaceNumber >= ffs->interfaces_count ||
-                   d->Reserved1)
+                   !d->Reserved1)
                        return -EINVAL;
                for (i = 0; i < ARRAY_SIZE(d->Reserved2); ++i)
                        if (d->Reserved2[i])
@@ -2729,6 +2729,7 @@ static int _ffs_func_bind(struct usb_configuration *c,
                func->ffs->ss_descs_count;
 
        int fs_len, hs_len, ss_len, ret, i;
+       struct ffs_ep *eps_ptr;
 
        /* Make it a single chunk, less management later on */
        vla_group(d);
@@ -2777,12 +2778,9 @@ static int _ffs_func_bind(struct usb_configuration *c,
               ffs->raw_descs_length);
 
        memset(vla_ptr(vlabuf, d, inums), 0xff, d_inums__sz);
-       for (ret = ffs->eps_count; ret; --ret) {
-               struct ffs_ep *ptr;
-
-               ptr = vla_ptr(vlabuf, d, eps);
-               ptr[ret].num = -1;
-       }
+       eps_ptr = vla_ptr(vlabuf, d, eps);
+       for (i = 0; i < ffs->eps_count; i++)
+               eps_ptr[i].num = -1;
 
        /* Save pointers
         * d_eps == vlabuf, func->eps used to kfree vlabuf later
@@ -2851,7 +2849,7 @@ static int _ffs_func_bind(struct usb_configuration *c,
                goto error;
 
        func->function.os_desc_table = vla_ptr(vlabuf, d, os_desc_table);
-       if (c->cdev->use_os_string)
+       if (c->cdev->use_os_string) {
                for (i = 0; i < ffs->interfaces_count; ++i) {
                        struct usb_os_desc *desc;
 
@@ -2862,13 +2860,15 @@ static int _ffs_func_bind(struct usb_configuration *c,
                                vla_ptr(vlabuf, d, ext_compat) + i * 16;
                        INIT_LIST_HEAD(&desc->ext_prop);
                }
-       ret = ffs_do_os_descs(ffs->ms_os_descs_count,
-                             vla_ptr(vlabuf, d, raw_descs) +
-                             fs_len + hs_len + ss_len,
-                             d_raw_descs__sz - fs_len - hs_len - ss_len,
-                             __ffs_func_bind_do_os_desc, func);
-       if (unlikely(ret < 0))
-               goto error;
+               ret = ffs_do_os_descs(ffs->ms_os_descs_count,
+                                     vla_ptr(vlabuf, d, raw_descs) +
+                                     fs_len + hs_len + ss_len,
+                                     d_raw_descs__sz - fs_len - hs_len -
+                                     ss_len,
+                                     __ffs_func_bind_do_os_desc, func);
+               if (unlikely(ret < 0))
+                       goto error;
+       }
        func->function.os_desc_n =
                c->cdev->use_os_string ? ffs->interfaces_count : 0;
 
index c45104e..64706a7 100644 (file)
@@ -161,14 +161,6 @@ static struct usb_endpoint_descriptor hs_ep_out_desc = {
        .wMaxPacketSize =       cpu_to_le16(512)
 };
 
-static struct usb_qualifier_descriptor dev_qualifier = {
-       .bLength =              sizeof(dev_qualifier),
-       .bDescriptorType =      USB_DT_DEVICE_QUALIFIER,
-       .bcdUSB =               cpu_to_le16(0x0200),
-       .bDeviceClass =         USB_CLASS_PRINTER,
-       .bNumConfigurations =   1
-};
-
 static struct usb_descriptor_header *hs_printer_function[] = {
        (struct usb_descriptor_header *) &intf_desc,
        (struct usb_descriptor_header *) &hs_ep_in_desc,
index 35fe3c8..197f733 100644 (file)
@@ -1445,16 +1445,18 @@ static void usbg_drop_tpg(struct se_portal_group *se_tpg)
        for (i = 0; i < TPG_INSTANCES; ++i)
                if (tpg_instances[i].tpg == tpg)
                        break;
-       if (i < TPG_INSTANCES)
+       if (i < TPG_INSTANCES) {
                tpg_instances[i].tpg = NULL;
-       opts = container_of(tpg_instances[i].func_inst,
-               struct f_tcm_opts, func_inst);
-       mutex_lock(&opts->dep_lock);
-       if (opts->has_dep)
-               module_put(opts->dependent);
-       else
-               configfs_undepend_item_unlocked(&opts->func_inst.group.cg_item);
-       mutex_unlock(&opts->dep_lock);
+               opts = container_of(tpg_instances[i].func_inst,
+                       struct f_tcm_opts, func_inst);
+               mutex_lock(&opts->dep_lock);
+               if (opts->has_dep)
+                       module_put(opts->dependent);
+               else
+                       configfs_undepend_item_unlocked(
+                               &opts->func_inst.group.cg_item);
+               mutex_unlock(&opts->dep_lock);
+       }
        mutex_unlock(&tpg_instances_lock);
 
        kfree(tpg);
index 186d4b1..cd214ec 100644 (file)
@@ -598,18 +598,6 @@ static struct usb_gadget_strings *fn_strings[] = {
        NULL,
 };
 
-static struct usb_qualifier_descriptor devqual_desc = {
-       .bLength = sizeof devqual_desc,
-       .bDescriptorType = USB_DT_DEVICE_QUALIFIER,
-
-       .bcdUSB = cpu_to_le16(0x200),
-       .bDeviceClass = USB_CLASS_MISC,
-       .bDeviceSubClass = 0x02,
-       .bDeviceProtocol = 0x01,
-       .bNumConfigurations = 1,
-       .bRESERVED = 0,
-};
-
 static struct usb_interface_assoc_descriptor iad_desc = {
        .bLength = sizeof iad_desc,
        .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
@@ -1292,6 +1280,7 @@ in_rq_cur(struct usb_function *fn, const struct usb_ctrlrequest *cr)
 
        if (control_selector == UAC2_CS_CONTROL_SAM_FREQ) {
                struct cntrl_cur_lay3 c;
+               memset(&c, 0, sizeof(struct cntrl_cur_lay3));
 
                if (entity_id == USB_IN_CLK_ID)
                        c.dCUR = p_srate;
index d626830..990df22 100644 (file)
@@ -83,9 +83,7 @@ EXPORT_SYMBOL_GPL(fsg_fs_function);
  * USB 2.0 devices need to expose both high speed and full speed
  * descriptors, unless they only run at full speed.
  *
- * That means alternate endpoint descriptors (bigger packets)
- * and a "device qualifier" ... plus more construction options
- * for the configuration descriptor.
+ * That means alternate endpoint descriptors (bigger packets).
  */
 struct usb_endpoint_descriptor fsg_hs_bulk_in_desc = {
        .bLength =              USB_DT_ENDPOINT_SIZE,
index e64479f..aa3707b 100644 (file)
@@ -938,8 +938,11 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr)
                        struct usb_ep           *ep = dev->gadget->ep0;
                        struct usb_request      *req = dev->req;
 
-                       if ((retval = setup_req (ep, req, 0)) == 0)
-                               retval = usb_ep_queue (ep, req, GFP_ATOMIC);
+                       if ((retval = setup_req (ep, req, 0)) == 0) {
+                               spin_unlock_irq (&dev->lock);
+                               retval = usb_ep_queue (ep, req, GFP_KERNEL);
+                               spin_lock_irq (&dev->lock);
+                       }
                        dev->state = STATE_DEV_CONNECTED;
 
                        /* assume that was SET_CONFIGURATION */
@@ -1457,8 +1460,11 @@ delegate:
                                                        w_length);
                                if (value < 0)
                                        break;
+
+                               spin_unlock (&dev->lock);
                                value = usb_ep_queue (gadget->ep0, dev->req,
-                                                       GFP_ATOMIC);
+                                                       GFP_KERNEL);
+                               spin_lock (&dev->lock);
                                if (value < 0) {
                                        clean_req (gadget->ep0, dev->req);
                                        break;
@@ -1481,11 +1487,14 @@ delegate:
        if (value >= 0 && dev->state != STATE_DEV_SETUP) {
                req->length = value;
                req->zero = value < w_length;
-               value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);
+
+               spin_unlock (&dev->lock);
+               value = usb_ep_queue (gadget->ep0, req, GFP_KERNEL);
                if (value < 0) {
                        DBG (dev, "ep_queue --> %d\n", value);
                        req->status = 0;
                }
+               return value;
        }
 
        /* device stalls when value < 0 */
index 6e8300d..e1b2dce 100644 (file)
@@ -603,11 +603,15 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver)
                }
        }
 
-       list_add_tail(&driver->pending, &gadget_driver_pending_list);
-       pr_info("udc-core: couldn't find an available UDC - added [%s] to list of pending drivers\n",
-               driver->function);
+       if (!driver->match_existing_only) {
+               list_add_tail(&driver->pending, &gadget_driver_pending_list);
+               pr_info("udc-core: couldn't find an available UDC - added [%s] to list of pending drivers\n",
+                       driver->function);
+               ret = 0;
+       }
+
        mutex_unlock(&udc_lock);
-       return 0;
+       return ret;
 found:
        ret = udc_bind_to_driver(udc, driver);
        mutex_unlock(&udc_lock);
index ae1b6e6..a962b89 100644 (file)
@@ -368,6 +368,15 @@ static void ehci_shutdown(struct usb_hcd *hcd)
 {
        struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 
+       /**
+        * Protect the system from crashing at system shutdown in cases where
+        * usb host is not added yet from OTG controller driver.
+        * As ehci_setup() not done yet, so stop accessing registers or
+        * variables initialized in ehci_setup()
+        */
+       if (!ehci->sbrn)
+               return;
+
        spin_lock_irq(&ehci->lock);
        ehci->shutdown = true;
        ehci->rh_state = EHCI_RH_STOPPING;
index ffc9029..74f62d6 100644 (file)
@@ -872,14 +872,22 @@ int ehci_hub_control(
 ) {
        struct ehci_hcd *ehci = hcd_to_ehci (hcd);
        int             ports = HCS_N_PORTS (ehci->hcs_params);
-       u32 __iomem     *status_reg = &ehci->regs->port_status[
-                               (wIndex & 0xff) - 1];
-       u32 __iomem     *hostpc_reg = &ehci->regs->hostpc[(wIndex & 0xff) - 1];
+       u32 __iomem     *status_reg, *hostpc_reg;
        u32             temp, temp1, status;
        unsigned long   flags;
        int             retval = 0;
        unsigned        selector;
 
+       /*
+        * Avoid underflow while calculating (wIndex & 0xff) - 1.
+        * The compiler might deduce that wIndex can never be 0 and then
+        * optimize away the tests for !wIndex below.
+        */
+       temp = wIndex & 0xff;
+       temp -= (temp > 0);
+       status_reg = &ehci->regs->port_status[temp];
+       hostpc_reg = &ehci->regs->hostpc[temp];
+
        /*
         * FIXME:  support SetPortFeatures USB_PORT_FEAT_INDICATOR.
         * HCS_INDICATOR may say we can change LEDs to off/amber/green.
index d3afc89..2f8d3af 100644 (file)
@@ -179,22 +179,32 @@ static int ehci_msm_remove(struct platform_device *pdev)
 static int ehci_msm_pm_suspend(struct device *dev)
 {
        struct usb_hcd *hcd = dev_get_drvdata(dev);
+       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
        bool do_wakeup = device_may_wakeup(dev);
 
        dev_dbg(dev, "ehci-msm PM suspend\n");
 
-       return ehci_suspend(hcd, do_wakeup);
+       /* Only call ehci_suspend if ehci_setup has been done */
+       if (ehci->sbrn)
+               return ehci_suspend(hcd, do_wakeup);
+
+       return 0;
 }
 
 static int ehci_msm_pm_resume(struct device *dev)
 {
        struct usb_hcd *hcd = dev_get_drvdata(dev);
+       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 
        dev_dbg(dev, "ehci-msm PM resume\n");
-       ehci_resume(hcd, false);
+
+       /* Only call ehci_resume if ehci_setup has been done */
+       if (ehci->sbrn)
+               ehci_resume(hcd, false);
 
        return 0;
 }
+
 #else
 #define ehci_msm_pm_suspend    NULL
 #define ehci_msm_pm_resume     NULL
index 4031b37..9a3d7db 100644 (file)
@@ -81,15 +81,23 @@ static int tegra_reset_usb_controller(struct platform_device *pdev)
        struct usb_hcd *hcd = platform_get_drvdata(pdev);
        struct tegra_ehci_hcd *tegra =
                (struct tegra_ehci_hcd *)hcd_to_ehci(hcd)->priv;
+       bool has_utmi_pad_registers = false;
 
        phy_np = of_parse_phandle(pdev->dev.of_node, "nvidia,phy", 0);
        if (!phy_np)
                return -ENOENT;
 
+       if (of_property_read_bool(phy_np, "nvidia,has-utmi-pad-registers"))
+               has_utmi_pad_registers = true;
+
        if (!usb1_reset_attempted) {
                struct reset_control *usb1_reset;
 
-               usb1_reset = of_reset_control_get(phy_np, "usb");
+               if (!has_utmi_pad_registers)
+                       usb1_reset = of_reset_control_get(phy_np, "utmi-pads");
+               else
+                       usb1_reset = tegra->rst;
+
                if (IS_ERR(usb1_reset)) {
                        dev_warn(&pdev->dev,
                                 "can't get utmi-pads reset from the PHY\n");
@@ -99,13 +107,15 @@ static int tegra_reset_usb_controller(struct platform_device *pdev)
                        reset_control_assert(usb1_reset);
                        udelay(1);
                        reset_control_deassert(usb1_reset);
+
+                       if (!has_utmi_pad_registers)
+                               reset_control_put(usb1_reset);
                }
 
-               reset_control_put(usb1_reset);
                usb1_reset_attempted = true;
        }
 
-       if (!of_property_read_bool(phy_np, "nvidia,has-utmi-pad-registers")) {
+       if (!has_utmi_pad_registers) {
                reset_control_assert(tegra->rst);
                udelay(1);
                reset_control_deassert(tegra->rst);
index d029bbe..641fed6 100644 (file)
@@ -183,7 +183,6 @@ static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed)
 {
        int     branch;
 
-       ed->state = ED_OPER;
        ed->ed_prev = NULL;
        ed->ed_next = NULL;
        ed->hwNextED = 0;
@@ -259,6 +258,8 @@ static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed)
        /* the HC may not see the schedule updates yet, but if it does
         * then they'll be properly ordered.
         */
+
+       ed->state = ED_OPER;
        return 0;
 }
 
index 48672fa..c10972f 100644 (file)
@@ -37,6 +37,7 @@
 /* Device for a quirk */
 #define PCI_VENDOR_ID_FRESCO_LOGIC     0x1b73
 #define PCI_DEVICE_ID_FRESCO_LOGIC_PDK 0x1000
+#define PCI_DEVICE_ID_FRESCO_LOGIC_FL1009      0x1009
 #define PCI_DEVICE_ID_FRESCO_LOGIC_FL1400      0x1400
 
 #define PCI_VENDOR_ID_ETRON            0x1b6f
@@ -114,6 +115,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
                xhci->quirks |= XHCI_TRUST_TX_LENGTH;
        }
 
+       if (pdev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC &&
+                       pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_FL1009)
+               xhci->quirks |= XHCI_BROKEN_STREAMS;
+
        if (pdev->vendor == PCI_VENDOR_ID_NEC)
                xhci->quirks |= XHCI_NEC_HOST;
 
index 676ea45..1f3f981 100644 (file)
@@ -196,6 +196,9 @@ static int xhci_plat_probe(struct platform_device *pdev)
                ret = clk_prepare_enable(clk);
                if (ret)
                        goto put_hcd;
+       } else if (PTR_ERR(clk) == -EPROBE_DEFER) {
+               ret = -EPROBE_DEFER;
+               goto put_hcd;
        }
 
        xhci = hcd_to_xhci(hcd);
index 52deae4..d7d5025 100644 (file)
@@ -290,6 +290,14 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci)
 
        temp_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
        xhci->cmd_ring_state = CMD_RING_STATE_ABORTED;
+
+       /*
+        * Writing the CMD_RING_ABORT bit should cause a cmd completion event,
+        * however on some host hw the CMD_RING_RUNNING bit is correctly cleared
+        * but the completion event in never sent. Use the cmd timeout timer to
+        * handle those cases. Use twice the time to cover the bit polling retry
+        */
+       mod_timer(&xhci->cmd_timer, jiffies + (2 * XHCI_CMD_DEFAULT_TIMEOUT));
        xhci_write_64(xhci, temp_64 | CMD_RING_ABORT,
                        &xhci->op_regs->cmd_ring);
 
@@ -314,6 +322,7 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci)
 
                xhci_err(xhci, "Stopped the command ring failed, "
                                "maybe the host is dead\n");
+               del_timer(&xhci->cmd_timer);
                xhci->xhc_state |= XHCI_STATE_DYING;
                xhci_quiesce(xhci);
                xhci_halt(xhci);
@@ -1246,22 +1255,21 @@ void xhci_handle_command_timeout(unsigned long data)
        int ret;
        unsigned long flags;
        u64 hw_ring_state;
-       struct xhci_command *cur_cmd = NULL;
+       bool second_timeout = false;
        xhci = (struct xhci_hcd *) data;
 
        /* mark this command to be cancelled */
        spin_lock_irqsave(&xhci->lock, flags);
        if (xhci->current_cmd) {
-               cur_cmd = xhci->current_cmd;
-               cur_cmd->status = COMP_CMD_ABORT;
+               if (xhci->current_cmd->status == COMP_CMD_ABORT)
+                       second_timeout = true;
+               xhci->current_cmd->status = COMP_CMD_ABORT;
        }
 
-
        /* Make sure command ring is running before aborting it */
        hw_ring_state = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
        if ((xhci->cmd_ring_state & CMD_RING_STATE_RUNNING) &&
            (hw_ring_state & CMD_RING_RUNNING))  {
-
                spin_unlock_irqrestore(&xhci->lock, flags);
                xhci_dbg(xhci, "Command timeout\n");
                ret = xhci_abort_cmd_ring(xhci);
@@ -1273,6 +1281,15 @@ void xhci_handle_command_timeout(unsigned long data)
                }
                return;
        }
+
+       /* command ring failed to restart, or host removed. Bail out */
+       if (second_timeout || xhci->xhc_state & XHCI_STATE_REMOVING) {
+               spin_unlock_irqrestore(&xhci->lock, flags);
+               xhci_dbg(xhci, "command timed out twice, ring start fail?\n");
+               xhci_cleanup_command_queue(xhci);
+               return;
+       }
+
        /* command timeout on stopped ring, ring can't be aborted */
        xhci_dbg(xhci, "Command timeout on stopped ring\n");
        xhci_handle_stopped_cmd_ring(xhci, xhci->current_cmd);
@@ -2721,7 +2738,8 @@ hw_died:
                writel(irq_pending, &xhci->ir_set->irq_pending);
        }
 
-       if (xhci->xhc_state & XHCI_STATE_DYING) {
+       if (xhci->xhc_state & XHCI_STATE_DYING ||
+           xhci->xhc_state & XHCI_STATE_HALTED) {
                xhci_dbg(xhci, "xHCI dying, ignoring interrupt. "
                                "Shouldn't IRQs be disabled?\n");
                /* Clear the event handler busy flag (RW1C);
index fa7e1ef..f2f9518 100644 (file)
@@ -685,20 +685,23 @@ void xhci_stop(struct usb_hcd *hcd)
        u32 temp;
        struct xhci_hcd *xhci = hcd_to_xhci(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).
-        */
-       xhci_halt(xhci);
-       xhci_reset(xhci);
-       spin_unlock_irq(&xhci->lock);
+       if (!(xhci->xhc_state & XHCI_STATE_HALTED)) {
+               spin_lock_irq(&xhci->lock);
+
+               xhci->xhc_state |= XHCI_STATE_HALTED;
+               xhci->cmd_ring_state = CMD_RING_STATE_STOPPED;
+               xhci_halt(xhci);
+               xhci_reset(xhci);
+
+               spin_unlock_irq(&xhci->lock);
+       }
+
+       if (!usb_hcd_is_primary_hcd(hcd)) {
+               mutex_unlock(&xhci->mutex);
+               return;
+       }
 
        xhci_cleanup_msix(xhci);
 
@@ -4886,7 +4889,7 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
                xhci->hcc_params2 = readl(&xhci->cap_regs->hcc_params2);
        xhci_print_registers(xhci);
 
-       xhci->quirks = quirks;
+       xhci->quirks |= quirks;
 
        get_quirks(dev, xhci);
 
index 39fd958..f824336 100644 (file)
@@ -1090,29 +1090,6 @@ void musb_stop(struct musb *musb)
        musb_platform_try_idle(musb, 0);
 }
 
-static void musb_shutdown(struct platform_device *pdev)
-{
-       struct musb     *musb = dev_to_musb(&pdev->dev);
-       unsigned long   flags;
-
-       pm_runtime_get_sync(musb->controller);
-
-       musb_host_cleanup(musb);
-       musb_gadget_cleanup(musb);
-
-       spin_lock_irqsave(&musb->lock, flags);
-       musb_platform_disable(musb);
-       musb_generic_disable(musb);
-       spin_unlock_irqrestore(&musb->lock, flags);
-
-       musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
-       musb_platform_exit(musb);
-
-       pm_runtime_put(musb->controller);
-       /* FIXME power down */
-}
-
-
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -1702,7 +1679,7 @@ EXPORT_SYMBOL_GPL(musb_dma_completion);
 #define use_dma                        0
 #endif
 
-static void (*musb_phy_callback)(enum musb_vbus_id_status status);
+static int (*musb_phy_callback)(enum musb_vbus_id_status status);
 
 /*
  * musb_mailbox - optional phy notifier function
@@ -1711,11 +1688,12 @@ static void (*musb_phy_callback)(enum musb_vbus_id_status status);
  * Optionally gets called from the USB PHY. Note that the USB PHY must be
  * disabled at the point the phy_callback is registered or unregistered.
  */
-void musb_mailbox(enum musb_vbus_id_status status)
+int musb_mailbox(enum musb_vbus_id_status status)
 {
        if (musb_phy_callback)
-               musb_phy_callback(status);
+               return musb_phy_callback(status);
 
+       return -ENODEV;
 };
 EXPORT_SYMBOL_GPL(musb_mailbox);
 
@@ -2028,11 +2006,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
        musb_readl = musb_default_readl;
        musb_writel = musb_default_writel;
 
-       /* We need musb_read/write functions initialized for PM */
-       pm_runtime_use_autosuspend(musb->controller);
-       pm_runtime_set_autosuspend_delay(musb->controller, 200);
-       pm_runtime_enable(musb->controller);
-
        /* The musb_platform_init() call:
         *   - adjusts musb->mregs
         *   - sets the musb->isr
@@ -2134,6 +2107,16 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
        if (musb->ops->phy_callback)
                musb_phy_callback = musb->ops->phy_callback;
 
+       /*
+        * We need musb_read/write functions initialized for PM.
+        * Note that at least 2430 glue needs autosuspend delay
+        * somewhere above 300 ms for the hardware to idle properly
+        * after disconnecting the cable in host mode. Let's use
+        * 500 ms for some margin.
+        */
+       pm_runtime_use_autosuspend(musb->controller);
+       pm_runtime_set_autosuspend_delay(musb->controller, 500);
+       pm_runtime_enable(musb->controller);
        pm_runtime_get_sync(musb->controller);
 
        status = usb_phy_init(musb->xceiv);
@@ -2237,13 +2220,8 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
        if (status)
                goto fail5;
 
-       pm_runtime_put(musb->controller);
-
-       /*
-        * For why this is currently needed, see commit 3e43a0725637
-        * ("usb: musb: core: add pm_runtime_irq_safe()")
-        */
-       pm_runtime_irq_safe(musb->controller);
+       pm_runtime_mark_last_busy(musb->controller);
+       pm_runtime_put_autosuspend(musb->controller);
 
        return 0;
 
@@ -2265,7 +2243,9 @@ fail2_5:
        usb_phy_shutdown(musb->xceiv);
 
 err_usb_phy_init:
+       pm_runtime_dont_use_autosuspend(musb->controller);
        pm_runtime_put_sync(musb->controller);
+       pm_runtime_disable(musb->controller);
 
 fail2:
        if (musb->irq_wake)
@@ -2273,7 +2253,6 @@ fail2:
        musb_platform_exit(musb);
 
 fail1:
-       pm_runtime_disable(musb->controller);
        dev_err(musb->controller,
                "musb_init_controller failed with status %d\n", status);
 
@@ -2312,6 +2291,7 @@ static int musb_remove(struct platform_device *pdev)
 {
        struct device   *dev = &pdev->dev;
        struct musb     *musb = dev_to_musb(dev);
+       unsigned long   flags;
 
        /* this gets called on rmmod.
         *  - Host mode: host may still be active
@@ -2319,17 +2299,26 @@ static int musb_remove(struct platform_device *pdev)
         *  - OTG mode: both roles are deactivated (or never-activated)
         */
        musb_exit_debugfs(musb);
-       musb_shutdown(pdev);
-       musb_phy_callback = NULL;
-
-       if (musb->dma_controller)
-               musb_dma_controller_destroy(musb->dma_controller);
-
-       usb_phy_shutdown(musb->xceiv);
 
        cancel_work_sync(&musb->irq_work);
        cancel_delayed_work_sync(&musb->finish_resume_work);
        cancel_delayed_work_sync(&musb->deassert_reset_work);
+       pm_runtime_get_sync(musb->controller);
+       musb_host_cleanup(musb);
+       musb_gadget_cleanup(musb);
+       spin_lock_irqsave(&musb->lock, flags);
+       musb_platform_disable(musb);
+       musb_generic_disable(musb);
+       spin_unlock_irqrestore(&musb->lock, flags);
+       musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
+       pm_runtime_dont_use_autosuspend(musb->controller);
+       pm_runtime_put_sync(musb->controller);
+       pm_runtime_disable(musb->controller);
+       musb_platform_exit(musb);
+       musb_phy_callback = NULL;
+       if (musb->dma_controller)
+               musb_dma_controller_destroy(musb->dma_controller);
+       usb_phy_shutdown(musb->xceiv);
        musb_free(musb);
        device_init_wakeup(dev, 0);
        return 0;
@@ -2429,7 +2418,8 @@ static void musb_restore_context(struct musb *musb)
        musb_writew(musb_base, MUSB_INTRTXE, musb->intrtxe);
        musb_writew(musb_base, MUSB_INTRRXE, musb->intrrxe);
        musb_writeb(musb_base, MUSB_INTRUSBE, musb->context.intrusbe);
-       musb_writeb(musb_base, MUSB_DEVCTL, musb->context.devctl);
+       if (musb->context.devctl & MUSB_DEVCTL_SESSION)
+               musb_writeb(musb_base, MUSB_DEVCTL, musb->context.devctl);
 
        for (i = 0; i < musb->config->num_eps; ++i) {
                struct musb_hw_ep       *hw_ep;
@@ -2612,7 +2602,6 @@ static struct platform_driver musb_driver = {
        },
        .probe          = musb_probe,
        .remove         = musb_remove,
-       .shutdown       = musb_shutdown,
 };
 
 module_platform_driver(musb_driver);
index b6afe9e..b55a776 100644 (file)
@@ -215,7 +215,7 @@ struct musb_platform_ops {
                                dma_addr_t *dma_addr, u32 *len);
        void    (*pre_root_reset_end)(struct musb *musb);
        void    (*post_root_reset_end)(struct musb *musb);
-       void    (*phy_callback)(enum musb_vbus_id_status status);
+       int     (*phy_callback)(enum musb_vbus_id_status status);
 };
 
 /*
@@ -312,6 +312,7 @@ struct musb {
        struct work_struct      irq_work;
        struct delayed_work     deassert_reset_work;
        struct delayed_work     finish_resume_work;
+       struct delayed_work     gadget_work;
        u16                     hwvers;
 
        u16                     intrrxe;
index 152865b..af2a3a7 100644 (file)
@@ -1656,6 +1656,20 @@ static int musb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA)
        return usb_phy_set_power(musb->xceiv, mA);
 }
 
+static void musb_gadget_work(struct work_struct *work)
+{
+       struct musb *musb;
+       unsigned long flags;
+
+       musb = container_of(work, struct musb, gadget_work.work);
+       pm_runtime_get_sync(musb->controller);
+       spin_lock_irqsave(&musb->lock, flags);
+       musb_pullup(musb, musb->softconnect);
+       spin_unlock_irqrestore(&musb->lock, flags);
+       pm_runtime_mark_last_busy(musb->controller);
+       pm_runtime_put_autosuspend(musb->controller);
+}
+
 static int musb_gadget_pullup(struct usb_gadget *gadget, int is_on)
 {
        struct musb     *musb = gadget_to_musb(gadget);
@@ -1663,20 +1677,16 @@ static int musb_gadget_pullup(struct usb_gadget *gadget, int is_on)
 
        is_on = !!is_on;
 
-       pm_runtime_get_sync(musb->controller);
-
        /* NOTE: this assumes we are sensing vbus; we'd rather
         * not pullup unless the B-session is active.
         */
        spin_lock_irqsave(&musb->lock, flags);
        if (is_on != musb->softconnect) {
                musb->softconnect = is_on;
-               musb_pullup(musb, is_on);
+               schedule_delayed_work(&musb->gadget_work, 0);
        }
        spin_unlock_irqrestore(&musb->lock, flags);
 
-       pm_runtime_put(musb->controller);
-
        return 0;
 }
 
@@ -1845,7 +1855,7 @@ int musb_gadget_setup(struct musb *musb)
 #elif IS_ENABLED(CONFIG_USB_MUSB_GADGET)
        musb->g.is_otg = 0;
 #endif
-
+       INIT_DELAYED_WORK(&musb->gadget_work, musb_gadget_work);
        musb_g_init_endpoints(musb);
 
        musb->is_active = 0;
@@ -1866,6 +1876,8 @@ void musb_gadget_cleanup(struct musb *musb)
 {
        if (musb->port_mode == MUSB_PORT_MODE_HOST)
                return;
+
+       cancel_delayed_work_sync(&musb->gadget_work);
        usb_del_gadget_udc(&musb->g);
 }
 
@@ -1914,8 +1926,8 @@ static int musb_gadget_start(struct usb_gadget *g,
        if (musb->xceiv->last_event == USB_EVENT_ID)
                musb_platform_set_vbus(musb, 1);
 
-       if (musb->xceiv->last_event == USB_EVENT_NONE)
-               pm_runtime_put(musb->controller);
+       pm_runtime_mark_last_busy(musb->controller);
+       pm_runtime_put_autosuspend(musb->controller);
 
        return 0;
 
@@ -1934,8 +1946,7 @@ static int musb_gadget_stop(struct usb_gadget *g)
        struct musb     *musb = gadget_to_musb(g);
        unsigned long   flags;
 
-       if (musb->xceiv->last_event == USB_EVENT_NONE)
-               pm_runtime_get_sync(musb->controller);
+       pm_runtime_get_sync(musb->controller);
 
        /*
         * REVISIT always use otg_set_peripheral() here too;
@@ -1963,7 +1974,8 @@ static int musb_gadget_stop(struct usb_gadget *g)
         * that currently misbehaves.
         */
 
-       pm_runtime_put(musb->controller);
+       pm_runtime_mark_last_busy(musb->controller);
+       pm_runtime_put_autosuspend(musb->controller);
 
        return 0;
 }
index 2f8ad7f..d227a71 100644 (file)
@@ -434,7 +434,13 @@ static void musb_advance_schedule(struct musb *musb, struct urb *urb,
                }
        }
 
-       if (qh != NULL && qh->is_ready) {
+       /*
+        * The pipe must be broken if current urb->status is set, so don't
+        * start next urb.
+        * TODO: to minimize the risk of regression, only check urb->status
+        * for RX, until we have a test case to understand the behavior of TX.
+        */
+       if ((!status || !is_in) && qh && qh->is_ready) {
                dev_dbg(musb->controller, "... next ep%d %cX urb %p\n",
                    hw_ep->epnum, is_in ? 'R' : 'T', next_urb(qh));
                musb_start_urb(musb, is_in, qh);
@@ -594,14 +600,13 @@ musb_rx_reinit(struct musb *musb, struct musb_qh *qh, u8 epnum)
                musb_writew(ep->regs, MUSB_TXCSR, 0);
 
        /* scrub all previous state, clearing toggle */
-       } else {
-               csr = musb_readw(ep->regs, MUSB_RXCSR);
-               if (csr & MUSB_RXCSR_RXPKTRDY)
-                       WARNING("rx%d, packet/%d ready?\n", ep->epnum,
-                               musb_readw(ep->regs, MUSB_RXCOUNT));
-
-               musb_h_flush_rxfifo(ep, MUSB_RXCSR_CLRDATATOG);
        }
+       csr = musb_readw(ep->regs, MUSB_RXCSR);
+       if (csr & MUSB_RXCSR_RXPKTRDY)
+               WARNING("rx%d, packet/%d ready?\n", ep->epnum,
+                       musb_readw(ep->regs, MUSB_RXCOUNT));
+
+       musb_h_flush_rxfifo(ep, MUSB_RXCSR_CLRDATATOG);
 
        /* target addr and (for multipoint) hub addr/port */
        if (musb->is_multipoint) {
@@ -627,7 +632,7 @@ musb_rx_reinit(struct musb *musb, struct musb_qh *qh, u8 epnum)
        ep->rx_reinit = 0;
 }
 
-static int musb_tx_dma_set_mode_mentor(struct dma_controller *dma,
+static void musb_tx_dma_set_mode_mentor(struct dma_controller *dma,
                struct musb_hw_ep *hw_ep, struct musb_qh *qh,
                struct urb *urb, u32 offset,
                u32 *length, u8 *mode)
@@ -664,23 +669,18 @@ static int musb_tx_dma_set_mode_mentor(struct dma_controller *dma,
        }
        channel->desired_mode = *mode;
        musb_writew(epio, MUSB_TXCSR, csr);
-
-       return 0;
 }
 
-static int musb_tx_dma_set_mode_cppi_tusb(struct dma_controller *dma,
-                                         struct musb_hw_ep *hw_ep,
-                                         struct musb_qh *qh,
-                                         struct urb *urb,
-                                         u32 offset,
-                                         u32 *length,
-                                         u8 *mode)
+static void musb_tx_dma_set_mode_cppi_tusb(struct dma_controller *dma,
+                                          struct musb_hw_ep *hw_ep,
+                                          struct musb_qh *qh,
+                                          struct urb *urb,
+                                          u32 offset,
+                                          u32 *length,
+                                          u8 *mode)
 {
        struct dma_channel *channel = hw_ep->tx_channel;
 
-       if (!is_cppi_enabled(hw_ep->musb) && !tusb_dma_omap(hw_ep->musb))
-               return -ENODEV;
-
        channel->actual_len = 0;
 
        /*
@@ -688,8 +688,6 @@ static int musb_tx_dma_set_mode_cppi_tusb(struct dma_controller *dma,
         * to identify the zero-length-final-packet case.
         */
        *mode = (urb->transfer_flags & URB_ZERO_PACKET) ? 1 : 0;
-
-       return 0;
 }
 
 static bool musb_tx_dma_program(struct dma_controller *dma,
@@ -699,15 +697,14 @@ static bool musb_tx_dma_program(struct dma_controller *dma,
        struct dma_channel      *channel = hw_ep->tx_channel;
        u16                     pkt_size = qh->maxpacket;
        u8                      mode;
-       int                     res;
 
        if (musb_dma_inventra(hw_ep->musb) || musb_dma_ux500(hw_ep->musb))
-               res = musb_tx_dma_set_mode_mentor(dma, hw_ep, qh, urb,
-                                                offset, &length, &mode);
+               musb_tx_dma_set_mode_mentor(dma, hw_ep, qh, urb, offset,
+                                           &length, &mode);
+       else if (is_cppi_enabled(hw_ep->musb) || tusb_dma_omap(hw_ep->musb))
+               musb_tx_dma_set_mode_cppi_tusb(dma, hw_ep, qh, urb, offset,
+                                              &length, &mode);
        else
-               res = musb_tx_dma_set_mode_cppi_tusb(dma, hw_ep, qh, urb,
-                                                    offset, &length, &mode);
-       if (res)
                return false;
 
        qh->segsize = length;
@@ -995,9 +992,15 @@ static void musb_bulk_nak_timeout(struct musb *musb, struct musb_hw_ep *ep,
        if (is_in) {
                dma = is_dma_capable() ? ep->rx_channel : NULL;
 
-               /* clear nak timeout bit */
+               /*
+                * Need to stop the transaction by clearing REQPKT first
+                * then the NAK Timeout bit ref MUSBMHDRC USB 2.0 HIGH-SPEED
+                * DUAL-ROLE CONTROLLER Programmer's Guide, section 9.2.2
+                */
                rx_csr = musb_readw(epio, MUSB_RXCSR);
                rx_csr |= MUSB_RXCSR_H_WZC_BITS;
+               rx_csr &= ~MUSB_RXCSR_H_REQPKT;
+               musb_writew(epio, MUSB_RXCSR, rx_csr);
                rx_csr &= ~MUSB_RXCSR_DATAERROR;
                musb_writew(epio, MUSB_RXCSR, rx_csr);
 
@@ -1551,7 +1554,7 @@ static int musb_rx_dma_iso_cppi41(struct dma_controller *dma,
                                  struct urb *urb,
                                  size_t len)
 {
-       struct dma_channel *channel = hw_ep->tx_channel;
+       struct dma_channel *channel = hw_ep->rx_channel;
        void __iomem *epio = hw_ep->regs;
        dma_addr_t *buf;
        u32 length, res;
@@ -1870,6 +1873,9 @@ void musb_host_rx(struct musb *musb, u8 epnum)
                status = -EPROTO;
                musb_writeb(epio, MUSB_RXINTERVAL, 0);
 
+               rx_csr &= ~MUSB_RXCSR_H_ERROR;
+               musb_writew(epio, MUSB_RXCSR, rx_csr);
+
        } else if (rx_csr & MUSB_RXCSR_DATAERROR) {
 
                if (USB_ENDPOINT_XFER_ISOC != qh->type) {
index c84e032..0b4cec9 100644 (file)
@@ -49,97 +49,14 @@ struct omap2430_glue {
        enum musb_vbus_id_status status;
        struct work_struct      omap_musb_mailbox_work;
        struct device           *control_otghs;
+       bool                    cable_connected;
+       bool                    enabled;
+       bool                    powered;
 };
 #define glue_to_musb(g)                platform_get_drvdata(g->musb)
 
 static struct omap2430_glue    *_glue;
 
-static struct timer_list musb_idle_timer;
-
-static void musb_do_idle(unsigned long _musb)
-{
-       struct musb     *musb = (void *)_musb;
-       unsigned long   flags;
-       u8      power;
-       u8      devctl;
-
-       spin_lock_irqsave(&musb->lock, flags);
-
-       switch (musb->xceiv->otg->state) {
-       case OTG_STATE_A_WAIT_BCON:
-
-               devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
-               if (devctl & MUSB_DEVCTL_BDEVICE) {
-                       musb->xceiv->otg->state = OTG_STATE_B_IDLE;
-                       MUSB_DEV_MODE(musb);
-               } else {
-                       musb->xceiv->otg->state = OTG_STATE_A_IDLE;
-                       MUSB_HST_MODE(musb);
-               }
-               break;
-       case OTG_STATE_A_SUSPEND:
-               /* finish RESUME signaling? */
-               if (musb->port1_status & MUSB_PORT_STAT_RESUME) {
-                       power = musb_readb(musb->mregs, MUSB_POWER);
-                       power &= ~MUSB_POWER_RESUME;
-                       dev_dbg(musb->controller, "root port resume stopped, power %02x\n", power);
-                       musb_writeb(musb->mregs, MUSB_POWER, power);
-                       musb->is_active = 1;
-                       musb->port1_status &= ~(USB_PORT_STAT_SUSPEND
-                                               | MUSB_PORT_STAT_RESUME);
-                       musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16;
-                       usb_hcd_poll_rh_status(musb->hcd);
-                       /* NOTE: it might really be A_WAIT_BCON ... */
-                       musb->xceiv->otg->state = OTG_STATE_A_HOST;
-               }
-               break;
-       case OTG_STATE_A_HOST:
-               devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
-               if (devctl &  MUSB_DEVCTL_BDEVICE)
-                       musb->xceiv->otg->state = OTG_STATE_B_IDLE;
-               else
-                       musb->xceiv->otg->state = OTG_STATE_A_WAIT_BCON;
-       default:
-               break;
-       }
-       spin_unlock_irqrestore(&musb->lock, flags);
-}
-
-
-static void omap2430_musb_try_idle(struct musb *musb, unsigned long timeout)
-{
-       unsigned long           default_timeout = jiffies + msecs_to_jiffies(3);
-       static unsigned long    last_timer;
-
-       if (timeout == 0)
-               timeout = default_timeout;
-
-       /* Never idle if active, or when VBUS timeout is not set as host */
-       if (musb->is_active || ((musb->a_wait_bcon == 0)
-                       && (musb->xceiv->otg->state == OTG_STATE_A_WAIT_BCON))) {
-               dev_dbg(musb->controller, "%s active, deleting timer\n",
-                       usb_otg_state_string(musb->xceiv->otg->state));
-               del_timer(&musb_idle_timer);
-               last_timer = jiffies;
-               return;
-       }
-
-       if (time_after(last_timer, timeout)) {
-               if (!timer_pending(&musb_idle_timer))
-                       last_timer = timeout;
-               else {
-                       dev_dbg(musb->controller, "Longer idle timer already pending, ignoring\n");
-                       return;
-               }
-       }
-       last_timer = timeout;
-
-       dev_dbg(musb->controller, "%s inactive, for idle timer for %lu ms\n",
-               usb_otg_state_string(musb->xceiv->otg->state),
-               (unsigned long)jiffies_to_msecs(timeout - jiffies));
-       mod_timer(&musb_idle_timer, timeout);
-}
-
 static void omap2430_musb_set_vbus(struct musb *musb, int is_on)
 {
        struct usb_otg  *otg = musb->xceiv->otg;
@@ -205,16 +122,6 @@ static void omap2430_musb_set_vbus(struct musb *musb, int is_on)
                musb_readb(musb->mregs, MUSB_DEVCTL));
 }
 
-static int omap2430_musb_set_mode(struct musb *musb, u8 musb_mode)
-{
-       u8      devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
-
-       devctl |= MUSB_DEVCTL_SESSION;
-       musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
-
-       return 0;
-}
-
 static inline void omap2430_low_level_exit(struct musb *musb)
 {
        u32 l;
@@ -234,22 +141,63 @@ static inline void omap2430_low_level_init(struct musb *musb)
        musb_writel(musb->mregs, OTG_FORCESTDBY, l);
 }
 
-static void omap2430_musb_mailbox(enum musb_vbus_id_status status)
+/*
+ * We can get multiple cable events so we need to keep track
+ * of the power state. Only keep power enabled if USB cable is
+ * connected and a gadget is started.
+ */
+static void omap2430_set_power(struct musb *musb, bool enabled, bool cable)
+{
+       struct device *dev = musb->controller;
+       struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
+       bool power_up;
+       int res;
+
+       if (glue->enabled != enabled)
+               glue->enabled = enabled;
+
+       if (glue->cable_connected != cable)
+               glue->cable_connected = cable;
+
+       power_up = glue->enabled && glue->cable_connected;
+       if (power_up == glue->powered) {
+               dev_warn(musb->controller, "power state already %i\n",
+                        power_up);
+               return;
+       }
+
+       glue->powered = power_up;
+
+       if (power_up) {
+               res = pm_runtime_get_sync(musb->controller);
+               if (res < 0) {
+                       dev_err(musb->controller, "could not enable: %i", res);
+                       glue->powered = false;
+               }
+       } else {
+               pm_runtime_mark_last_busy(musb->controller);
+               pm_runtime_put_autosuspend(musb->controller);
+       }
+}
+
+static int omap2430_musb_mailbox(enum musb_vbus_id_status status)
 {
        struct omap2430_glue    *glue = _glue;
 
        if (!glue) {
                pr_err("%s: musb core is not yet initialized\n", __func__);
-               return;
+               return -EPROBE_DEFER;
        }
        glue->status = status;
 
        if (!glue_to_musb(glue)) {
                pr_err("%s: musb core is not yet ready\n", __func__);
-               return;
+               return -EPROBE_DEFER;
        }
 
        schedule_work(&glue->omap_musb_mailbox_work);
+
+       return 0;
 }
 
 static void omap_musb_set_mailbox(struct omap2430_glue *glue)
@@ -259,6 +207,13 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue)
        struct musb_hdrc_platform_data *pdata = dev_get_platdata(dev);
        struct omap_musb_board_data *data = pdata->board_data;
        struct usb_otg *otg = musb->xceiv->otg;
+       bool cable_connected;
+
+       cable_connected = ((glue->status == MUSB_ID_GROUND) ||
+                          (glue->status == MUSB_VBUS_VALID));
+
+       if (cable_connected)
+               omap2430_set_power(musb, glue->enabled, cable_connected);
 
        switch (glue->status) {
        case MUSB_ID_GROUND:
@@ -268,7 +223,6 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue)
                musb->xceiv->otg->state = OTG_STATE_A_IDLE;
                musb->xceiv->last_event = USB_EVENT_ID;
                if (musb->gadget_driver) {
-                       pm_runtime_get_sync(dev);
                        omap_control_usb_set_mode(glue->control_otghs,
                                USB_MODE_HOST);
                        omap2430_musb_set_vbus(musb, 1);
@@ -281,8 +235,6 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue)
                otg->default_a = false;
                musb->xceiv->otg->state = OTG_STATE_B_IDLE;
                musb->xceiv->last_event = USB_EVENT_VBUS;
-               if (musb->gadget_driver)
-                       pm_runtime_get_sync(dev);
                omap_control_usb_set_mode(glue->control_otghs, USB_MODE_DEVICE);
                break;
 
@@ -291,11 +243,8 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue)
                dev_dbg(dev, "VBUS Disconnect\n");
 
                musb->xceiv->last_event = USB_EVENT_NONE;
-               if (musb->gadget_driver) {
+               if (musb->gadget_driver)
                        omap2430_musb_set_vbus(musb, 0);
-                       pm_runtime_mark_last_busy(dev);
-                       pm_runtime_put_autosuspend(dev);
-               }
 
                if (data->interface_type == MUSB_INTERFACE_UTMI)
                        otg_set_vbus(musb->xceiv->otg, 0);
@@ -307,6 +256,9 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue)
                dev_dbg(dev, "ID float\n");
        }
 
+       if (!cable_connected)
+               omap2430_set_power(musb, glue->enabled, cable_connected);
+
        atomic_notifier_call_chain(&musb->xceiv->notifier,
                        musb->xceiv->last_event, NULL);
 }
@@ -316,13 +268,8 @@ static void omap_musb_mailbox_work(struct work_struct *mailbox_work)
 {
        struct omap2430_glue *glue = container_of(mailbox_work,
                                struct omap2430_glue, omap_musb_mailbox_work);
-       struct musb *musb = glue_to_musb(glue);
-       struct device *dev = musb->controller;
 
-       pm_runtime_get_sync(dev);
        omap_musb_set_mailbox(glue);
-       pm_runtime_mark_last_busy(dev);
-       pm_runtime_put_autosuspend(dev);
 }
 
 static irqreturn_t omap2430_musb_interrupt(int irq, void *__hci)
@@ -389,23 +336,7 @@ static int omap2430_musb_init(struct musb *musb)
                return PTR_ERR(musb->phy);
        }
        musb->isr = omap2430_musb_interrupt;
-
-       /*
-        * Enable runtime PM for musb parent (this driver). We can't
-        * do it earlier as struct musb is not yet allocated and we
-        * need to touch the musb registers for runtime PM.
-        */
-       pm_runtime_enable(glue->dev);
-       status = pm_runtime_get_sync(glue->dev);
-       if (status < 0)
-               goto err1;
-
-       status = pm_runtime_get_sync(dev);
-       if (status < 0) {
-               dev_err(dev, "pm_runtime_get_sync FAILED %d\n", status);
-               pm_runtime_put_sync(glue->dev);
-               goto err1;
-       }
+       phy_init(musb->phy);
 
        l = musb_readl(musb->mregs, OTG_INTERFSEL);
 
@@ -427,20 +358,10 @@ static int omap2430_musb_init(struct musb *musb)
                        musb_readl(musb->mregs, OTG_INTERFSEL),
                        musb_readl(musb->mregs, OTG_SIMENABLE));
 
-       setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
-
        if (glue->status != MUSB_UNKNOWN)
                omap_musb_set_mailbox(glue);
 
-       phy_init(musb->phy);
-       phy_power_on(musb->phy);
-
-       pm_runtime_put_noidle(musb->controller);
-       pm_runtime_put_noidle(glue->dev);
        return 0;
-
-err1:
-       return status;
 }
 
 static void omap2430_musb_enable(struct musb *musb)
@@ -452,6 +373,11 @@ static void omap2430_musb_enable(struct musb *musb)
        struct musb_hdrc_platform_data *pdata = dev_get_platdata(dev);
        struct omap_musb_board_data *data = pdata->board_data;
 
+       if (!WARN_ON(!musb->phy))
+               phy_power_on(musb->phy);
+
+       omap2430_set_power(musb, true, glue->cable_connected);
+
        switch (glue->status) {
 
        case MUSB_ID_GROUND:
@@ -487,18 +413,25 @@ static void omap2430_musb_disable(struct musb *musb)
        struct device *dev = musb->controller;
        struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
 
+       if (!WARN_ON(!musb->phy))
+               phy_power_off(musb->phy);
+
        if (glue->status != MUSB_UNKNOWN)
                omap_control_usb_set_mode(glue->control_otghs,
                        USB_MODE_DISCONNECT);
+
+       omap2430_set_power(musb, false, glue->cable_connected);
 }
 
 static int omap2430_musb_exit(struct musb *musb)
 {
-       del_timer_sync(&musb_idle_timer);
+       struct device *dev = musb->controller;
+       struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
 
        omap2430_low_level_exit(musb);
-       phy_power_off(musb->phy);
        phy_exit(musb->phy);
+       musb->phy = NULL;
+       cancel_work_sync(&glue->omap_musb_mailbox_work);
 
        return 0;
 }
@@ -512,9 +445,6 @@ static const struct musb_platform_ops omap2430_ops = {
        .init           = omap2430_musb_init,
        .exit           = omap2430_musb_exit,
 
-       .set_mode       = omap2430_musb_set_mode,
-       .try_idle       = omap2430_musb_try_idle,
-
        .set_vbus       = omap2430_musb_set_vbus,
 
        .enable         = omap2430_musb_enable,
@@ -639,11 +569,9 @@ static int omap2430_probe(struct platform_device *pdev)
                goto err2;
        }
 
-       /*
-        * Note that we cannot enable PM runtime yet for this
-        * driver as we need struct musb initialized first.
-        * See omap2430_musb_init above.
-        */
+       pm_runtime_enable(glue->dev);
+       pm_runtime_use_autosuspend(glue->dev);
+       pm_runtime_set_autosuspend_delay(glue->dev, 500);
 
        ret = platform_device_add(musb);
        if (ret) {
@@ -662,12 +590,14 @@ err0:
 
 static int omap2430_remove(struct platform_device *pdev)
 {
-       struct omap2430_glue            *glue = platform_get_drvdata(pdev);
+       struct omap2430_glue *glue = platform_get_drvdata(pdev);
+       struct musb *musb = glue_to_musb(glue);
 
        pm_runtime_get_sync(glue->dev);
-       cancel_work_sync(&glue->omap_musb_mailbox_work);
        platform_device_unregister(glue->musb);
+       omap2430_set_power(musb, false, false);
        pm_runtime_put_sync(glue->dev);
+       pm_runtime_dont_use_autosuspend(glue->dev);
        pm_runtime_disable(glue->dev);
 
        return 0;
@@ -680,12 +610,13 @@ static int omap2430_runtime_suspend(struct device *dev)
        struct omap2430_glue            *glue = dev_get_drvdata(dev);
        struct musb                     *musb = glue_to_musb(glue);
 
-       if (musb) {
-               musb->context.otg_interfsel = musb_readl(musb->mregs,
-                               OTG_INTERFSEL);
+       if (!musb)
+               return 0;
 
-               omap2430_low_level_exit(musb);
-       }
+       musb->context.otg_interfsel = musb_readl(musb->mregs,
+                                                OTG_INTERFSEL);
+
+       omap2430_low_level_exit(musb);
 
        return 0;
 }
@@ -696,7 +627,7 @@ static int omap2430_runtime_resume(struct device *dev)
        struct musb                     *musb = glue_to_musb(glue);
 
        if (!musb)
-               return -EPROBE_DEFER;
+               return 0;
 
        omap2430_low_level_init(musb);
        musb_writel(musb->mregs, OTG_INTERFSEL,
@@ -738,18 +669,8 @@ static struct platform_driver omap2430_driver = {
        },
 };
 
+module_platform_driver(omap2430_driver);
+
 MODULE_DESCRIPTION("OMAP2PLUS MUSB Glue Layer");
 MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
 MODULE_LICENSE("GPL v2");
-
-static int __init omap2430_init(void)
-{
-       return platform_driver_register(&omap2430_driver);
-}
-subsys_initcall(omap2430_init);
-
-static void __exit omap2430_exit(void)
-{
-       platform_driver_unregister(&omap2430_driver);
-}
-module_exit(omap2430_exit);
index fdab423..7650051 100644 (file)
@@ -80,7 +80,8 @@ static struct musb *sunxi_musb;
 
 struct sunxi_glue {
        struct device           *dev;
-       struct platform_device  *musb;
+       struct musb             *musb;
+       struct platform_device  *musb_pdev;
        struct clk              *clk;
        struct reset_control    *rst;
        struct phy              *phy;
@@ -102,7 +103,7 @@ static void sunxi_musb_work(struct work_struct *work)
                return;
 
        if (test_and_clear_bit(SUNXI_MUSB_FL_HOSTMODE_PEND, &glue->flags)) {
-               struct musb *musb = platform_get_drvdata(glue->musb);
+               struct musb *musb = glue->musb;
                unsigned long flags;
                u8 devctl;
 
@@ -112,7 +113,7 @@ static void sunxi_musb_work(struct work_struct *work)
                if (test_bit(SUNXI_MUSB_FL_HOSTMODE, &glue->flags)) {
                        set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
                        musb->xceiv->otg->default_a = 1;
-                       musb->xceiv->otg->state = OTG_STATE_A_IDLE;
+                       musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
                        MUSB_HST_MODE(musb);
                        devctl |= MUSB_DEVCTL_SESSION;
                } else {
@@ -145,10 +146,12 @@ static void sunxi_musb_set_vbus(struct musb *musb, int is_on)
 {
        struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
 
-       if (is_on)
+       if (is_on) {
                set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
-       else
+               musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
+       } else {
                clear_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
+       }
 
        schedule_work(&glue->work);
 }
@@ -264,15 +267,6 @@ static int sunxi_musb_init(struct musb *musb)
        if (ret)
                goto error_unregister_notifier;
 
-       if (musb->port_mode == MUSB_PORT_MODE_HOST) {
-               ret = phy_power_on(glue->phy);
-               if (ret)
-                       goto error_phy_exit;
-               set_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags);
-               /* Stop musb work from turning vbus off again */
-               set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
-       }
-
        musb->isr = sunxi_musb_interrupt;
 
        /* Stop the musb-core from doing runtime pm (not supported on sunxi) */
@@ -280,8 +274,6 @@ static int sunxi_musb_init(struct musb *musb)
 
        return 0;
 
-error_phy_exit:
-       phy_exit(glue->phy);
 error_unregister_notifier:
        if (musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE)
                extcon_unregister_notifier(glue->extcon, EXTCON_USB_HOST,
@@ -323,10 +315,31 @@ static int sunxi_musb_exit(struct musb *musb)
        return 0;
 }
 
+static int sunxi_set_mode(struct musb *musb, u8 mode)
+{
+       struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
+       int ret;
+
+       if (mode == MUSB_HOST) {
+               ret = phy_power_on(glue->phy);
+               if (ret)
+                       return ret;
+
+               set_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags);
+               /* Stop musb work from turning vbus off again */
+               set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
+               musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
+       }
+
+       return 0;
+}
+
 static void sunxi_musb_enable(struct musb *musb)
 {
        struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
 
+       glue->musb = musb;
+
        /* musb_core does not call us in a balanced manner */
        if (test_and_set_bit(SUNXI_MUSB_FL_ENABLED, &glue->flags))
                return;
@@ -569,6 +582,7 @@ static const struct musb_platform_ops sunxi_musb_ops = {
        .exit           = sunxi_musb_exit,
        .enable         = sunxi_musb_enable,
        .disable        = sunxi_musb_disable,
+       .set_mode       = sunxi_set_mode,
        .fifo_offset    = sunxi_musb_fifo_offset,
        .ep_offset      = sunxi_musb_ep_offset,
        .busctl_offset  = sunxi_musb_busctl_offset,
@@ -721,9 +735,9 @@ static int sunxi_musb_probe(struct platform_device *pdev)
        pinfo.data      = &pdata;
        pinfo.size_data = sizeof(pdata);
 
-       glue->musb = platform_device_register_full(&pinfo);
-       if (IS_ERR(glue->musb)) {
-               ret = PTR_ERR(glue->musb);
+       glue->musb_pdev = platform_device_register_full(&pinfo);
+       if (IS_ERR(glue->musb_pdev)) {
+               ret = PTR_ERR(glue->musb_pdev);
                dev_err(&pdev->dev, "Error registering musb dev: %d\n", ret);
                goto err_unregister_usb_phy;
        }
@@ -740,7 +754,7 @@ static int sunxi_musb_remove(struct platform_device *pdev)
        struct sunxi_glue *glue = platform_get_drvdata(pdev);
        struct platform_device *usb_phy = glue->usb_phy;
 
-       platform_device_unregister(glue->musb); /* Frees glue ! */
+       platform_device_unregister(glue->musb_pdev);
        usb_phy_generic_unregister(usb_phy);
 
        return 0;
index 24e2b3c..a72e8d6 100644 (file)
@@ -97,6 +97,9 @@ struct twl6030_usb {
 
        struct regulator                *usb3v3;
 
+       /* used to check initial cable status after probe */
+       struct delayed_work     get_status_work;
+
        /* used to set vbus, in atomic path */
        struct work_struct      set_vbus_work;
 
@@ -227,12 +230,16 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
                        twl->asleep = 1;
                        status = MUSB_VBUS_VALID;
                        twl->linkstat = status;
-                       musb_mailbox(status);
+                       ret = musb_mailbox(status);
+                       if (ret)
+                               twl->linkstat = MUSB_UNKNOWN;
                } else {
                        if (twl->linkstat != MUSB_UNKNOWN) {
                                status = MUSB_VBUS_OFF;
                                twl->linkstat = status;
-                               musb_mailbox(status);
+                               ret = musb_mailbox(status);
+                               if (ret)
+                                       twl->linkstat = MUSB_UNKNOWN;
                                if (twl->asleep) {
                                        regulator_disable(twl->usb3v3);
                                        twl->asleep = 0;
@@ -264,7 +271,9 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
                twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_SET);
                status = MUSB_ID_GROUND;
                twl->linkstat = status;
-               musb_mailbox(status);
+               ret = musb_mailbox(status);
+               if (ret)
+                       twl->linkstat = MUSB_UNKNOWN;
        } else  {
                twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_CLR);
                twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET);
@@ -274,6 +283,15 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
        return IRQ_HANDLED;
 }
 
+static void twl6030_status_work(struct work_struct *work)
+{
+       struct twl6030_usb *twl = container_of(work, struct twl6030_usb,
+                                              get_status_work.work);
+
+       twl6030_usb_irq(twl->irq2, twl);
+       twl6030_usbotg_irq(twl->irq1, twl);
+}
+
 static int twl6030_enable_irq(struct twl6030_usb *twl)
 {
        twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET);
@@ -284,8 +302,6 @@ static int twl6030_enable_irq(struct twl6030_usb *twl)
                                REG_INT_MSK_LINE_C);
        twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK,
                                REG_INT_MSK_STS_C);
-       twl6030_usb_irq(twl->irq2, twl);
-       twl6030_usbotg_irq(twl->irq1, twl);
 
        return 0;
 }
@@ -371,6 +387,7 @@ static int twl6030_usb_probe(struct platform_device *pdev)
                dev_warn(&pdev->dev, "could not create sysfs file\n");
 
        INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work);
+       INIT_DELAYED_WORK(&twl->get_status_work, twl6030_status_work);
 
        status = request_threaded_irq(twl->irq1, NULL, twl6030_usbotg_irq,
                        IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT,
@@ -395,6 +412,7 @@ static int twl6030_usb_probe(struct platform_device *pdev)
 
        twl->asleep = 0;
        twl6030_enable_irq(twl);
+       schedule_delayed_work(&twl->get_status_work, HZ);
        dev_info(&pdev->dev, "Initialized TWL6030 USB module\n");
 
        return 0;
@@ -404,6 +422,7 @@ static int twl6030_usb_remove(struct platform_device *pdev)
 {
        struct twl6030_usb *twl = platform_get_drvdata(pdev);
 
+       cancel_delayed_work(&twl->get_status_work);
        twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK,
                REG_INT_MSK_LINE_C);
        twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK,
index 2eddbe5..5608af4 100644 (file)
@@ -2007,6 +2007,7 @@ static void mos7720_release(struct usb_serial *serial)
                                    urblist_entry)
                        usb_unlink_urb(urbtrack->urb);
                spin_unlock_irqrestore(&mos_parport->listlock, flags);
+               parport_del_port(mos_parport->pp);
 
                kref_put(&mos_parport->ref_count, destroy_mos_parport);
        }
index 4d49fce..5ef014b 100644 (file)
@@ -836,6 +836,7 @@ static int uas_slave_configure(struct scsi_device *sdev)
        if (devinfo->flags & US_FL_BROKEN_FUA)
                sdev->broken_fua = 1;
 
+       scsi_change_queue_depth(sdev, devinfo->qdepth - 2);
        return 0;
 }
 
@@ -848,7 +849,6 @@ static struct scsi_host_template uas_host_template = {
        .slave_configure = uas_slave_configure,
        .eh_abort_handler = uas_eh_abort_handler,
        .eh_bus_reset_handler = uas_eh_bus_reset_handler,
-       .can_queue = MAX_CMNDS,
        .this_id = -1,
        .sg_tablesize = SG_NONE,
        .skip_settle_delay = 1,
index fca5110..2e0450b 100644 (file)
@@ -941,7 +941,7 @@ static void vhci_stop(struct usb_hcd *hcd)
 
 static int vhci_get_frame_number(struct usb_hcd *hcd)
 {
-       pr_err("Not yet implemented\n");
+       dev_err_ratelimited(&hcd->self.root_hub->dev, "Not yet implemented\n");
        return 0;
 }
 
index 9360140..688691d 100644 (file)
@@ -749,7 +749,8 @@ static int vfio_vpd_config_write(struct vfio_pci_device *vdev, int pos,
                if (pci_write_vpd(pdev, addr & ~PCI_VPD_ADDR_F, 4, &data) != 4)
                        return count;
        } else {
-               if (pci_read_vpd(pdev, addr, 4, &data) != 4)
+               data = 0;
+               if (pci_read_vpd(pdev, addr, 4, &data) < 0)
                        return count;
                *pdata = cpu_to_le32(data);
        }
index e9ea3fe..15ecfc9 100644 (file)
@@ -228,9 +228,9 @@ static int vfio_intx_set_signal(struct vfio_pci_device *vdev, int fd)
 
 static void vfio_intx_disable(struct vfio_pci_device *vdev)
 {
-       vfio_intx_set_signal(vdev, -1);
        vfio_virqfd_disable(&vdev->ctx[0].unmask);
        vfio_virqfd_disable(&vdev->ctx[0].mask);
+       vfio_intx_set_signal(vdev, -1);
        vdev->irq_type = VFIO_PCI_NUM_IRQS;
        vdev->num_ctx = 0;
        kfree(vdev->ctx);
@@ -401,13 +401,13 @@ static void vfio_msi_disable(struct vfio_pci_device *vdev, bool msix)
        struct pci_dev *pdev = vdev->pdev;
        int i;
 
-       vfio_msi_set_block(vdev, 0, vdev->num_ctx, NULL, msix);
-
        for (i = 0; i < vdev->num_ctx; i++) {
                vfio_virqfd_disable(&vdev->ctx[i].unmask);
                vfio_virqfd_disable(&vdev->ctx[i].mask);
        }
 
+       vfio_msi_set_block(vdev, 0, vdev->num_ctx, NULL, msix);
+
        if (msix) {
                pci_disable_msix(vdev->pdev);
                kfree(vdev->msix);
index 15a6582..2ba1942 100644 (file)
@@ -515,7 +515,7 @@ static int map_try_harder(struct vfio_domain *domain, dma_addr_t iova,
                          unsigned long pfn, long npage, int prot)
 {
        long i;
-       int ret;
+       int ret = 0;
 
        for (i = 0; i < npage; i++, pfn++, iova += PAGE_SIZE) {
                ret = iommu_map(domain->domain, iova,
index 8ea531d..bbfe7e2 100644 (file)
@@ -51,8 +51,8 @@ static void hdmi_core_ddc_init(struct hdmi_core_data *core)
 {
        void __iomem *base = core->base;
        const unsigned long long iclk = 266000000;      /* DSS L3 ICLK */
-       const unsigned ss_scl_high = 4000;              /* ns */
-       const unsigned ss_scl_low = 4700;               /* ns */
+       const unsigned ss_scl_high = 4600;              /* ns */
+       const unsigned ss_scl_low = 5400;               /* ns */
        const unsigned fs_scl_high = 600;               /* ns */
        const unsigned fs_scl_low = 1300;               /* ns */
        const unsigned sda_hold = 1000;                 /* ns */
@@ -442,7 +442,7 @@ static void hdmi_core_write_avi_infoframe(struct hdmi_core_data *core,
 
        c = (ptr[1] >> 6) & 0x3;
        m = (ptr[1] >> 4) & 0x3;
-       r = (ptr[1] >> 0) & 0x3;
+       r = (ptr[1] >> 0) & 0xf;
 
        itc = (ptr[2] >> 7) & 0x1;
        ec = (ptr[2] >> 4) & 0x7;
index b54f26c..b4b3e25 100644 (file)
@@ -746,7 +746,7 @@ config ALIM7101_WDT
 
 config EBC_C384_WDT
        tristate "WinSystems EBC-C384 Watchdog Timer"
-       depends on X86 && ISA
+       depends on X86 && ISA_BUS_API
        select WATCHDOG_CORE
        help
          Enables watchdog timer support for the watchdog timer on the
index d46839f..e4db19e 100644 (file)
@@ -151,8 +151,6 @@ static DECLARE_WAIT_QUEUE_HEAD(balloon_wq);
 static void balloon_process(struct work_struct *work);
 static DECLARE_DELAYED_WORK(balloon_worker, balloon_process);
 
-static void release_memory_resource(struct resource *resource);
-
 /* When ballooning out (allocating memory to return to Xen) we don't really
    want the kernel to try too hard since that can trigger the oom killer. */
 #define GFP_BALLOON \
@@ -248,6 +246,19 @@ static enum bp_state update_schedule(enum bp_state state)
 }
 
 #ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG
+static void release_memory_resource(struct resource *resource)
+{
+       if (!resource)
+               return;
+
+       /*
+        * No need to reset region to identity mapped since we now
+        * know that no I/O can be in this region
+        */
+       release_resource(resource);
+       kfree(resource);
+}
+
 static struct resource *additional_memory_resource(phys_addr_t size)
 {
        struct resource *res;
@@ -286,19 +297,6 @@ static struct resource *additional_memory_resource(phys_addr_t size)
        return res;
 }
 
-static void release_memory_resource(struct resource *resource)
-{
-       if (!resource)
-               return;
-
-       /*
-        * No need to reset region to identity mapped since we now
-        * know that no I/O can be in this region
-        */
-       release_resource(resource);
-       kfree(resource);
-}
-
 static enum bp_state reserve_additional_memory(void)
 {
        long credit;
index 8e67336..6a25533 100644 (file)
@@ -183,8 +183,7 @@ int xen_pcibk_config_read(struct pci_dev *dev, int offset, int size,
                field_start = OFFSET(cfg_entry);
                field_end = OFFSET(cfg_entry) + field->size;
 
-               if ((req_start >= field_start && req_start < field_end)
-                   || (req_end > field_start && req_end <= field_end)) {
+                if (req_end > field_start && field_end > req_start) {
                        err = conf_space_read(dev, cfg_entry, field_start,
                                              &tmp_val);
                        if (err)
@@ -230,8 +229,7 @@ int xen_pcibk_config_write(struct pci_dev *dev, int offset, int size, u32 value)
                field_start = OFFSET(cfg_entry);
                field_end = OFFSET(cfg_entry) + field->size;
 
-               if ((req_start >= field_start && req_start < field_end)
-                   || (req_end > field_start && req_end <= field_end)) {
+                if (req_end > field_start && field_end > req_start) {
                        tmp_val = 0;
 
                        err = xen_pcibk_config_read(dev, field_start,
index ad3d17d..9ead1c2 100644 (file)
@@ -145,7 +145,7 @@ static int rom_write(struct pci_dev *dev, int offset, u32 value, void *data)
        /* A write to obtain the length must happen as a 32-bit write.
         * This does not (yet) support writing individual bytes
         */
-       if (value == ~PCI_ROM_ADDRESS_ENABLE)
+       if ((value | ~PCI_ROM_ADDRESS_MASK) == ~0U)
                bar->which = 1;
        else {
                u32 tmpval;
@@ -225,38 +225,42 @@ static inline void read_dev_bar(struct pci_dev *dev,
                           (PCI_BASE_ADDRESS_SPACE_MEMORY |
                                PCI_BASE_ADDRESS_MEM_TYPE_64))) {
                        bar_info->val = res[pos - 1].start >> 32;
-                       bar_info->len_val = res[pos - 1].end >> 32;
+                       bar_info->len_val = -resource_size(&res[pos - 1]) >> 32;
                        return;
                }
        }
 
+       if (!res[pos].flags ||
+           (res[pos].flags & (IORESOURCE_DISABLED | IORESOURCE_UNSET |
+                              IORESOURCE_BUSY)))
+               return;
+
        bar_info->val = res[pos].start |
                        (res[pos].flags & PCI_REGION_FLAG_MASK);
-       bar_info->len_val = resource_size(&res[pos]);
+       bar_info->len_val = -resource_size(&res[pos]) |
+                           (res[pos].flags & PCI_REGION_FLAG_MASK);
 }
 
 static void *bar_init(struct pci_dev *dev, int offset)
 {
-       struct pci_bar_info *bar = kmalloc(sizeof(*bar), GFP_KERNEL);
+       struct pci_bar_info *bar = kzalloc(sizeof(*bar), GFP_KERNEL);
 
        if (!bar)
                return ERR_PTR(-ENOMEM);
 
        read_dev_bar(dev, bar, offset, ~0);
-       bar->which = 0;
 
        return bar;
 }
 
 static void *rom_init(struct pci_dev *dev, int offset)
 {
-       struct pci_bar_info *bar = kmalloc(sizeof(*bar), GFP_KERNEL);
+       struct pci_bar_info *bar = kzalloc(sizeof(*bar), GFP_KERNEL);
 
        if (!bar)
                return ERR_PTR(-ENOMEM);
 
        read_dev_bar(dev, bar, offset, ~PCI_ROM_ADDRESS_ENABLE);
-       bar->which = 0;
 
        return bar;
 }
index f0d268b..a439548 100644 (file)
@@ -70,9 +70,13 @@ struct autofs_info {
 };
 
 #define AUTOFS_INF_EXPIRING    (1<<0) /* dentry in the process of expiring */
-#define AUTOFS_INF_NO_RCU      (1<<1) /* the dentry is being considered
+#define AUTOFS_INF_WANT_EXPIRE (1<<1) /* the dentry is being considered
                                        * for expiry, so RCU_walk is
-                                       * not permitted
+                                       * not permitted.  If it progresses to
+                                       * actual expiry attempt, the flag is
+                                       * not cleared when EXPIRING is set -
+                                       * in that case it gets cleared only
+                                       * when it comes to clearing EXPIRING.
                                        */
 #define AUTOFS_INF_PENDING     (1<<2) /* dentry pending mount */
 
index 9510d8d..b493909 100644 (file)
@@ -316,19 +316,17 @@ struct dentry *autofs4_expire_direct(struct super_block *sb,
        if (ino->flags & AUTOFS_INF_PENDING)
                goto out;
        if (!autofs4_direct_busy(mnt, root, timeout, do_now)) {
-               ino->flags |= AUTOFS_INF_NO_RCU;
+               ino->flags |= AUTOFS_INF_WANT_EXPIRE;
                spin_unlock(&sbi->fs_lock);
                synchronize_rcu();
                spin_lock(&sbi->fs_lock);
                if (!autofs4_direct_busy(mnt, root, timeout, do_now)) {
                        ino->flags |= AUTOFS_INF_EXPIRING;
-                       smp_mb();
-                       ino->flags &= ~AUTOFS_INF_NO_RCU;
                        init_completion(&ino->expire_complete);
                        spin_unlock(&sbi->fs_lock);
                        return root;
                }
-               ino->flags &= ~AUTOFS_INF_NO_RCU;
+               ino->flags &= ~AUTOFS_INF_WANT_EXPIRE;
        }
 out:
        spin_unlock(&sbi->fs_lock);
@@ -446,7 +444,7 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
        while ((dentry = get_next_positive_subdir(dentry, root))) {
                spin_lock(&sbi->fs_lock);
                ino = autofs4_dentry_ino(dentry);
-               if (ino->flags & AUTOFS_INF_NO_RCU)
+               if (ino->flags & AUTOFS_INF_WANT_EXPIRE)
                        expired = NULL;
                else
                        expired = should_expire(dentry, mnt, timeout, how);
@@ -455,7 +453,7 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
                        continue;
                }
                ino = autofs4_dentry_ino(expired);
-               ino->flags |= AUTOFS_INF_NO_RCU;
+               ino->flags |= AUTOFS_INF_WANT_EXPIRE;
                spin_unlock(&sbi->fs_lock);
                synchronize_rcu();
                spin_lock(&sbi->fs_lock);
@@ -465,7 +463,7 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
                        goto found;
                }
 
-               ino->flags &= ~AUTOFS_INF_NO_RCU;
+               ino->flags &= ~AUTOFS_INF_WANT_EXPIRE;
                if (expired != dentry)
                        dput(expired);
                spin_unlock(&sbi->fs_lock);
@@ -475,17 +473,8 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
 found:
        pr_debug("returning %p %pd\n", expired, expired);
        ino->flags |= AUTOFS_INF_EXPIRING;
-       smp_mb();
-       ino->flags &= ~AUTOFS_INF_NO_RCU;
        init_completion(&ino->expire_complete);
        spin_unlock(&sbi->fs_lock);
-       spin_lock(&sbi->lookup_lock);
-       spin_lock(&expired->d_parent->d_lock);
-       spin_lock_nested(&expired->d_lock, DENTRY_D_LOCK_NESTED);
-       list_move(&expired->d_parent->d_subdirs, &expired->d_child);
-       spin_unlock(&expired->d_lock);
-       spin_unlock(&expired->d_parent->d_lock);
-       spin_unlock(&sbi->lookup_lock);
        return expired;
 }
 
@@ -496,7 +485,7 @@ int autofs4_expire_wait(struct dentry *dentry, int rcu_walk)
        int status;
 
        /* Block on any pending expire */
-       if (!(ino->flags & (AUTOFS_INF_EXPIRING | AUTOFS_INF_NO_RCU)))
+       if (!(ino->flags & AUTOFS_INF_WANT_EXPIRE))
                return 0;
        if (rcu_walk)
                return -ECHILD;
@@ -554,7 +543,7 @@ int autofs4_expire_run(struct super_block *sb,
        ino = autofs4_dentry_ino(dentry);
        /* avoid rapid-fire expire attempts if expiry fails */
        ino->last_used = now;
-       ino->flags &= ~AUTOFS_INF_EXPIRING;
+       ino->flags &= ~(AUTOFS_INF_EXPIRING|AUTOFS_INF_WANT_EXPIRE);
        complete_all(&ino->expire_complete);
        spin_unlock(&sbi->fs_lock);
 
@@ -583,7 +572,7 @@ int autofs4_do_expire_multi(struct super_block *sb, struct vfsmount *mnt,
                spin_lock(&sbi->fs_lock);
                /* avoid rapid-fire expire attempts if expiry fails */
                ino->last_used = now;
-               ino->flags &= ~AUTOFS_INF_EXPIRING;
+               ino->flags &= ~(AUTOFS_INF_EXPIRING|AUTOFS_INF_WANT_EXPIRE);
                complete_all(&ino->expire_complete);
                spin_unlock(&sbi->fs_lock);
                dput(dentry);
index 78bd802..3767f66 100644 (file)
@@ -458,7 +458,7 @@ static int autofs4_d_manage(struct dentry *dentry, bool rcu_walk)
                 */
                struct inode *inode;
 
-               if (ino->flags & (AUTOFS_INF_EXPIRING | AUTOFS_INF_NO_RCU))
+               if (ino->flags & AUTOFS_INF_WANT_EXPIRE)
                        return 0;
                if (d_mountpoint(dentry))
                        return 0;
index 0146d91..631f155 100644 (file)
@@ -66,11 +66,12 @@ static int autofs4_write(struct autofs_sb_info *sbi,
        set_fs(KERNEL_DS);
 
        mutex_lock(&sbi->pipe_mutex);
-       wr = __vfs_write(file, data, bytes, &file->f_pos);
-       while (bytes && wr) {
+       while (bytes) {
+               wr = __vfs_write(file, data, bytes, &file->f_pos);
+               if (wr <= 0)
+                       break;
                data += wr;
                bytes -= wr;
-               wr = __vfs_write(file, data, bytes, &file->f_pos);
        }
        mutex_unlock(&sbi->pipe_mutex);
 
index e158b22..a7a2811 100644 (file)
@@ -2275,7 +2275,7 @@ static int elf_core_dump(struct coredump_params *cprm)
                goto end_coredump;
 
        /* Align to page */
-       if (!dump_skip(cprm, dataoff - cprm->file->f_pos))
+       if (!dump_skip(cprm, dataoff - cprm->pos))
                goto end_coredump;
 
        for (i = 0, vma = first_vma(current, gate_vma); vma != NULL;
index 71ade0e..2035893 100644 (file)
@@ -1787,7 +1787,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
                                goto end_coredump;
        }
 
-       if (!dump_skip(cprm, dataoff - cprm->file->f_pos))
+       if (!dump_skip(cprm, dataoff - cprm->pos))
                goto end_coredump;
 
        if (!elf_fdpic_dump_segments(cprm))
index b677a6e..7706c8d 100644 (file)
@@ -2645,7 +2645,7 @@ static void btrfsic_dump_tree_sub(const struct btrfsic_state *state,
         * This algorithm is recursive because the amount of used stack space
         * is very small and the max recursion depth is limited.
         */
-       indent_add = sprintf(buf, "%c-%llu(%s/%llu/%d)",
+       indent_add = sprintf(buf, "%c-%llu(%s/%llu/%u)",
                             btrfsic_get_block_type(state, block),
                             block->logical_bytenr, block->dev_state->name,
                             block->dev_bytenr, block->mirror_num);
index 427c36b..a85cf7d 100644 (file)
@@ -1373,7 +1373,8 @@ tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct btrfs_path *path,
 
        if (tm->op == MOD_LOG_KEY_REMOVE_WHILE_FREEING) {
                BUG_ON(tm->slot != 0);
-               eb_rewin = alloc_dummy_extent_buffer(fs_info, eb->start);
+               eb_rewin = alloc_dummy_extent_buffer(fs_info, eb->start,
+                                               eb->len);
                if (!eb_rewin) {
                        btrfs_tree_read_unlock_blocking(eb);
                        free_extent_buffer(eb);
@@ -1454,7 +1455,8 @@ get_old_root(struct btrfs_root *root, u64 time_seq)
        } else if (old_root) {
                btrfs_tree_read_unlock(eb_root);
                free_extent_buffer(eb_root);
-               eb = alloc_dummy_extent_buffer(root->fs_info, logical);
+               eb = alloc_dummy_extent_buffer(root->fs_info, logical,
+                                       root->nodesize);
        } else {
                btrfs_set_lock_blocking_rw(eb_root, BTRFS_READ_LOCK);
                eb = btrfs_clone_extent_buffer(eb_root);
@@ -1552,6 +1554,7 @@ noinline int btrfs_cow_block(struct btrfs_trans_handle *trans,
                       trans->transid, root->fs_info->generation);
 
        if (!should_cow_block(trans, root, buf)) {
+               trans->dirty = true;
                *cow_ret = buf;
                return 0;
        }
@@ -1783,10 +1786,12 @@ static noinline int generic_bin_search(struct extent_buffer *eb,
                        if (!err) {
                                tmp = (struct btrfs_disk_key *)(kaddr + offset -
                                                        map_start);
-                       } else {
+                       } else if (err == 1) {
                                read_extent_buffer(eb, &unaligned,
                                                   offset, sizeof(unaligned));
                                tmp = &unaligned;
+                       } else {
+                               return err;
                        }
 
                } else {
@@ -2510,6 +2515,8 @@ read_block_for_search(struct btrfs_trans_handle *trans,
                if (!btrfs_buffer_uptodate(tmp, 0, 0))
                        ret = -EIO;
                free_extent_buffer(tmp);
+       } else {
+               ret = PTR_ERR(tmp);
        }
        return ret;
 }
@@ -2773,8 +2780,10 @@ again:
                         * then we don't want to set the path blocking,
                         * so we test it here
                         */
-                       if (!should_cow_block(trans, root, b))
+                       if (!should_cow_block(trans, root, b)) {
+                               trans->dirty = true;
                                goto cow_done;
+                       }
 
                        /*
                         * must have write locks on this node and the
@@ -2823,6 +2832,8 @@ cow_done:
                }
 
                ret = key_search(b, key, level, &prev_cmp, &slot);
+               if (ret < 0)
+                       goto done;
 
                if (level != 0) {
                        int dec = 0;
index 101c3cf..4274a7b 100644 (file)
@@ -2518,7 +2518,7 @@ void btrfs_put_block_group(struct btrfs_block_group_cache *cache);
 int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
                           struct btrfs_root *root, unsigned long count);
 int btrfs_async_run_delayed_refs(struct btrfs_root *root,
-                                unsigned long count, int wait);
+                                unsigned long count, u64 transid, int wait);
 int btrfs_lookup_data_extent(struct btrfs_root *root, u64 start, u64 len);
 int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans,
                             struct btrfs_root *root, u64 bytenr,
index 61561c2..d3aaabb 100644 (file)
@@ -1606,15 +1606,23 @@ int btrfs_inode_delayed_dir_index_count(struct inode *inode)
        return 0;
 }
 
-void btrfs_get_delayed_items(struct inode *inode, struct list_head *ins_list,
-                            struct list_head *del_list)
+bool btrfs_readdir_get_delayed_items(struct inode *inode,
+                                    struct list_head *ins_list,
+                                    struct list_head *del_list)
 {
        struct btrfs_delayed_node *delayed_node;
        struct btrfs_delayed_item *item;
 
        delayed_node = btrfs_get_delayed_node(inode);
        if (!delayed_node)
-               return;
+               return false;
+
+       /*
+        * We can only do one readdir with delayed items at a time because of
+        * item->readdir_list.
+        */
+       inode_unlock_shared(inode);
+       inode_lock(inode);
 
        mutex_lock(&delayed_node->mutex);
        item = __btrfs_first_delayed_insertion_item(delayed_node);
@@ -1641,10 +1649,13 @@ void btrfs_get_delayed_items(struct inode *inode, struct list_head *ins_list,
         * requeue or dequeue this delayed node.
         */
        atomic_dec(&delayed_node->refs);
+
+       return true;
 }
 
-void btrfs_put_delayed_items(struct list_head *ins_list,
-                            struct list_head *del_list)
+void btrfs_readdir_put_delayed_items(struct inode *inode,
+                                    struct list_head *ins_list,
+                                    struct list_head *del_list)
 {
        struct btrfs_delayed_item *curr, *next;
 
@@ -1659,6 +1670,12 @@ void btrfs_put_delayed_items(struct list_head *ins_list,
                if (atomic_dec_and_test(&curr->refs))
                        kfree(curr);
        }
+
+       /*
+        * The VFS is going to do up_read(), so we need to downgrade back to a
+        * read lock.
+        */
+       downgrade_write(&inode->i_rwsem);
 }
 
 int btrfs_should_delete_dir_index(struct list_head *del_list,
index 0167853..2495b3d 100644 (file)
@@ -137,10 +137,12 @@ void btrfs_kill_all_delayed_nodes(struct btrfs_root *root);
 void btrfs_destroy_delayed_inodes(struct btrfs_root *root);
 
 /* Used for readdir() */
-void btrfs_get_delayed_items(struct inode *inode, struct list_head *ins_list,
-                            struct list_head *del_list);
-void btrfs_put_delayed_items(struct list_head *ins_list,
-                            struct list_head *del_list);
+bool btrfs_readdir_get_delayed_items(struct inode *inode,
+                                    struct list_head *ins_list,
+                                    struct list_head *del_list);
+void btrfs_readdir_put_delayed_items(struct inode *inode,
+                                    struct list_head *ins_list,
+                                    struct list_head *del_list);
 int btrfs_should_delete_dir_index(struct list_head *del_list,
                                  u64 index);
 int btrfs_readdir_delayed_dir_index(struct dir_context *ctx,
index 6628fca..60ce119 100644 (file)
@@ -1098,7 +1098,7 @@ void readahead_tree_block(struct btrfs_root *root, u64 bytenr)
        struct inode *btree_inode = root->fs_info->btree_inode;
 
        buf = btrfs_find_create_tree_block(root, bytenr);
-       if (!buf)
+       if (IS_ERR(buf))
                return;
        read_extent_buffer_pages(&BTRFS_I(btree_inode)->io_tree,
                                 buf, 0, WAIT_NONE, btree_get_extent, 0);
@@ -1114,7 +1114,7 @@ int reada_tree_block_flagged(struct btrfs_root *root, u64 bytenr,
        int ret;
 
        buf = btrfs_find_create_tree_block(root, bytenr);
-       if (!buf)
+       if (IS_ERR(buf))
                return 0;
 
        set_bit(EXTENT_BUFFER_READAHEAD, &buf->bflags);
@@ -1147,7 +1147,8 @@ struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root,
                                                 u64 bytenr)
 {
        if (btrfs_test_is_dummy_root(root))
-               return alloc_test_extent_buffer(root->fs_info, bytenr);
+               return alloc_test_extent_buffer(root->fs_info, bytenr,
+                               root->nodesize);
        return alloc_extent_buffer(root->fs_info, bytenr);
 }
 
@@ -1171,8 +1172,8 @@ struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
        int ret;
 
        buf = btrfs_find_create_tree_block(root, bytenr);
-       if (!buf)
-               return ERR_PTR(-ENOMEM);
+       if (IS_ERR(buf))
+               return buf;
 
        ret = btree_read_extent_buffer_pages(root, buf, 0, parent_transid);
        if (ret) {
@@ -1314,14 +1315,16 @@ static struct btrfs_root *btrfs_alloc_root(struct btrfs_fs_info *fs_info,
 
 #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
 /* Should only be used by the testing infrastructure */
-struct btrfs_root *btrfs_alloc_dummy_root(void)
+struct btrfs_root *btrfs_alloc_dummy_root(u32 sectorsize, u32 nodesize)
 {
        struct btrfs_root *root;
 
        root = btrfs_alloc_root(NULL, GFP_KERNEL);
        if (!root)
                return ERR_PTR(-ENOMEM);
-       __setup_root(4096, 4096, 4096, root, NULL, 1);
+       /* We don't use the stripesize in selftest, set it as sectorsize */
+       __setup_root(nodesize, sectorsize, sectorsize, root, NULL,
+                       BTRFS_ROOT_TREE_OBJECTID);
        set_bit(BTRFS_ROOT_DUMMY_ROOT, &root->state);
        root->alloc_bytenr = 0;
 
@@ -1803,6 +1806,13 @@ static int cleaner_kthread(void *arg)
                if (btrfs_need_cleaner_sleep(root))
                        goto sleep;
 
+               /*
+                * Do not do anything if we might cause open_ctree() to block
+                * before we have finished mounting the filesystem.
+                */
+               if (!root->fs_info->open)
+                       goto sleep;
+
                if (!mutex_trylock(&root->fs_info->cleaner_mutex))
                        goto sleep;
 
@@ -2517,7 +2527,6 @@ int open_ctree(struct super_block *sb,
        int num_backups_tried = 0;
        int backup_index = 0;
        int max_active;
-       bool cleaner_mutex_locked = false;
 
        tree_root = fs_info->tree_root = btrfs_alloc_root(fs_info, GFP_KERNEL);
        chunk_root = fs_info->chunk_root = btrfs_alloc_root(fs_info, GFP_KERNEL);
@@ -2797,7 +2806,7 @@ int open_ctree(struct super_block *sb,
 
        nodesize = btrfs_super_nodesize(disk_super);
        sectorsize = btrfs_super_sectorsize(disk_super);
-       stripesize = btrfs_super_stripesize(disk_super);
+       stripesize = sectorsize;
        fs_info->dirty_metadata_batch = nodesize * (1 + ilog2(nr_cpu_ids));
        fs_info->delalloc_batch = sectorsize * 512 * (1 + ilog2(nr_cpu_ids));
 
@@ -2996,13 +3005,6 @@ retry_root_backup:
                goto fail_sysfs;
        }
 
-       /*
-        * Hold the cleaner_mutex thread here so that we don't block
-        * for a long time on btrfs_recover_relocation.  cleaner_kthread
-        * will wait for us to finish mounting the filesystem.
-        */
-       mutex_lock(&fs_info->cleaner_mutex);
-       cleaner_mutex_locked = true;
        fs_info->cleaner_kthread = kthread_run(cleaner_kthread, tree_root,
                                               "btrfs-cleaner");
        if (IS_ERR(fs_info->cleaner_kthread))
@@ -3062,8 +3064,10 @@ retry_root_backup:
                ret = btrfs_cleanup_fs_roots(fs_info);
                if (ret)
                        goto fail_qgroup;
-               /* We locked cleaner_mutex before creating cleaner_kthread. */
+
+               mutex_lock(&fs_info->cleaner_mutex);
                ret = btrfs_recover_relocation(tree_root);
+               mutex_unlock(&fs_info->cleaner_mutex);
                if (ret < 0) {
                        btrfs_warn(fs_info, "failed to recover relocation: %d",
                                        ret);
@@ -3071,8 +3075,6 @@ retry_root_backup:
                        goto fail_qgroup;
                }
        }
-       mutex_unlock(&fs_info->cleaner_mutex);
-       cleaner_mutex_locked = false;
 
        location.objectid = BTRFS_FS_TREE_OBJECTID;
        location.type = BTRFS_ROOT_ITEM_KEY;
@@ -3186,10 +3188,6 @@ fail_cleaner:
        filemap_write_and_wait(fs_info->btree_inode->i_mapping);
 
 fail_sysfs:
-       if (cleaner_mutex_locked) {
-               mutex_unlock(&fs_info->cleaner_mutex);
-               cleaner_mutex_locked = false;
-       }
        btrfs_sysfs_remove_mounted(fs_info);
 
 fail_fsdev_sysfs:
@@ -4130,6 +4128,16 @@ static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info,
         * Hint to catch really bogus numbers, bitflips or so, more exact checks are
         * done later
         */
+       if (btrfs_super_bytes_used(sb) < 6 * btrfs_super_nodesize(sb)) {
+               btrfs_err(fs_info, "bytes_used is too small %llu",
+                      btrfs_super_bytes_used(sb));
+               ret = -EINVAL;
+       }
+       if (!is_power_of_2(btrfs_super_stripesize(sb))) {
+               btrfs_err(fs_info, "invalid stripesize %u",
+                      btrfs_super_stripesize(sb));
+               ret = -EINVAL;
+       }
        if (btrfs_super_num_devices(sb) > (1UL << 31))
                printk(KERN_WARNING "BTRFS: suspicious number of devices: %llu\n",
                                btrfs_super_num_devices(sb));
index 8e79d00..acba821 100644 (file)
@@ -90,7 +90,7 @@ void btrfs_drop_and_free_fs_root(struct btrfs_fs_info *fs_info,
 void btrfs_free_fs_root(struct btrfs_root *root);
 
 #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
-struct btrfs_root *btrfs_alloc_dummy_root(void);
+struct btrfs_root *btrfs_alloc_dummy_root(u32 sectorsize, u32 nodesize);
 #endif
 
 /*
index a400951..82b912a 100644 (file)
@@ -2042,6 +2042,11 @@ int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr,
        struct btrfs_bio *bbio = NULL;
 
 
+       /*
+        * Avoid races with device replace and make sure our bbio has devices
+        * associated to its stripes that don't go away while we are discarding.
+        */
+       btrfs_bio_counter_inc_blocked(root->fs_info);
        /* Tell the block device(s) that the sectors can be discarded */
        ret = btrfs_map_block(root->fs_info, REQ_DISCARD,
                              bytenr, &num_bytes, &bbio, 0);
@@ -2074,6 +2079,7 @@ int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr,
                }
                btrfs_put_bbio(bbio);
        }
+       btrfs_bio_counter_dec(root->fs_info);
 
        if (actual_bytes)
                *actual_bytes = discarded_bytes;
@@ -2829,6 +2835,7 @@ int btrfs_should_throttle_delayed_refs(struct btrfs_trans_handle *trans,
 
 struct async_delayed_refs {
        struct btrfs_root *root;
+       u64 transid;
        int count;
        int error;
        int sync;
@@ -2844,6 +2851,10 @@ static void delayed_ref_async_start(struct btrfs_work *work)
 
        async = container_of(work, struct async_delayed_refs, work);
 
+       /* if the commit is already started, we don't need to wait here */
+       if (btrfs_transaction_blocked(async->root->fs_info))
+               goto done;
+
        trans = btrfs_join_transaction(async->root);
        if (IS_ERR(trans)) {
                async->error = PTR_ERR(trans);
@@ -2855,10 +2866,15 @@ static void delayed_ref_async_start(struct btrfs_work *work)
         * wait on delayed refs
         */
        trans->sync = true;
+
+       /* Don't bother flushing if we got into a different transaction */
+       if (trans->transid > async->transid)
+               goto end;
+
        ret = btrfs_run_delayed_refs(trans, async->root, async->count);
        if (ret)
                async->error = ret;
-
+end:
        ret = btrfs_end_transaction(trans, async->root);
        if (ret && !async->error)
                async->error = ret;
@@ -2870,7 +2886,7 @@ done:
 }
 
 int btrfs_async_run_delayed_refs(struct btrfs_root *root,
-                                unsigned long count, int wait)
+                                unsigned long count, u64 transid, int wait)
 {
        struct async_delayed_refs *async;
        int ret;
@@ -2882,6 +2898,7 @@ int btrfs_async_run_delayed_refs(struct btrfs_root *root,
        async->root = root->fs_info->tree_root;
        async->count = count;
        async->error = 0;
+       async->transid = transid;
        if (wait)
                async->sync = 1;
        else
@@ -8010,8 +8027,9 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root,
        struct extent_buffer *buf;
 
        buf = btrfs_find_create_tree_block(root, bytenr);
-       if (!buf)
-               return ERR_PTR(-ENOMEM);
+       if (IS_ERR(buf))
+               return buf;
+
        btrfs_set_header_generation(buf, trans->transid);
        btrfs_set_buffer_lockdep_class(root->root_key.objectid, buf, level);
        btrfs_tree_lock(buf);
@@ -8038,7 +8056,7 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root,
                set_extent_dirty(&trans->transaction->dirty_pages, buf->start,
                         buf->start + buf->len - 1, GFP_NOFS);
        }
-       trans->blocks_used++;
+       trans->dirty = true;
        /* this returns a buffer locked for blocking */
        return buf;
 }
@@ -8653,8 +8671,9 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,
        next = btrfs_find_tree_block(root->fs_info, bytenr);
        if (!next) {
                next = btrfs_find_create_tree_block(root, bytenr);
-               if (!next)
-                       return -ENOMEM;
+               if (IS_ERR(next))
+                       return PTR_ERR(next);
+
                btrfs_set_buffer_lockdep_class(root->root_key.objectid, next,
                                               level - 1);
                reada = 1;
index 3cd5782..75533ad 100644 (file)
@@ -2025,9 +2025,16 @@ int repair_io_failure(struct inode *inode, u64 start, u64 length, u64 logical,
        bio->bi_iter.bi_size = 0;
        map_length = length;
 
+       /*
+        * Avoid races with device replace and make sure our bbio has devices
+        * associated to its stripes that don't go away while we are doing the
+        * read repair operation.
+        */
+       btrfs_bio_counter_inc_blocked(fs_info);
        ret = btrfs_map_block(fs_info, WRITE, logical,
                              &map_length, &bbio, mirror_num);
        if (ret) {
+               btrfs_bio_counter_dec(fs_info);
                bio_put(bio);
                return -EIO;
        }
@@ -2037,6 +2044,7 @@ int repair_io_failure(struct inode *inode, u64 start, u64 length, u64 logical,
        dev = bbio->stripes[mirror_num-1].dev;
        btrfs_put_bbio(bbio);
        if (!dev || !dev->bdev || !dev->writeable) {
+               btrfs_bio_counter_dec(fs_info);
                bio_put(bio);
                return -EIO;
        }
@@ -2045,6 +2053,7 @@ int repair_io_failure(struct inode *inode, u64 start, u64 length, u64 logical,
 
        if (btrfsic_submit_bio_wait(WRITE_SYNC, bio)) {
                /* try to remap that extent elsewhere? */
+               btrfs_bio_counter_dec(fs_info);
                bio_put(bio);
                btrfs_dev_stat_inc_and_print(dev, BTRFS_DEV_STAT_WRITE_ERRS);
                return -EIO;
@@ -2054,6 +2063,7 @@ int repair_io_failure(struct inode *inode, u64 start, u64 length, u64 logical,
                "read error corrected: ino %llu off %llu (dev %s sector %llu)",
                                  btrfs_ino(inode), start,
                                  rcu_str_deref(dev->name), sector);
+       btrfs_bio_counter_dec(fs_info);
        bio_put(bio);
        return 0;
 }
@@ -4718,16 +4728,16 @@ err:
 }
 
 struct extent_buffer *alloc_dummy_extent_buffer(struct btrfs_fs_info *fs_info,
-                                               u64 start)
+                                               u64 start, u32 nodesize)
 {
        unsigned long len;
 
        if (!fs_info) {
                /*
                 * Called only from tests that don't always have a fs_info
-                * available, but we know that nodesize is 4096
+                * available
                 */
-               len = 4096;
+               len = nodesize;
        } else {
                len = fs_info->tree_root->nodesize;
        }
@@ -4823,7 +4833,7 @@ struct extent_buffer *find_extent_buffer(struct btrfs_fs_info *fs_info,
 
 #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
 struct extent_buffer *alloc_test_extent_buffer(struct btrfs_fs_info *fs_info,
-                                              u64 start)
+                                       u64 start, u32 nodesize)
 {
        struct extent_buffer *eb, *exists = NULL;
        int ret;
@@ -4831,7 +4841,7 @@ struct extent_buffer *alloc_test_extent_buffer(struct btrfs_fs_info *fs_info,
        eb = find_extent_buffer(fs_info, start);
        if (eb)
                return eb;
-       eb = alloc_dummy_extent_buffer(fs_info, start);
+       eb = alloc_dummy_extent_buffer(fs_info, start, nodesize);
        if (!eb)
                return NULL;
        eb->fs_info = fs_info;
@@ -4882,18 +4892,25 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info,
        int uptodate = 1;
        int ret;
 
+       if (!IS_ALIGNED(start, fs_info->tree_root->sectorsize)) {
+               btrfs_err(fs_info, "bad tree block start %llu", start);
+               return ERR_PTR(-EINVAL);
+       }
+
        eb = find_extent_buffer(fs_info, start);
        if (eb)
                return eb;
 
        eb = __alloc_extent_buffer(fs_info, start, len);
        if (!eb)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        for (i = 0; i < num_pages; i++, index++) {
                p = find_or_create_page(mapping, index, GFP_NOFS|__GFP_NOFAIL);
-               if (!p)
+               if (!p) {
+                       exists = ERR_PTR(-ENOMEM);
                        goto free_eb;
+               }
 
                spin_lock(&mapping->private_lock);
                if (PagePrivate(p)) {
@@ -4938,8 +4955,10 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info,
                set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags);
 again:
        ret = radix_tree_preload(GFP_NOFS);
-       if (ret)
+       if (ret) {
+               exists = ERR_PTR(ret);
                goto free_eb;
+       }
 
        spin_lock(&fs_info->buffer_lock);
        ret = radix_tree_insert(&fs_info->buffer_radix,
@@ -5323,6 +5342,11 @@ int read_extent_buffer_to_user(struct extent_buffer *eb, void __user *dstv,
        return ret;
 }
 
+/*
+ * return 0 if the item is found within a page.
+ * return 1 if the item spans two pages.
+ * return -EINVAL otherwise.
+ */
 int map_private_extent_buffer(struct extent_buffer *eb, unsigned long start,
                               unsigned long min_len, char **map,
                               unsigned long *map_start,
@@ -5337,7 +5361,7 @@ int map_private_extent_buffer(struct extent_buffer *eb, unsigned long start,
                PAGE_SHIFT;
 
        if (i != end_i)
-               return -EINVAL;
+               return 1;
 
        if (i == 0) {
                offset = start_offset;
index 1baf19c..c0c1c4f 100644 (file)
@@ -348,7 +348,7 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info,
 struct extent_buffer *__alloc_dummy_extent_buffer(struct btrfs_fs_info *fs_info,
                                                  u64 start, unsigned long len);
 struct extent_buffer *alloc_dummy_extent_buffer(struct btrfs_fs_info *fs_info,
-                                               u64 start);
+                                               u64 start, u32 nodesize);
 struct extent_buffer *btrfs_clone_extent_buffer(struct extent_buffer *src);
 struct extent_buffer *find_extent_buffer(struct btrfs_fs_info *fs_info,
                                         u64 start);
@@ -468,5 +468,5 @@ noinline u64 find_lock_delalloc_range(struct inode *inode,
                                      u64 *end, u64 max_bytes);
 #endif
 struct extent_buffer *alloc_test_extent_buffer(struct btrfs_fs_info *fs_info,
-                                              u64 start);
+                                              u64 start, u32 nodesize);
 #endif
index e0c9bd3..2234e88 100644 (file)
@@ -1534,30 +1534,30 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file,
                reserve_bytes = round_up(write_bytes + sector_offset,
                                root->sectorsize);
 
-               if ((BTRFS_I(inode)->flags & (BTRFS_INODE_NODATACOW |
-                                             BTRFS_INODE_PREALLOC)) &&
-                   check_can_nocow(inode, pos, &write_bytes) > 0) {
-                       /*
-                        * For nodata cow case, no need to reserve
-                        * data space.
-                        */
-                       only_release_metadata = true;
-                       /*
-                        * our prealloc extent may be smaller than
-                        * write_bytes, so scale down.
-                        */
-                       num_pages = DIV_ROUND_UP(write_bytes + offset,
-                                                PAGE_SIZE);
-                       reserve_bytes = round_up(write_bytes + sector_offset,
-                                       root->sectorsize);
-                       goto reserve_metadata;
-               }
-
                ret = btrfs_check_data_free_space(inode, pos, write_bytes);
-               if (ret < 0)
-                       break;
+               if (ret < 0) {
+                       if ((BTRFS_I(inode)->flags & (BTRFS_INODE_NODATACOW |
+                                                     BTRFS_INODE_PREALLOC)) &&
+                           check_can_nocow(inode, pos, &write_bytes) > 0) {
+                               /*
+                                * For nodata cow case, no need to reserve
+                                * data space.
+                                */
+                               only_release_metadata = true;
+                               /*
+                                * our prealloc extent may be smaller than
+                                * write_bytes, so scale down.
+                                */
+                               num_pages = DIV_ROUND_UP(write_bytes + offset,
+                                                        PAGE_SIZE);
+                               reserve_bytes = round_up(write_bytes +
+                                                        sector_offset,
+                                                        root->sectorsize);
+                       } else {
+                               break;
+                       }
+               }
 
-reserve_metadata:
                ret = btrfs_delalloc_reserve_metadata(inode, reserve_bytes);
                if (ret) {
                        if (!only_release_metadata)
index c6dc118..69d270f 100644 (file)
@@ -29,7 +29,7 @@
 #include "inode-map.h"
 #include "volumes.h"
 
-#define BITS_PER_BITMAP                (PAGE_SIZE * 8)
+#define BITS_PER_BITMAP                (PAGE_SIZE * 8UL)
 #define MAX_CACHE_BYTES_PER_GIG        SZ_32K
 
 struct btrfs_trim_range {
@@ -1415,11 +1415,11 @@ static inline u64 offset_to_bitmap(struct btrfs_free_space_ctl *ctl,
                                   u64 offset)
 {
        u64 bitmap_start;
-       u32 bytes_per_bitmap;
+       u64 bytes_per_bitmap;
 
        bytes_per_bitmap = BITS_PER_BITMAP * ctl->unit;
        bitmap_start = offset - ctl->start;
-       bitmap_start = div_u64(bitmap_start, bytes_per_bitmap);
+       bitmap_start = div64_u64(bitmap_start, bytes_per_bitmap);
        bitmap_start *= bytes_per_bitmap;
        bitmap_start += ctl->start;
 
@@ -1638,10 +1638,10 @@ static void recalculate_thresholds(struct btrfs_free_space_ctl *ctl)
        u64 bitmap_bytes;
        u64 extent_bytes;
        u64 size = block_group->key.offset;
-       u32 bytes_per_bg = BITS_PER_BITMAP * ctl->unit;
-       u32 max_bitmaps = div_u64(size + bytes_per_bg - 1, bytes_per_bg);
+       u64 bytes_per_bg = BITS_PER_BITMAP * ctl->unit;
+       u64 max_bitmaps = div64_u64(size + bytes_per_bg - 1, bytes_per_bg);
 
-       max_bitmaps = max_t(u32, max_bitmaps, 1);
+       max_bitmaps = max_t(u64, max_bitmaps, 1);
 
        ASSERT(ctl->total_bitmaps <= max_bitmaps);
 
@@ -1660,7 +1660,7 @@ static void recalculate_thresholds(struct btrfs_free_space_ctl *ctl)
         * sure we don't go over our overall goal of MAX_CACHE_BYTES_PER_GIG as
         * we add more bitmaps.
         */
-       bitmap_bytes = (ctl->total_bitmaps + 1) * PAGE_SIZE;
+       bitmap_bytes = (ctl->total_bitmaps + 1) * ctl->unit;
 
        if (bitmap_bytes >= max_bytes) {
                ctl->extents_thresh = 0;
@@ -3662,7 +3662,7 @@ have_info:
                        if (tmp->offset + tmp->bytes < offset)
                                break;
                        if (offset + bytes < tmp->offset) {
-                               n = rb_prev(&info->offset_index);
+                               n = rb_prev(&tmp->offset_index);
                                continue;
                        }
                        info = tmp;
@@ -3676,7 +3676,7 @@ have_info:
                        if (offset + bytes < tmp->offset)
                                break;
                        if (tmp->offset + tmp->bytes < offset) {
-                               n = rb_next(&info->offset_index);
+                               n = rb_next(&tmp->offset_index);
                                continue;
                        }
                        info = tmp;
index aae520b..a97fdc1 100644 (file)
@@ -24,6 +24,11 @@ int __init btrfs_hash_init(void)
        return PTR_ERR_OR_ZERO(tfm);
 }
 
+const char* btrfs_crc32c_impl(void)
+{
+       return crypto_tfm_alg_driver_name(crypto_shash_tfm(tfm));
+}
+
 void btrfs_hash_exit(void)
 {
        crypto_free_shash(tfm);
index 118a231..c3a2ec5 100644 (file)
@@ -22,6 +22,7 @@
 int __init btrfs_hash_init(void);
 
 void btrfs_hash_exit(void);
+const char* btrfs_crc32c_impl(void);
 
 u32 btrfs_crc32c(u32 crc, const void *address, unsigned int length);
 
index 2704995..4421954 100644 (file)
@@ -3271,7 +3271,16 @@ int btrfs_orphan_add(struct btrfs_trans_handle *trans, struct inode *inode)
        /* grab metadata reservation from transaction handle */
        if (reserve) {
                ret = btrfs_orphan_reserve_metadata(trans, inode);
-               BUG_ON(ret); /* -ENOSPC in reservation; Logic error? JDM */
+               ASSERT(!ret);
+               if (ret) {
+                       atomic_dec(&root->orphan_inodes);
+                       clear_bit(BTRFS_INODE_ORPHAN_META_RESERVED,
+                                 &BTRFS_I(inode)->runtime_flags);
+                       if (insert)
+                               clear_bit(BTRFS_INODE_HAS_ORPHAN_ITEM,
+                                         &BTRFS_I(inode)->runtime_flags);
+                       return ret;
+               }
        }
 
        /* insert an orphan item to track this unlinked/truncated file */
@@ -4549,6 +4558,7 @@ delete:
                        BUG_ON(ret);
                        if (btrfs_should_throttle_delayed_refs(trans, root))
                                btrfs_async_run_delayed_refs(root,
+                                                            trans->transid,
                                        trans->delayed_ref_updates * 2, 0);
                        if (be_nice) {
                                if (truncate_space_check(trans, root,
@@ -5748,6 +5758,7 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
        int name_len;
        int is_curr = 0;        /* ctx->pos points to the current index? */
        bool emitted;
+       bool put = false;
 
        /* FIXME, use a real flag for deciding about the key type */
        if (root->fs_info->tree_root == root)
@@ -5765,7 +5776,8 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
        if (key_type == BTRFS_DIR_INDEX_KEY) {
                INIT_LIST_HEAD(&ins_list);
                INIT_LIST_HEAD(&del_list);
-               btrfs_get_delayed_items(inode, &ins_list, &del_list);
+               put = btrfs_readdir_get_delayed_items(inode, &ins_list,
+                                                     &del_list);
        }
 
        key.type = key_type;
@@ -5912,8 +5924,8 @@ next:
 nopos:
        ret = 0;
 err:
-       if (key_type == BTRFS_DIR_INDEX_KEY)
-               btrfs_put_delayed_items(&ins_list, &del_list);
+       if (put)
+               btrfs_readdir_put_delayed_items(inode, &ins_list, &del_list);
        btrfs_free_path(path);
        return ret;
 }
@@ -6979,7 +6991,18 @@ insert:
                 * existing will always be non-NULL, since there must be
                 * extent causing the -EEXIST.
                 */
-               if (start >= extent_map_end(existing) ||
+               if (existing->start == em->start &&
+                   extent_map_end(existing) == extent_map_end(em) &&
+                   em->block_start == existing->block_start) {
+                       /*
+                        * these two extents are the same, it happens
+                        * with inlines especially
+                        */
+                       free_extent_map(em);
+                       em = existing;
+                       err = 0;
+
+               } else if (start >= extent_map_end(existing) ||
                    start <= existing->start) {
                        /*
                         * The existing extent map is the one nearest to
@@ -10514,7 +10537,7 @@ static const struct inode_operations btrfs_dir_ro_inode_operations = {
 static const struct file_operations btrfs_dir_file_operations = {
        .llseek         = generic_file_llseek,
        .read           = generic_read_dir,
-       .iterate        = btrfs_real_readdir,
+       .iterate_shared = btrfs_real_readdir,
        .unlocked_ioctl = btrfs_ioctl,
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = btrfs_compat_ioctl,
index 5591704..aca8264 100644 (file)
@@ -718,12 +718,13 @@ int btrfs_wait_ordered_extents(struct btrfs_root *root, int nr,
        return count;
 }
 
-void btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, int nr,
+int btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, int nr,
                              const u64 range_start, const u64 range_len)
 {
        struct btrfs_root *root;
        struct list_head splice;
        int done;
+       int total_done = 0;
 
        INIT_LIST_HEAD(&splice);
 
@@ -742,6 +743,7 @@ void btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, int nr,
                done = btrfs_wait_ordered_extents(root, nr,
                                                  range_start, range_len);
                btrfs_put_fs_root(root);
+               total_done += done;
 
                spin_lock(&fs_info->ordered_root_lock);
                if (nr != -1) {
@@ -752,6 +754,8 @@ void btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, int nr,
        list_splice_tail(&splice, &fs_info->ordered_roots);
        spin_unlock(&fs_info->ordered_root_lock);
        mutex_unlock(&fs_info->ordered_operations_mutex);
+
+       return total_done;
 }
 
 /*
@@ -964,6 +968,7 @@ int btrfs_ordered_update_i_size(struct inode *inode, u64 offset,
        struct rb_node *prev = NULL;
        struct btrfs_ordered_extent *test;
        int ret = 1;
+       u64 orig_offset = offset;
 
        spin_lock_irq(&tree->lock);
        if (ordered) {
@@ -979,7 +984,7 @@ int btrfs_ordered_update_i_size(struct inode *inode, u64 offset,
 
        /* truncate file */
        if (disk_i_size > i_size) {
-               BTRFS_I(inode)->disk_i_size = i_size;
+               BTRFS_I(inode)->disk_i_size = orig_offset;
                ret = 0;
                goto out;
        }
index 2049c9b..4515077 100644 (file)
@@ -199,7 +199,7 @@ int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u64 disk_bytenr,
                           u32 *sum, int len);
 int btrfs_wait_ordered_extents(struct btrfs_root *root, int nr,
                               const u64 range_start, const u64 range_len);
-void btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, int nr,
+int btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, int nr,
                              const u64 range_start, const u64 range_len);
 void btrfs_get_logged_extents(struct inode *inode,
                              struct list_head *logged_list,
index 298631e..8428db7 100644 (file)
@@ -761,12 +761,14 @@ static void __reada_start_machine(struct btrfs_fs_info *fs_info)
 
        do {
                enqueued = 0;
+               mutex_lock(&fs_devices->device_list_mutex);
                list_for_each_entry(device, &fs_devices->devices, dev_list) {
                        if (atomic_read(&device->reada_in_flight) <
                            MAX_IN_FLIGHT)
                                enqueued += reada_start_machine_dev(fs_info,
                                                                    device);
                }
+               mutex_unlock(&fs_devices->device_list_mutex);
                total += enqueued;
        } while (enqueued && total < 10000);
 
index 46d847f..70427ef 100644 (file)
@@ -3582,6 +3582,46 @@ int scrub_enumerate_chunks(struct scrub_ctx *sctx,
                 */
                scrub_pause_on(fs_info);
                ret = btrfs_inc_block_group_ro(root, cache);
+               if (!ret && is_dev_replace) {
+                       /*
+                        * If we are doing a device replace wait for any tasks
+                        * that started dellaloc right before we set the block
+                        * group to RO mode, as they might have just allocated
+                        * an extent from it or decided they could do a nocow
+                        * write. And if any such tasks did that, wait for their
+                        * ordered extents to complete and then commit the
+                        * current transaction, so that we can later see the new
+                        * extent items in the extent tree - the ordered extents
+                        * create delayed data references (for cow writes) when
+                        * they complete, which will be run and insert the
+                        * corresponding extent items into the extent tree when
+                        * we commit the transaction they used when running
+                        * inode.c:btrfs_finish_ordered_io(). We later use
+                        * the commit root of the extent tree to find extents
+                        * to copy from the srcdev into the tgtdev, and we don't
+                        * want to miss any new extents.
+                        */
+                       btrfs_wait_block_group_reservations(cache);
+                       btrfs_wait_nocow_writers(cache);
+                       ret = btrfs_wait_ordered_roots(fs_info, -1,
+                                                      cache->key.objectid,
+                                                      cache->key.offset);
+                       if (ret > 0) {
+                               struct btrfs_trans_handle *trans;
+
+                               trans = btrfs_join_transaction(root);
+                               if (IS_ERR(trans))
+                                       ret = PTR_ERR(trans);
+                               else
+                                       ret = btrfs_commit_transaction(trans,
+                                                                      root);
+                               if (ret) {
+                                       scrub_pause_off(fs_info);
+                                       btrfs_put_block_group(cache);
+                                       break;
+                               }
+                       }
+               }
                scrub_pause_off(fs_info);
 
                if (ret == 0) {
@@ -3602,9 +3642,11 @@ int scrub_enumerate_chunks(struct scrub_ctx *sctx,
                        break;
                }
 
+               btrfs_dev_replace_lock(&fs_info->dev_replace, 1);
                dev_replace->cursor_right = found_key.offset + length;
                dev_replace->cursor_left = found_key.offset;
                dev_replace->item_needs_writeback = 1;
+               btrfs_dev_replace_unlock(&fs_info->dev_replace, 1);
                ret = scrub_chunk(sctx, scrub_dev, chunk_offset, length,
                                  found_key.offset, cache, is_dev_replace);
 
@@ -3640,6 +3682,11 @@ int scrub_enumerate_chunks(struct scrub_ctx *sctx,
 
                scrub_pause_off(fs_info);
 
+               btrfs_dev_replace_lock(&fs_info->dev_replace, 1);
+               dev_replace->cursor_left = dev_replace->cursor_right;
+               dev_replace->item_needs_writeback = 1;
+               btrfs_dev_replace_unlock(&fs_info->dev_replace, 1);
+
                if (ro_set)
                        btrfs_dec_block_group_ro(root, cache);
 
@@ -3677,9 +3724,6 @@ int scrub_enumerate_chunks(struct scrub_ctx *sctx,
                        ret = -ENOMEM;
                        break;
                }
-
-               dev_replace->cursor_left = dev_replace->cursor_right;
-               dev_replace->item_needs_writeback = 1;
 skip:
                key.offset = found_key.offset + length;
                btrfs_release_path(path);
index 4e59a91..60e7179 100644 (file)
@@ -235,7 +235,7 @@ void __btrfs_abort_transaction(struct btrfs_trans_handle *trans,
        trans->aborted = errno;
        /* Nothing used. The other threads that have joined this
         * transaction may be able to continue. */
-       if (!trans->blocks_used && list_empty(&trans->new_bgs)) {
+       if (!trans->dirty && list_empty(&trans->new_bgs)) {
                const char *errstr;
 
                errstr = btrfs_decode_error(errno);
@@ -1807,6 +1807,8 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
                        }
                }
                sb->s_flags &= ~MS_RDONLY;
+
+               fs_info->open = 1;
        }
 out:
        wake_up_process(fs_info->transaction_kthread);
@@ -2303,7 +2305,7 @@ static void btrfs_interface_exit(void)
 
 static void btrfs_print_mod_info(void)
 {
-       printk(KERN_INFO "Btrfs loaded"
+       printk(KERN_INFO "Btrfs loaded, crc32c=%s"
 #ifdef CONFIG_BTRFS_DEBUG
                        ", debug=on"
 #endif
@@ -2313,33 +2315,48 @@ static void btrfs_print_mod_info(void)
 #ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
                        ", integrity-checker=on"
 #endif
-                       "\n");
+                       "\n",
+                       btrfs_crc32c_impl());
 }
 
 static int btrfs_run_sanity_tests(void)
 {
-       int ret;
-
+       int ret, i;
+       u32 sectorsize, nodesize;
+       u32 test_sectorsize[] = {
+               PAGE_SIZE,
+       };
        ret = btrfs_init_test_fs();
        if (ret)
                return ret;
-
-       ret = btrfs_test_free_space_cache();
-       if (ret)
-               goto out;
-       ret = btrfs_test_extent_buffer_operations();
-       if (ret)
-               goto out;
-       ret = btrfs_test_extent_io();
-       if (ret)
-               goto out;
-       ret = btrfs_test_inodes();
-       if (ret)
-               goto out;
-       ret = btrfs_test_qgroups();
-       if (ret)
-               goto out;
-       ret = btrfs_test_free_space_tree();
+       for (i = 0; i < ARRAY_SIZE(test_sectorsize); i++) {
+               sectorsize = test_sectorsize[i];
+               for (nodesize = sectorsize;
+                    nodesize <= BTRFS_MAX_METADATA_BLOCKSIZE;
+                    nodesize <<= 1) {
+                       pr_info("BTRFS: selftest: sectorsize: %u  nodesize: %u\n",
+                               sectorsize, nodesize);
+                       ret = btrfs_test_free_space_cache(sectorsize, nodesize);
+                       if (ret)
+                               goto out;
+                       ret = btrfs_test_extent_buffer_operations(sectorsize,
+                               nodesize);
+                       if (ret)
+                               goto out;
+                       ret = btrfs_test_extent_io(sectorsize, nodesize);
+                       if (ret)
+                               goto out;
+                       ret = btrfs_test_inodes(sectorsize, nodesize);
+                       if (ret)
+                               goto out;
+                       ret = btrfs_test_qgroups(sectorsize, nodesize);
+                       if (ret)
+                               goto out;
+                       ret = btrfs_test_free_space_tree(sectorsize, nodesize);
+                       if (ret)
+                               goto out;
+               }
+       }
 out:
        btrfs_destroy_test_fs();
        return ret;
index f54bf45..02223f3 100644 (file)
@@ -68,7 +68,7 @@ int btrfs_init_test_fs(void)
        if (IS_ERR(test_mnt)) {
                printk(KERN_ERR "btrfs: cannot mount test file system\n");
                unregister_filesystem(&test_type);
-               return ret;
+               return PTR_ERR(test_mnt);
        }
        return 0;
 }
@@ -175,7 +175,7 @@ void btrfs_free_dummy_root(struct btrfs_root *root)
 }
 
 struct btrfs_block_group_cache *
-btrfs_alloc_dummy_block_group(unsigned long length)
+btrfs_alloc_dummy_block_group(unsigned long length, u32 sectorsize)
 {
        struct btrfs_block_group_cache *cache;
 
@@ -192,8 +192,8 @@ btrfs_alloc_dummy_block_group(unsigned long length)
        cache->key.objectid = 0;
        cache->key.offset = length;
        cache->key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
-       cache->sectorsize = 4096;
-       cache->full_stripe_len = 4096;
+       cache->sectorsize = sectorsize;
+       cache->full_stripe_len = sectorsize;
 
        INIT_LIST_HEAD(&cache->list);
        INIT_LIST_HEAD(&cache->cluster_list);
index 054b8c7..66fb6b7 100644 (file)
 struct btrfs_root;
 struct btrfs_trans_handle;
 
-int btrfs_test_free_space_cache(void);
-int btrfs_test_extent_buffer_operations(void);
-int btrfs_test_extent_io(void);
-int btrfs_test_inodes(void);
-int btrfs_test_qgroups(void);
-int btrfs_test_free_space_tree(void);
+int btrfs_test_free_space_cache(u32 sectorsize, u32 nodesize);
+int btrfs_test_extent_buffer_operations(u32 sectorsize, u32 nodesize);
+int btrfs_test_extent_io(u32 sectorsize, u32 nodesize);
+int btrfs_test_inodes(u32 sectorsize, u32 nodesize);
+int btrfs_test_qgroups(u32 sectorsize, u32 nodesize);
+int btrfs_test_free_space_tree(u32 sectorsize, u32 nodesize);
 int btrfs_init_test_fs(void);
 void btrfs_destroy_test_fs(void);
 struct inode *btrfs_new_test_inode(void);
 struct btrfs_fs_info *btrfs_alloc_dummy_fs_info(void);
 void btrfs_free_dummy_root(struct btrfs_root *root);
 struct btrfs_block_group_cache *
-btrfs_alloc_dummy_block_group(unsigned long length);
+btrfs_alloc_dummy_block_group(unsigned long length, u32 sectorsize);
 void btrfs_free_dummy_block_group(struct btrfs_block_group_cache *cache);
 void btrfs_init_dummy_trans(struct btrfs_trans_handle *trans);
 #else
-static inline int btrfs_test_free_space_cache(void)
+static inline int btrfs_test_free_space_cache(u32 sectorsize, u32 nodesize)
 {
        return 0;
 }
-static inline int btrfs_test_extent_buffer_operations(void)
+static inline int btrfs_test_extent_buffer_operations(u32 sectorsize,
+       u32 nodesize)
 {
        return 0;
 }
@@ -57,19 +58,19 @@ static inline int btrfs_init_test_fs(void)
 static inline void btrfs_destroy_test_fs(void)
 {
 }
-static inline int btrfs_test_extent_io(void)
+static inline int btrfs_test_extent_io(u32 sectorsize, u32 nodesize)
 {
        return 0;
 }
-static inline int btrfs_test_inodes(void)
+static inline int btrfs_test_inodes(u32 sectorsize, u32 nodesize)
 {
        return 0;
 }
-static inline int btrfs_test_qgroups(void)
+static inline int btrfs_test_qgroups(u32 sectorsize, u32 nodesize)
 {
        return 0;
 }
-static inline int btrfs_test_free_space_tree(void)
+static inline int btrfs_test_free_space_tree(u32 sectorsize, u32 nodesize)
 {
        return 0;
 }
index f51963a..4f8cbd1 100644 (file)
@@ -22,7 +22,7 @@
 #include "../extent_io.h"
 #include "../disk-io.h"
 
-static int test_btrfs_split_item(void)
+static int test_btrfs_split_item(u32 sectorsize, u32 nodesize)
 {
        struct btrfs_path *path;
        struct btrfs_root *root;
@@ -40,7 +40,7 @@ static int test_btrfs_split_item(void)
 
        test_msg("Running btrfs_split_item tests\n");
 
-       root = btrfs_alloc_dummy_root();
+       root = btrfs_alloc_dummy_root(sectorsize, nodesize);
        if (IS_ERR(root)) {
                test_msg("Could not allocate root\n");
                return PTR_ERR(root);
@@ -53,7 +53,8 @@ static int test_btrfs_split_item(void)
                return -ENOMEM;
        }
 
-       path->nodes[0] = eb = alloc_dummy_extent_buffer(NULL, 4096);
+       path->nodes[0] = eb = alloc_dummy_extent_buffer(NULL, nodesize,
+                                                       nodesize);
        if (!eb) {
                test_msg("Could not allocate dummy buffer\n");
                ret = -ENOMEM;
@@ -222,8 +223,8 @@ out:
        return ret;
 }
 
-int btrfs_test_extent_buffer_operations(void)
+int btrfs_test_extent_buffer_operations(u32 sectorsize, u32 nodesize)
 {
-       test_msg("Running extent buffer operation tests");
-       return test_btrfs_split_item();
+       test_msg("Running extent buffer operation tests\n");
+       return test_btrfs_split_item(sectorsize, nodesize);
 }
index 5572460..d19ab03 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/slab.h>
 #include <linux/sizes.h>
 #include "btrfs-tests.h"
+#include "../ctree.h"
 #include "../extent_io.h"
 
 #define PROCESS_UNLOCK         (1 << 0)
@@ -65,7 +66,7 @@ static noinline int process_page_range(struct inode *inode, u64 start, u64 end,
        return count;
 }
 
-static int test_find_delalloc(void)
+static int test_find_delalloc(u32 sectorsize)
 {
        struct inode *inode;
        struct extent_io_tree tmp;
@@ -113,7 +114,7 @@ static int test_find_delalloc(void)
         * |--- delalloc ---|
         * |---  search  ---|
         */
-       set_extent_delalloc(&tmp, 0, 4095, NULL);
+       set_extent_delalloc(&tmp, 0, sectorsize - 1, NULL);
        start = 0;
        end = 0;
        found = find_lock_delalloc_range(inode, &tmp, locked_page, &start,
@@ -122,9 +123,9 @@ static int test_find_delalloc(void)
                test_msg("Should have found at least one delalloc\n");
                goto out_bits;
        }
-       if (start != 0 || end != 4095) {
-               test_msg("Expected start 0 end 4095, got start %Lu end %Lu\n",
-                        start, end);
+       if (start != 0 || end != (sectorsize - 1)) {
+               test_msg("Expected start 0 end %u, got start %llu end %llu\n",
+                       sectorsize - 1, start, end);
                goto out_bits;
        }
        unlock_extent(&tmp, start, end);
@@ -144,7 +145,7 @@ static int test_find_delalloc(void)
                test_msg("Couldn't find the locked page\n");
                goto out_bits;
        }
-       set_extent_delalloc(&tmp, 4096, max_bytes - 1, NULL);
+       set_extent_delalloc(&tmp, sectorsize, max_bytes - 1, NULL);
        start = test_start;
        end = 0;
        found = find_lock_delalloc_range(inode, &tmp, locked_page, &start,
@@ -172,7 +173,7 @@ static int test_find_delalloc(void)
         * |--- delalloc ---|
         *                    |--- search ---|
         */
-       test_start = max_bytes + 4096;
+       test_start = max_bytes + sectorsize;
        locked_page = find_lock_page(inode->i_mapping, test_start >>
                                     PAGE_SHIFT);
        if (!locked_page) {
@@ -272,6 +273,16 @@ out:
        return ret;
 }
 
+/**
+ * test_bit_in_byte - Determine whether a bit is set in a byte
+ * @nr: bit number to test
+ * @addr: Address to start counting from
+ */
+static inline int test_bit_in_byte(int nr, const u8 *addr)
+{
+       return 1UL & (addr[nr / BITS_PER_BYTE] >> (nr & (BITS_PER_BYTE - 1)));
+}
+
 static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb,
                             unsigned long len)
 {
@@ -298,25 +309,29 @@ static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb,
                return -EINVAL;
        }
 
-       bitmap_set(bitmap, (PAGE_SIZE - sizeof(long) / 2) * BITS_PER_BYTE,
-                  sizeof(long) * BITS_PER_BYTE);
-       extent_buffer_bitmap_set(eb, PAGE_SIZE - sizeof(long) / 2, 0,
-                                sizeof(long) * BITS_PER_BYTE);
-       if (memcmp_extent_buffer(eb, bitmap, 0, len) != 0) {
-               test_msg("Setting straddling pages failed\n");
-               return -EINVAL;
-       }
+       /* Straddling pages test */
+       if (len > PAGE_SIZE) {
+               bitmap_set(bitmap,
+                       (PAGE_SIZE - sizeof(long) / 2) * BITS_PER_BYTE,
+                       sizeof(long) * BITS_PER_BYTE);
+               extent_buffer_bitmap_set(eb, PAGE_SIZE - sizeof(long) / 2, 0,
+                                       sizeof(long) * BITS_PER_BYTE);
+               if (memcmp_extent_buffer(eb, bitmap, 0, len) != 0) {
+                       test_msg("Setting straddling pages failed\n");
+                       return -EINVAL;
+               }
 
-       bitmap_set(bitmap, 0, len * BITS_PER_BYTE);
-       bitmap_clear(bitmap,
-                    (PAGE_SIZE - sizeof(long) / 2) * BITS_PER_BYTE,
-                    sizeof(long) * BITS_PER_BYTE);
-       extent_buffer_bitmap_set(eb, 0, 0, len * BITS_PER_BYTE);
-       extent_buffer_bitmap_clear(eb, PAGE_SIZE - sizeof(long) / 2, 0,
-                                  sizeof(long) * BITS_PER_BYTE);
-       if (memcmp_extent_buffer(eb, bitmap, 0, len) != 0) {
-               test_msg("Clearing straddling pages failed\n");
-               return -EINVAL;
+               bitmap_set(bitmap, 0, len * BITS_PER_BYTE);
+               bitmap_clear(bitmap,
+                       (PAGE_SIZE - sizeof(long) / 2) * BITS_PER_BYTE,
+                       sizeof(long) * BITS_PER_BYTE);
+               extent_buffer_bitmap_set(eb, 0, 0, len * BITS_PER_BYTE);
+               extent_buffer_bitmap_clear(eb, PAGE_SIZE - sizeof(long) / 2, 0,
+                                       sizeof(long) * BITS_PER_BYTE);
+               if (memcmp_extent_buffer(eb, bitmap, 0, len) != 0) {
+                       test_msg("Clearing straddling pages failed\n");
+                       return -EINVAL;
+               }
        }
 
        /*
@@ -333,7 +348,7 @@ static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb,
        for (i = 0; i < len * BITS_PER_BYTE; i++) {
                int bit, bit1;
 
-               bit = !!test_bit(i, bitmap);
+               bit = !!test_bit_in_byte(i, (u8 *)bitmap);
                bit1 = !!extent_buffer_test_bit(eb, 0, i);
                if (bit1 != bit) {
                        test_msg("Testing bit pattern failed\n");
@@ -351,15 +366,22 @@ static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb,
        return 0;
 }
 
-static int test_eb_bitmaps(void)
+static int test_eb_bitmaps(u32 sectorsize, u32 nodesize)
 {
-       unsigned long len = PAGE_SIZE * 4;
+       unsigned long len;
        unsigned long *bitmap;
        struct extent_buffer *eb;
        int ret;
 
        test_msg("Running extent buffer bitmap tests\n");
 
+       /*
+        * In ppc64, sectorsize can be 64K, thus 4 * 64K will be larger than
+        * BTRFS_MAX_METADATA_BLOCKSIZE.
+        */
+       len = (sectorsize < BTRFS_MAX_METADATA_BLOCKSIZE)
+               ? sectorsize * 4 : sectorsize;
+
        bitmap = kmalloc(len, GFP_KERNEL);
        if (!bitmap) {
                test_msg("Couldn't allocate test bitmap\n");
@@ -379,7 +401,7 @@ static int test_eb_bitmaps(void)
 
        /* Do it over again with an extent buffer which isn't page-aligned. */
        free_extent_buffer(eb);
-       eb = __alloc_dummy_extent_buffer(NULL, PAGE_SIZE / 2, len);
+       eb = __alloc_dummy_extent_buffer(NULL, nodesize / 2, len);
        if (!eb) {
                test_msg("Couldn't allocate test extent buffer\n");
                kfree(bitmap);
@@ -393,17 +415,17 @@ out:
        return ret;
 }
 
-int btrfs_test_extent_io(void)
+int btrfs_test_extent_io(u32 sectorsize, u32 nodesize)
 {
        int ret;
 
        test_msg("Running extent I/O tests\n");
 
-       ret = test_find_delalloc();
+       ret = test_find_delalloc(sectorsize);
        if (ret)
                goto out;
 
-       ret = test_eb_bitmaps();
+       ret = test_eb_bitmaps(sectorsize, nodesize);
 out:
        test_msg("Extent I/O tests finished\n");
        return ret;
index 0eeb8f3..3956bb2 100644 (file)
@@ -22,7 +22,7 @@
 #include "../disk-io.h"
 #include "../free-space-cache.h"
 
-#define BITS_PER_BITMAP                (PAGE_SIZE * 8)
+#define BITS_PER_BITMAP                (PAGE_SIZE * 8UL)
 
 /*
  * This test just does basic sanity checking, making sure we can add an extent
@@ -99,7 +99,8 @@ static int test_extents(struct btrfs_block_group_cache *cache)
        return 0;
 }
 
-static int test_bitmaps(struct btrfs_block_group_cache *cache)
+static int test_bitmaps(struct btrfs_block_group_cache *cache,
+                       u32 sectorsize)
 {
        u64 next_bitmap_offset;
        int ret;
@@ -139,7 +140,7 @@ static int test_bitmaps(struct btrfs_block_group_cache *cache)
         * The first bitmap we have starts at offset 0 so the next one is just
         * at the end of the first bitmap.
         */
-       next_bitmap_offset = (u64)(BITS_PER_BITMAP * 4096);
+       next_bitmap_offset = (u64)(BITS_PER_BITMAP * sectorsize);
 
        /* Test a bit straddling two bitmaps */
        ret = test_add_free_space_entry(cache, next_bitmap_offset - SZ_2M,
@@ -167,9 +168,10 @@ static int test_bitmaps(struct btrfs_block_group_cache *cache)
 }
 
 /* This is the high grade jackassery */
-static int test_bitmaps_and_extents(struct btrfs_block_group_cache *cache)
+static int test_bitmaps_and_extents(struct btrfs_block_group_cache *cache,
+                                   u32 sectorsize)
 {
-       u64 bitmap_offset = (u64)(BITS_PER_BITMAP * 4096);
+       u64 bitmap_offset = (u64)(BITS_PER_BITMAP * sectorsize);
        int ret;
 
        test_msg("Running bitmap and extent tests\n");
@@ -401,7 +403,8 @@ static int check_cache_empty(struct btrfs_block_group_cache *cache)
  * requests.
  */
 static int
-test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache)
+test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache,
+                                      u32 sectorsize)
 {
        int ret;
        u64 offset;
@@ -539,7 +542,7 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache)
         * The goal is to test that the bitmap entry space stealing doesn't
         * steal this space region.
         */
-       ret = btrfs_add_free_space(cache, SZ_128M + SZ_16M, 4096);
+       ret = btrfs_add_free_space(cache, SZ_128M + SZ_16M, sectorsize);
        if (ret) {
                test_msg("Error adding free space: %d\n", ret);
                return ret;
@@ -597,8 +600,8 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache)
                return -ENOENT;
        }
 
-       if (cache->free_space_ctl->free_space != (SZ_1M + 4096)) {
-               test_msg("Cache free space is not 1Mb + 4Kb\n");
+       if (cache->free_space_ctl->free_space != (SZ_1M + sectorsize)) {
+               test_msg("Cache free space is not 1Mb + %u\n", sectorsize);
                return -EINVAL;
        }
 
@@ -611,22 +614,25 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache)
                return -EINVAL;
        }
 
-       /* All that remains is a 4Kb free space region in a bitmap. Confirm. */
+       /*
+        * All that remains is a sectorsize free space region in a bitmap.
+        * Confirm.
+        */
        ret = check_num_extents_and_bitmaps(cache, 1, 1);
        if (ret)
                return ret;
 
-       if (cache->free_space_ctl->free_space != 4096) {
-               test_msg("Cache free space is not 4Kb\n");
+       if (cache->free_space_ctl->free_space != sectorsize) {
+               test_msg("Cache free space is not %u\n", sectorsize);
                return -EINVAL;
        }
 
        offset = btrfs_find_space_for_alloc(cache,
-                                           0, 4096, 0,
+                                           0, sectorsize, 0,
                                            &max_extent_size);
        if (offset != (SZ_128M + SZ_16M)) {
-               test_msg("Failed to allocate 4Kb from space cache, returned offset is: %llu\n",
-                        offset);
+               test_msg("Failed to allocate %u, returned offset : %llu\n",
+                        sectorsize, offset);
                return -EINVAL;
        }
 
@@ -733,7 +739,7 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache)
         * The goal is to test that the bitmap entry space stealing doesn't
         * steal this space region.
         */
-       ret = btrfs_add_free_space(cache, SZ_32M, 8192);
+       ret = btrfs_add_free_space(cache, SZ_32M, 2 * sectorsize);
        if (ret) {
                test_msg("Error adding free space: %d\n", ret);
                return ret;
@@ -757,7 +763,7 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache)
 
        /*
         * Confirm that our extent entry didn't stole all free space from the
-        * bitmap, because of the small 8Kb free space region.
+        * bitmap, because of the small 2 * sectorsize free space region.
         */
        ret = check_num_extents_and_bitmaps(cache, 2, 1);
        if (ret)
@@ -783,8 +789,8 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache)
                return -ENOENT;
        }
 
-       if (cache->free_space_ctl->free_space != (SZ_1M + 8192)) {
-               test_msg("Cache free space is not 1Mb + 8Kb\n");
+       if (cache->free_space_ctl->free_space != (SZ_1M + 2 * sectorsize)) {
+               test_msg("Cache free space is not 1Mb + %u\n", 2 * sectorsize);
                return -EINVAL;
        }
 
@@ -796,21 +802,25 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache)
                return -EINVAL;
        }
 
-       /* All that remains is a 8Kb free space region in a bitmap. Confirm. */
+       /*
+        * All that remains is 2 * sectorsize free space region
+        * in a bitmap. Confirm.
+        */
        ret = check_num_extents_and_bitmaps(cache, 1, 1);
        if (ret)
                return ret;
 
-       if (cache->free_space_ctl->free_space != 8192) {
-               test_msg("Cache free space is not 8Kb\n");
+       if (cache->free_space_ctl->free_space != 2 * sectorsize) {
+               test_msg("Cache free space is not %u\n", 2 * sectorsize);
                return -EINVAL;
        }
 
        offset = btrfs_find_space_for_alloc(cache,
-                                           0, 8192, 0,
+                                           0, 2 * sectorsize, 0,
                                            &max_extent_size);
        if (offset != SZ_32M) {
-               test_msg("Failed to allocate 8Kb from space cache, returned offset is: %llu\n",
+               test_msg("Failed to allocate %u, offset: %llu\n",
+                        2 * sectorsize,
                         offset);
                return -EINVAL;
        }
@@ -825,7 +835,7 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache)
        return 0;
 }
 
-int btrfs_test_free_space_cache(void)
+int btrfs_test_free_space_cache(u32 sectorsize, u32 nodesize)
 {
        struct btrfs_block_group_cache *cache;
        struct btrfs_root *root = NULL;
@@ -833,13 +843,19 @@ int btrfs_test_free_space_cache(void)
 
        test_msg("Running btrfs free space cache tests\n");
 
-       cache = btrfs_alloc_dummy_block_group(1024 * 1024 * 1024);
+       /*
+        * For ppc64 (with 64k page size), bytes per bitmap might be
+        * larger than 1G.  To make bitmap test available in ppc64,
+        * alloc dummy block group whose size cross bitmaps.
+        */
+       cache = btrfs_alloc_dummy_block_group(BITS_PER_BITMAP * sectorsize
+                                       + PAGE_SIZE, sectorsize);
        if (!cache) {
                test_msg("Couldn't run the tests\n");
                return 0;
        }
 
-       root = btrfs_alloc_dummy_root();
+       root = btrfs_alloc_dummy_root(sectorsize, nodesize);
        if (IS_ERR(root)) {
                ret = PTR_ERR(root);
                goto out;
@@ -855,14 +871,14 @@ int btrfs_test_free_space_cache(void)
        ret = test_extents(cache);
        if (ret)
                goto out;
-       ret = test_bitmaps(cache);
+       ret = test_bitmaps(cache, sectorsize);
        if (ret)
                goto out;
-       ret = test_bitmaps_and_extents(cache);
+       ret = test_bitmaps_and_extents(cache, sectorsize);
        if (ret)
                goto out;
 
-       ret = test_steal_space_from_bitmap_to_extent(cache);
+       ret = test_steal_space_from_bitmap_to_extent(cache, sectorsize);
 out:
        btrfs_free_dummy_block_group(cache);
        btrfs_free_dummy_root(root);
index 7cea446..aac5070 100644 (file)
@@ -16,6 +16,7 @@
  * Boston, MA 021110-1307, USA.
  */
 
+#include <linux/types.h>
 #include "btrfs-tests.h"
 #include "../ctree.h"
 #include "../disk-io.h"
@@ -30,7 +31,7 @@ struct free_space_extent {
  * The test cases align their operations to this in order to hit some of the
  * edge cases in the bitmap code.
  */
-#define BITMAP_RANGE (BTRFS_FREE_SPACE_BITMAP_BITS * 4096)
+#define BITMAP_RANGE (BTRFS_FREE_SPACE_BITMAP_BITS * PAGE_SIZE)
 
 static int __check_free_space_extents(struct btrfs_trans_handle *trans,
                                      struct btrfs_fs_info *fs_info,
@@ -439,7 +440,8 @@ typedef int (*test_func_t)(struct btrfs_trans_handle *,
                           struct btrfs_block_group_cache *,
                           struct btrfs_path *);
 
-static int run_test(test_func_t test_func, int bitmaps)
+static int run_test(test_func_t test_func, int bitmaps,
+               u32 sectorsize, u32 nodesize)
 {
        struct btrfs_root *root = NULL;
        struct btrfs_block_group_cache *cache = NULL;
@@ -447,7 +449,7 @@ static int run_test(test_func_t test_func, int bitmaps)
        struct btrfs_path *path = NULL;
        int ret;
 
-       root = btrfs_alloc_dummy_root();
+       root = btrfs_alloc_dummy_root(sectorsize, nodesize);
        if (IS_ERR(root)) {
                test_msg("Couldn't allocate dummy root\n");
                ret = PTR_ERR(root);
@@ -466,7 +468,8 @@ static int run_test(test_func_t test_func, int bitmaps)
        root->fs_info->free_space_root = root;
        root->fs_info->tree_root = root;
 
-       root->node = alloc_test_extent_buffer(root->fs_info, 4096);
+       root->node = alloc_test_extent_buffer(root->fs_info,
+               nodesize, nodesize);
        if (!root->node) {
                test_msg("Couldn't allocate dummy buffer\n");
                ret = -ENOMEM;
@@ -474,9 +477,9 @@ static int run_test(test_func_t test_func, int bitmaps)
        }
        btrfs_set_header_level(root->node, 0);
        btrfs_set_header_nritems(root->node, 0);
-       root->alloc_bytenr += 8192;
+       root->alloc_bytenr += 2 * nodesize;
 
-       cache = btrfs_alloc_dummy_block_group(8 * BITMAP_RANGE);
+       cache = btrfs_alloc_dummy_block_group(8 * BITMAP_RANGE, sectorsize);
        if (!cache) {
                test_msg("Couldn't allocate dummy block group cache\n");
                ret = -ENOMEM;
@@ -534,17 +537,18 @@ out:
        return ret;
 }
 
-static int run_test_both_formats(test_func_t test_func)
+static int run_test_both_formats(test_func_t test_func,
+       u32 sectorsize, u32 nodesize)
 {
        int ret;
 
-       ret = run_test(test_func, 0);
+       ret = run_test(test_func, 0, sectorsize, nodesize);
        if (ret)
                return ret;
-       return run_test(test_func, 1);
+       return run_test(test_func, 1, sectorsize, nodesize);
 }
 
-int btrfs_test_free_space_tree(void)
+int btrfs_test_free_space_tree(u32 sectorsize, u32 nodesize)
 {
        test_func_t tests[] = {
                test_empty_block_group,
@@ -561,9 +565,11 @@ int btrfs_test_free_space_tree(void)
 
        test_msg("Running free space tree tests\n");
        for (i = 0; i < ARRAY_SIZE(tests); i++) {
-               int ret = run_test_both_formats(tests[i]);
+               int ret = run_test_both_formats(tests[i], sectorsize,
+                       nodesize);
                if (ret) {
-                       test_msg("%pf failed\n", tests[i]);
+                       test_msg("%pf : sectorsize %u failed\n",
+                               tests[i], sectorsize);
                        return ret;
                }
        }
index 8a25fe8..29648c0 100644 (file)
@@ -16,6 +16,7 @@
  * Boston, MA 021110-1307, USA.
  */
 
+#include <linux/types.h>
 #include "btrfs-tests.h"
 #include "../ctree.h"
 #include "../btrfs_inode.h"
@@ -86,19 +87,19 @@ static void insert_inode_item_key(struct btrfs_root *root)
  * diagram of how the extents will look though this may not be possible we still
  * want to make sure everything acts normally (the last number is not inclusive)
  *
- * [0 - 5][5 -  6][6 - 10][10 - 4096][  4096 - 8192 ][8192 - 12288]
- * [hole ][inline][ hole ][ regular ][regular1 split][    hole    ]
+ * [0 - 5][5 -  6][     6 - 4096     ][ 4096 - 4100][4100 - 8195][8195 - 12291]
+ * [hole ][inline][hole but no extent][  hole   ][   regular ][regular1 split]
  *
- * [ 12288 - 20480][20480 - 24576][  24576 - 28672  ][28672 - 36864][36864 - 45056]
- * [regular1 split][   prealloc1 ][prealloc1 written][   prealloc1 ][ compressed  ]
+ * [12291 - 16387][16387 - 24579][24579 - 28675][ 28675 - 32771][32771 - 36867 ]
+ * [    hole    ][regular1 split][   prealloc ][   prealloc1  ][prealloc1 written]
  *
- * [45056 - 49152][49152-53248][53248-61440][61440-65536][     65536+81920   ]
- * [ compressed1 ][  regular  ][compressed1][  regular  ][ hole but no extent]
+ * [36867 - 45059][45059 - 53251][53251 - 57347][57347 - 61443][61443- 69635]
+ * [  prealloc1  ][ compressed  ][ compressed1 ][    regular  ][ compressed1]
  *
- * [81920-86016]
- * [  regular  ]
+ * [69635-73731][   73731 - 86019   ][86019-90115]
+ * [  regular  ][ hole but no extent][  regular  ]
  */
-static void setup_file_extents(struct btrfs_root *root)
+static void setup_file_extents(struct btrfs_root *root, u32 sectorsize)
 {
        int slot = 0;
        u64 disk_bytenr = SZ_1M;
@@ -119,7 +120,7 @@ static void setup_file_extents(struct btrfs_root *root)
        insert_extent(root, offset, 1, 1, 0, 0, 0, BTRFS_FILE_EXTENT_INLINE, 0,
                      slot);
        slot++;
-       offset = 4096;
+       offset = sectorsize;
 
        /* Now another hole */
        insert_extent(root, offset, 4, 4, 0, 0, 0, BTRFS_FILE_EXTENT_REG, 0,
@@ -128,99 +129,106 @@ static void setup_file_extents(struct btrfs_root *root)
        offset += 4;
 
        /* Now for a regular extent */
-       insert_extent(root, offset, 4095, 4095, 0, disk_bytenr, 4096,
-                     BTRFS_FILE_EXTENT_REG, 0, slot);
+       insert_extent(root, offset, sectorsize - 1, sectorsize - 1, 0,
+                     disk_bytenr, sectorsize, BTRFS_FILE_EXTENT_REG, 0, slot);
        slot++;
-       disk_bytenr += 4096;
-       offset += 4095;
+       disk_bytenr += sectorsize;
+       offset += sectorsize - 1;
 
        /*
         * Now for 3 extents that were split from a hole punch so we test
         * offsets properly.
         */
-       insert_extent(root, offset, 4096, 16384, 0, disk_bytenr, 16384,
-                     BTRFS_FILE_EXTENT_REG, 0, slot);
+       insert_extent(root, offset, sectorsize, 4 * sectorsize, 0, disk_bytenr,
+                     4 * sectorsize, BTRFS_FILE_EXTENT_REG, 0, slot);
        slot++;
-       offset += 4096;
-       insert_extent(root, offset, 4096, 4096, 0, 0, 0, BTRFS_FILE_EXTENT_REG,
-                     0, slot);
+       offset += sectorsize;
+       insert_extent(root, offset, sectorsize, sectorsize, 0, 0, 0,
+                     BTRFS_FILE_EXTENT_REG, 0, slot);
        slot++;
-       offset += 4096;
-       insert_extent(root, offset, 8192, 16384, 8192, disk_bytenr, 16384,
+       offset += sectorsize;
+       insert_extent(root, offset, 2 * sectorsize, 4 * sectorsize,
+                     2 * sectorsize, disk_bytenr, 4 * sectorsize,
                      BTRFS_FILE_EXTENT_REG, 0, slot);
        slot++;
-       offset += 8192;
-       disk_bytenr += 16384;
+       offset += 2 * sectorsize;
+       disk_bytenr += 4 * sectorsize;
 
        /* Now for a unwritten prealloc extent */
-       insert_extent(root, offset, 4096, 4096, 0, disk_bytenr, 4096,
-                     BTRFS_FILE_EXTENT_PREALLOC, 0, slot);
+       insert_extent(root, offset, sectorsize, sectorsize, 0, disk_bytenr,
+               sectorsize, BTRFS_FILE_EXTENT_PREALLOC, 0, slot);
        slot++;
-       offset += 4096;
+       offset += sectorsize;
 
        /*
         * We want to jack up disk_bytenr a little more so the em stuff doesn't
         * merge our records.
         */
-       disk_bytenr += 8192;
+       disk_bytenr += 2 * sectorsize;
 
        /*
         * Now for a partially written prealloc extent, basically the same as
         * the hole punch example above.  Ram_bytes never changes when you mark
         * extents written btw.
         */
-       insert_extent(root, offset, 4096, 16384, 0, disk_bytenr, 16384,
-                     BTRFS_FILE_EXTENT_PREALLOC, 0, slot);
+       insert_extent(root, offset, sectorsize, 4 * sectorsize, 0, disk_bytenr,
+                     4 * sectorsize, BTRFS_FILE_EXTENT_PREALLOC, 0, slot);
        slot++;
-       offset += 4096;
-       insert_extent(root, offset, 4096, 16384, 4096, disk_bytenr, 16384,
-                     BTRFS_FILE_EXTENT_REG, 0, slot);
+       offset += sectorsize;
+       insert_extent(root, offset, sectorsize, 4 * sectorsize, sectorsize,
+                     disk_bytenr, 4 * sectorsize, BTRFS_FILE_EXTENT_REG, 0,
+                     slot);
        slot++;
-       offset += 4096;
-       insert_extent(root, offset, 8192, 16384, 8192, disk_bytenr, 16384,
+       offset += sectorsize;
+       insert_extent(root, offset, 2 * sectorsize, 4 * sectorsize,
+                     2 * sectorsize, disk_bytenr, 4 * sectorsize,
                      BTRFS_FILE_EXTENT_PREALLOC, 0, slot);
        slot++;
-       offset += 8192;
-       disk_bytenr += 16384;
+       offset += 2 * sectorsize;
+       disk_bytenr += 4 * sectorsize;
 
        /* Now a normal compressed extent */
-       insert_extent(root, offset, 8192, 8192, 0, disk_bytenr, 4096,
-                     BTRFS_FILE_EXTENT_REG, BTRFS_COMPRESS_ZLIB, slot);
+       insert_extent(root, offset, 2 * sectorsize, 2 * sectorsize, 0,
+                     disk_bytenr, sectorsize, BTRFS_FILE_EXTENT_REG,
+                     BTRFS_COMPRESS_ZLIB, slot);
        slot++;
-       offset += 8192;
+       offset += 2 * sectorsize;
        /* No merges */
-       disk_bytenr += 8192;
+       disk_bytenr += 2 * sectorsize;
 
        /* Now a split compressed extent */
-       insert_extent(root, offset, 4096, 16384, 0, disk_bytenr, 4096,
-                     BTRFS_FILE_EXTENT_REG, BTRFS_COMPRESS_ZLIB, slot);
+       insert_extent(root, offset, sectorsize, 4 * sectorsize, 0, disk_bytenr,
+                     sectorsize, BTRFS_FILE_EXTENT_REG,
+                     BTRFS_COMPRESS_ZLIB, slot);
        slot++;
-       offset += 4096;
-       insert_extent(root, offset, 4096, 4096, 0, disk_bytenr + 4096, 4096,
+       offset += sectorsize;
+       insert_extent(root, offset, sectorsize, sectorsize, 0,
+                     disk_bytenr + sectorsize, sectorsize,
                      BTRFS_FILE_EXTENT_REG, 0, slot);
        slot++;
-       offset += 4096;
-       insert_extent(root, offset, 8192, 16384, 8192, disk_bytenr, 4096,
+       offset += sectorsize;
+       insert_extent(root, offset, 2 * sectorsize, 4 * sectorsize,
+                     2 * sectorsize, disk_bytenr, sectorsize,
                      BTRFS_FILE_EXTENT_REG, BTRFS_COMPRESS_ZLIB, slot);
        slot++;
-       offset += 8192;
-       disk_bytenr += 8192;
+       offset += 2 * sectorsize;
+       disk_bytenr += 2 * sectorsize;
 
        /* Now extents that have a hole but no hole extent */
-       insert_extent(root, offset, 4096, 4096, 0, disk_bytenr, 4096,
-                     BTRFS_FILE_EXTENT_REG, 0, slot);
+       insert_extent(root, offset, sectorsize, sectorsize, 0, disk_bytenr,
+                     sectorsize, BTRFS_FILE_EXTENT_REG, 0, slot);
        slot++;
-       offset += 16384;
-       disk_bytenr += 4096;
-       insert_extent(root, offset, 4096, 4096, 0, disk_bytenr, 4096,
-                     BTRFS_FILE_EXTENT_REG, 0, slot);
+       offset += 4 * sectorsize;
+       disk_bytenr += sectorsize;
+       insert_extent(root, offset, sectorsize, sectorsize, 0, disk_bytenr,
+                     sectorsize, BTRFS_FILE_EXTENT_REG, 0, slot);
 }
 
 static unsigned long prealloc_only = 0;
 static unsigned long compressed_only = 0;
 static unsigned long vacancy_only = 0;
 
-static noinline int test_btrfs_get_extent(void)
+static noinline int test_btrfs_get_extent(u32 sectorsize, u32 nodesize)
 {
        struct inode *inode = NULL;
        struct btrfs_root *root = NULL;
@@ -240,7 +248,7 @@ static noinline int test_btrfs_get_extent(void)
        BTRFS_I(inode)->location.objectid = BTRFS_FIRST_FREE_OBJECTID;
        BTRFS_I(inode)->location.offset = 0;
 
-       root = btrfs_alloc_dummy_root();
+       root = btrfs_alloc_dummy_root(sectorsize, nodesize);
        if (IS_ERR(root)) {
                test_msg("Couldn't allocate root\n");
                goto out;
@@ -256,7 +264,7 @@ static noinline int test_btrfs_get_extent(void)
                goto out;
        }
 
-       root->node = alloc_dummy_extent_buffer(NULL, 4096);
+       root->node = alloc_dummy_extent_buffer(NULL, nodesize, nodesize);
        if (!root->node) {
                test_msg("Couldn't allocate dummy buffer\n");
                goto out;
@@ -273,7 +281,7 @@ static noinline int test_btrfs_get_extent(void)
 
        /* First with no extents */
        BTRFS_I(inode)->root = root;
-       em = btrfs_get_extent(inode, NULL, 0, 0, 4096, 0);
+       em = btrfs_get_extent(inode, NULL, 0, 0, sectorsize, 0);
        if (IS_ERR(em)) {
                em = NULL;
                test_msg("Got an error when we shouldn't have\n");
@@ -295,7 +303,7 @@ static noinline int test_btrfs_get_extent(void)
         * setup_file_extents, so if you change anything there you need to
         * update the comment and update the expected values below.
         */
-       setup_file_extents(root);
+       setup_file_extents(root, sectorsize);
 
        em = btrfs_get_extent(inode, NULL, 0, 0, (u64)-1, 0);
        if (IS_ERR(em)) {
@@ -318,7 +326,7 @@ static noinline int test_btrfs_get_extent(void)
        offset = em->start + em->len;
        free_extent_map(em);
 
-       em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0);
+       em = btrfs_get_extent(inode, NULL, 0, offset, sectorsize, 0);
        if (IS_ERR(em)) {
                test_msg("Got an error when we shouldn't have\n");
                goto out;
@@ -327,7 +335,8 @@ static noinline int test_btrfs_get_extent(void)
                test_msg("Expected an inline, got %llu\n", em->block_start);
                goto out;
        }
-       if (em->start != offset || em->len != 4091) {
+
+       if (em->start != offset || em->len != (sectorsize - 5)) {
                test_msg("Unexpected extent wanted start %llu len 1, got start "
                         "%llu len %llu\n", offset, em->start, em->len);
                goto out;
@@ -344,7 +353,7 @@ static noinline int test_btrfs_get_extent(void)
        offset = em->start + em->len;
        free_extent_map(em);
 
-       em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0);
+       em = btrfs_get_extent(inode, NULL, 0, offset, sectorsize, 0);
        if (IS_ERR(em)) {
                test_msg("Got an error when we shouldn't have\n");
                goto out;
@@ -366,7 +375,7 @@ static noinline int test_btrfs_get_extent(void)
        free_extent_map(em);
 
        /* Regular extent */
-       em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0);
+       em = btrfs_get_extent(inode, NULL, 0, offset, sectorsize, 0);
        if (IS_ERR(em)) {
                test_msg("Got an error when we shouldn't have\n");
                goto out;
@@ -375,7 +384,7 @@ static noinline int test_btrfs_get_extent(void)
                test_msg("Expected a real extent, got %llu\n", em->block_start);
                goto out;
        }
-       if (em->start != offset || em->len != 4095) {
+       if (em->start != offset || em->len != sectorsize - 1) {
                test_msg("Unexpected extent wanted start %llu len 4095, got "
                         "start %llu len %llu\n", offset, em->start, em->len);
                goto out;
@@ -393,7 +402,7 @@ static noinline int test_btrfs_get_extent(void)
        free_extent_map(em);
 
        /* The next 3 are split extents */
-       em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0);
+       em = btrfs_get_extent(inode, NULL, 0, offset, sectorsize, 0);
        if (IS_ERR(em)) {
                test_msg("Got an error when we shouldn't have\n");
                goto out;
@@ -402,9 +411,10 @@ static noinline int test_btrfs_get_extent(void)
                test_msg("Expected a real extent, got %llu\n", em->block_start);
                goto out;
        }
-       if (em->start != offset || em->len != 4096) {
-               test_msg("Unexpected extent wanted start %llu len 4096, got "
-                        "start %llu len %llu\n", offset, em->start, em->len);
+       if (em->start != offset || em->len != sectorsize) {
+               test_msg("Unexpected extent start %llu len %u, "
+                       "got start %llu len %llu\n",
+                       offset, sectorsize, em->start, em->len);
                goto out;
        }
        if (em->flags != 0) {
@@ -421,7 +431,7 @@ static noinline int test_btrfs_get_extent(void)
        offset = em->start + em->len;
        free_extent_map(em);
 
-       em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0);
+       em = btrfs_get_extent(inode, NULL, 0, offset, sectorsize, 0);
        if (IS_ERR(em)) {
                test_msg("Got an error when we shouldn't have\n");
                goto out;
@@ -430,9 +440,10 @@ static noinline int test_btrfs_get_extent(void)
                test_msg("Expected a hole, got %llu\n", em->block_start);
                goto out;
        }
-       if (em->start != offset || em->len != 4096) {
-               test_msg("Unexpected extent wanted start %llu len 4096, got "
-                        "start %llu len %llu\n", offset, em->start, em->len);
+       if (em->start != offset || em->len != sectorsize) {
+               test_msg("Unexpected extent wanted start %llu len %u, "
+                       "got start %llu len %llu\n",
+                       offset, sectorsize, em->start, em->len);
                goto out;
        }
        if (em->flags != 0) {
@@ -442,7 +453,7 @@ static noinline int test_btrfs_get_extent(void)
        offset = em->start + em->len;
        free_extent_map(em);
 
-       em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0);
+       em = btrfs_get_extent(inode, NULL, 0, offset, sectorsize, 0);
        if (IS_ERR(em)) {
                test_msg("Got an error when we shouldn't have\n");
                goto out;
@@ -451,9 +462,10 @@ static noinline int test_btrfs_get_extent(void)
                test_msg("Expected a real extent, got %llu\n", em->block_start);
                goto out;
        }
-       if (em->start != offset || em->len != 8192) {
-               test_msg("Unexpected extent wanted start %llu len 8192, got "
-                        "start %llu len %llu\n", offset, em->start, em->len);
+       if (em->start != offset || em->len != 2 * sectorsize) {
+               test_msg("Unexpected extent wanted start %llu len %u, "
+                       "got start %llu len %llu\n",
+                       offset, 2 * sectorsize, em->start, em->len);
                goto out;
        }
        if (em->flags != 0) {
@@ -475,7 +487,7 @@ static noinline int test_btrfs_get_extent(void)
        free_extent_map(em);
 
        /* Prealloc extent */
-       em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0);
+       em = btrfs_get_extent(inode, NULL, 0, offset, sectorsize, 0);
        if (IS_ERR(em)) {
                test_msg("Got an error when we shouldn't have\n");
                goto out;
@@ -484,9 +496,10 @@ static noinline int test_btrfs_get_extent(void)
                test_msg("Expected a real extent, got %llu\n", em->block_start);
                goto out;
        }
-       if (em->start != offset || em->len != 4096) {
-               test_msg("Unexpected extent wanted start %llu len 4096, got "
-                        "start %llu len %llu\n", offset, em->start, em->len);
+       if (em->start != offset || em->len != sectorsize) {
+               test_msg("Unexpected extent wanted start %llu len %u, "
+                       "got start %llu len %llu\n",
+                       offset, sectorsize, em->start, em->len);
                goto out;
        }
        if (em->flags != prealloc_only) {
@@ -503,7 +516,7 @@ static noinline int test_btrfs_get_extent(void)
        free_extent_map(em);
 
        /* The next 3 are a half written prealloc extent */
-       em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0);
+       em = btrfs_get_extent(inode, NULL, 0, offset, sectorsize, 0);
        if (IS_ERR(em)) {
                test_msg("Got an error when we shouldn't have\n");
                goto out;
@@ -512,9 +525,10 @@ static noinline int test_btrfs_get_extent(void)
                test_msg("Expected a real extent, got %llu\n", em->block_start);
                goto out;
        }
-       if (em->start != offset || em->len != 4096) {
-               test_msg("Unexpected extent wanted start %llu len 4096, got "
-                        "start %llu len %llu\n", offset, em->start, em->len);
+       if (em->start != offset || em->len != sectorsize) {
+               test_msg("Unexpected extent wanted start %llu len %u, "
+                       "got start %llu len %llu\n",
+                       offset, sectorsize, em->start, em->len);
                goto out;
        }
        if (em->flags != prealloc_only) {
@@ -532,7 +546,7 @@ static noinline int test_btrfs_get_extent(void)
        offset = em->start + em->len;
        free_extent_map(em);
 
-       em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0);
+       em = btrfs_get_extent(inode, NULL, 0, offset, sectorsize, 0);
        if (IS_ERR(em)) {
                test_msg("Got an error when we shouldn't have\n");
                goto out;
@@ -541,9 +555,10 @@ static noinline int test_btrfs_get_extent(void)
                test_msg("Expected a real extent, got %llu\n", em->block_start);
                goto out;
        }
-       if (em->start != offset || em->len != 4096) {
-               test_msg("Unexpected extent wanted start %llu len 4096, got "
-                        "start %llu len %llu\n", offset, em->start, em->len);
+       if (em->start != offset || em->len != sectorsize) {
+               test_msg("Unexpected extent wanted start %llu len %u, "
+                       "got start %llu len %llu\n",
+                       offset, sectorsize, em->start, em->len);
                goto out;
        }
        if (em->flags != 0) {
@@ -564,7 +579,7 @@ static noinline int test_btrfs_get_extent(void)
        offset = em->start + em->len;
        free_extent_map(em);
 
-       em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0);
+       em = btrfs_get_extent(inode, NULL, 0, offset, sectorsize, 0);
        if (IS_ERR(em)) {
                test_msg("Got an error when we shouldn't have\n");
                goto out;
@@ -573,9 +588,10 @@ static noinline int test_btrfs_get_extent(void)
                test_msg("Expected a real extent, got %llu\n", em->block_start);
                goto out;
        }
-       if (em->start != offset || em->len != 8192) {
-               test_msg("Unexpected extent wanted start %llu len 8192, got "
-                        "start %llu len %llu\n", offset, em->start, em->len);
+       if (em->start != offset || em->len != 2 * sectorsize) {
+               test_msg("Unexpected extent wanted start %llu len %u, "
+                       "got start %llu len %llu\n",
+                       offset, 2 * sectorsize, em->start, em->len);
                goto out;
        }
        if (em->flags != prealloc_only) {
@@ -598,7 +614,7 @@ static noinline int test_btrfs_get_extent(void)
        free_extent_map(em);
 
        /* Now for the compressed extent */
-       em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0);
+       em = btrfs_get_extent(inode, NULL, 0, offset, sectorsize, 0);
        if (IS_ERR(em)) {
                test_msg("Got an error when we shouldn't have\n");
                goto out;
@@ -607,9 +623,10 @@ static noinline int test_btrfs_get_extent(void)
                test_msg("Expected a real extent, got %llu\n", em->block_start);
                goto out;
        }
-       if (em->start != offset || em->len != 8192) {
-               test_msg("Unexpected extent wanted start %llu len 8192, got "
-                        "start %llu len %llu\n", offset, em->start, em->len);
+       if (em->start != offset || em->len != 2 * sectorsize) {
+               test_msg("Unexpected extent wanted start %llu len %u,"
+                       "got start %llu len %llu\n",
+                       offset, 2 * sectorsize, em->start, em->len);
                goto out;
        }
        if (em->flags != compressed_only) {
@@ -631,7 +648,7 @@ static noinline int test_btrfs_get_extent(void)
        free_extent_map(em);
 
        /* Split compressed extent */
-       em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0);
+       em = btrfs_get_extent(inode, NULL, 0, offset, sectorsize, 0);
        if (IS_ERR(em)) {
                test_msg("Got an error when we shouldn't have\n");
                goto out;
@@ -640,9 +657,10 @@ static noinline int test_btrfs_get_extent(void)
                test_msg("Expected a real extent, got %llu\n", em->block_start);
                goto out;
        }
-       if (em->start != offset || em->len != 4096) {
-               test_msg("Unexpected extent wanted start %llu len 4096, got "
-                        "start %llu len %llu\n", offset, em->start, em->len);
+       if (em->start != offset || em->len != sectorsize) {
+               test_msg("Unexpected extent wanted start %llu len %u,"
+                       "got start %llu len %llu\n",
+                       offset, sectorsize, em->start, em->len);
                goto out;
        }
        if (em->flags != compressed_only) {
@@ -665,7 +683,7 @@ static noinline int test_btrfs_get_extent(void)
        offset = em->start + em->len;
        free_extent_map(em);
 
-       em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0);
+       em = btrfs_get_extent(inode, NULL, 0, offset, sectorsize, 0);
        if (IS_ERR(em)) {
                test_msg("Got an error when we shouldn't have\n");
                goto out;
@@ -674,9 +692,10 @@ static noinline int test_btrfs_get_extent(void)
                test_msg("Expected a real extent, got %llu\n", em->block_start);
                goto out;
        }
-       if (em->start != offset || em->len != 4096) {
-               test_msg("Unexpected extent wanted start %llu len 4096, got "
-                        "start %llu len %llu\n", offset, em->start, em->len);
+       if (em->start != offset || em->len != sectorsize) {
+               test_msg("Unexpected extent wanted start %llu len %u, "
+                       "got start %llu len %llu\n",
+                       offset, sectorsize, em->start, em->len);
                goto out;
        }
        if (em->flags != 0) {
@@ -691,7 +710,7 @@ static noinline int test_btrfs_get_extent(void)
        offset = em->start + em->len;
        free_extent_map(em);
 
-       em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0);
+       em = btrfs_get_extent(inode, NULL, 0, offset, sectorsize, 0);
        if (IS_ERR(em)) {
                test_msg("Got an error when we shouldn't have\n");
                goto out;
@@ -701,9 +720,10 @@ static noinline int test_btrfs_get_extent(void)
                         disk_bytenr, em->block_start);
                goto out;
        }
-       if (em->start != offset || em->len != 8192) {
-               test_msg("Unexpected extent wanted start %llu len 8192, got "
-                        "start %llu len %llu\n", offset, em->start, em->len);
+       if (em->start != offset || em->len != 2 * sectorsize) {
+               test_msg("Unexpected extent wanted start %llu len %u, "
+                       "got start %llu len %llu\n",
+                       offset, 2 * sectorsize, em->start, em->len);
                goto out;
        }
        if (em->flags != compressed_only) {
@@ -725,7 +745,7 @@ static noinline int test_btrfs_get_extent(void)
        free_extent_map(em);
 
        /* A hole between regular extents but no hole extent */
-       em = btrfs_get_extent(inode, NULL, 0, offset + 6, 4096, 0);
+       em = btrfs_get_extent(inode, NULL, 0, offset + 6, sectorsize, 0);
        if (IS_ERR(em)) {
                test_msg("Got an error when we shouldn't have\n");
                goto out;
@@ -734,9 +754,10 @@ static noinline int test_btrfs_get_extent(void)
                test_msg("Expected a real extent, got %llu\n", em->block_start);
                goto out;
        }
-       if (em->start != offset || em->len != 4096) {
-               test_msg("Unexpected extent wanted start %llu len 4096, got "
-                        "start %llu len %llu\n", offset, em->start, em->len);
+       if (em->start != offset || em->len != sectorsize) {
+               test_msg("Unexpected extent wanted start %llu len %u, "
+                       "got start %llu len %llu\n",
+                       offset, sectorsize, em->start, em->len);
                goto out;
        }
        if (em->flags != 0) {
@@ -765,9 +786,10 @@ static noinline int test_btrfs_get_extent(void)
         * length of the actual hole, if this changes we'll have to change this
         * test.
         */
-       if (em->start != offset || em->len != 12288) {
-               test_msg("Unexpected extent wanted start %llu len 12288, got "
-                        "start %llu len %llu\n", offset, em->start, em->len);
+       if (em->start != offset || em->len != 3 * sectorsize) {
+               test_msg("Unexpected extent wanted start %llu len %u, "
+                       "got start %llu len %llu\n",
+                       offset, 3 * sectorsize, em->start, em->len);
                goto out;
        }
        if (em->flags != vacancy_only) {
@@ -783,7 +805,7 @@ static noinline int test_btrfs_get_extent(void)
        offset = em->start + em->len;
        free_extent_map(em);
 
-       em = btrfs_get_extent(inode, NULL, 0, offset, 4096, 0);
+       em = btrfs_get_extent(inode, NULL, 0, offset, sectorsize, 0);
        if (IS_ERR(em)) {
                test_msg("Got an error when we shouldn't have\n");
                goto out;
@@ -792,9 +814,10 @@ static noinline int test_btrfs_get_extent(void)
                test_msg("Expected a real extent, got %llu\n", em->block_start);
                goto out;
        }
-       if (em->start != offset || em->len != 4096) {
-               test_msg("Unexpected extent wanted start %llu len 4096, got "
-                        "start %llu len %llu\n", offset, em->start, em->len);
+       if (em->start != offset || em->len != sectorsize) {
+               test_msg("Unexpected extent wanted start %llu len %u,"
+                       "got start %llu len %llu\n",
+                       offset, sectorsize, em->start, em->len);
                goto out;
        }
        if (em->flags != 0) {
@@ -815,7 +838,7 @@ out:
        return ret;
 }
 
-static int test_hole_first(void)
+static int test_hole_first(u32 sectorsize, u32 nodesize)
 {
        struct inode *inode = NULL;
        struct btrfs_root *root = NULL;
@@ -832,7 +855,7 @@ static int test_hole_first(void)
        BTRFS_I(inode)->location.objectid = BTRFS_FIRST_FREE_OBJECTID;
        BTRFS_I(inode)->location.offset = 0;
 
-       root = btrfs_alloc_dummy_root();
+       root = btrfs_alloc_dummy_root(sectorsize, nodesize);
        if (IS_ERR(root)) {
                test_msg("Couldn't allocate root\n");
                goto out;
@@ -844,7 +867,7 @@ static int test_hole_first(void)
                goto out;
        }
 
-       root->node = alloc_dummy_extent_buffer(NULL, 4096);
+       root->node = alloc_dummy_extent_buffer(NULL, nodesize, nodesize);
        if (!root->node) {
                test_msg("Couldn't allocate dummy buffer\n");
                goto out;
@@ -861,9 +884,9 @@ static int test_hole_first(void)
         * btrfs_get_extent.
         */
        insert_inode_item_key(root);
-       insert_extent(root, 4096, 4096, 4096, 0, 4096, 4096,
-                     BTRFS_FILE_EXTENT_REG, 0, 1);
-       em = btrfs_get_extent(inode, NULL, 0, 0, 8192, 0);
+       insert_extent(root, sectorsize, sectorsize, sectorsize, 0, sectorsize,
+                     sectorsize, BTRFS_FILE_EXTENT_REG, 0, 1);
+       em = btrfs_get_extent(inode, NULL, 0, 0, 2 * sectorsize, 0);
        if (IS_ERR(em)) {
                test_msg("Got an error when we shouldn't have\n");
                goto out;
@@ -872,9 +895,10 @@ static int test_hole_first(void)
                test_msg("Expected a hole, got %llu\n", em->block_start);
                goto out;
        }
-       if (em->start != 0 || em->len != 4096) {
-               test_msg("Unexpected extent wanted start 0 len 4096, got start "
-                        "%llu len %llu\n", em->start, em->len);
+       if (em->start != 0 || em->len != sectorsize) {
+               test_msg("Unexpected extent wanted start 0 len %u, "
+                       "got start %llu len %llu\n",
+                       sectorsize, em->start, em->len);
                goto out;
        }
        if (em->flags != vacancy_only) {
@@ -884,18 +908,19 @@ static int test_hole_first(void)
        }
        free_extent_map(em);
 
-       em = btrfs_get_extent(inode, NULL, 0, 4096, 8192, 0);
+       em = btrfs_get_extent(inode, NULL, 0, sectorsize, 2 * sectorsize, 0);
        if (IS_ERR(em)) {
                test_msg("Got an error when we shouldn't have\n");
                goto out;
        }
-       if (em->block_start != 4096) {
+       if (em->block_start != sectorsize) {
                test_msg("Expected a real extent, got %llu\n", em->block_start);
                goto out;
        }
-       if (em->start != 4096 || em->len != 4096) {
-               test_msg("Unexpected extent wanted start 4096 len 4096, got "
-                        "start %llu len %llu\n", em->start, em->len);
+       if (em->start != sectorsize || em->len != sectorsize) {
+               test_msg("Unexpected extent wanted start %u len %u, "
+                       "got start %llu len %llu\n",
+                       sectorsize, sectorsize, em->start, em->len);
                goto out;
        }
        if (em->flags != 0) {
@@ -912,7 +937,7 @@ out:
        return ret;
 }
 
-static int test_extent_accounting(void)
+static int test_extent_accounting(u32 sectorsize, u32 nodesize)
 {
        struct inode *inode = NULL;
        struct btrfs_root *root = NULL;
@@ -924,7 +949,7 @@ static int test_extent_accounting(void)
                return ret;
        }
 
-       root = btrfs_alloc_dummy_root();
+       root = btrfs_alloc_dummy_root(sectorsize, nodesize);
        if (IS_ERR(root)) {
                test_msg("Couldn't allocate root\n");
                goto out;
@@ -954,10 +979,11 @@ static int test_extent_accounting(void)
                goto out;
        }
 
-       /* [BTRFS_MAX_EXTENT_SIZE][4k] */
+       /* [BTRFS_MAX_EXTENT_SIZE][sectorsize] */
        BTRFS_I(inode)->outstanding_extents++;
        ret = btrfs_set_extent_delalloc(inode, BTRFS_MAX_EXTENT_SIZE,
-                                       BTRFS_MAX_EXTENT_SIZE + 4095, NULL);
+                                       BTRFS_MAX_EXTENT_SIZE + sectorsize - 1,
+                                       NULL);
        if (ret) {
                test_msg("btrfs_set_extent_delalloc returned %d\n", ret);
                goto out;
@@ -969,10 +995,10 @@ static int test_extent_accounting(void)
                goto out;
        }
 
-       /* [BTRFS_MAX_EXTENT_SIZE/2][4K HOLE][the rest] */
+       /* [BTRFS_MAX_EXTENT_SIZE/2][sectorsize HOLE][the rest] */
        ret = clear_extent_bit(&BTRFS_I(inode)->io_tree,
                               BTRFS_MAX_EXTENT_SIZE >> 1,
-                              (BTRFS_MAX_EXTENT_SIZE >> 1) + 4095,
+                              (BTRFS_MAX_EXTENT_SIZE >> 1) + sectorsize - 1,
                               EXTENT_DELALLOC | EXTENT_DIRTY |
                               EXTENT_UPTODATE | EXTENT_DO_ACCOUNTING, 0, 0,
                               NULL, GFP_KERNEL);
@@ -987,10 +1013,11 @@ static int test_extent_accounting(void)
                goto out;
        }
 
-       /* [BTRFS_MAX_EXTENT_SIZE][4K] */
+       /* [BTRFS_MAX_EXTENT_SIZE][sectorsize] */
        BTRFS_I(inode)->outstanding_extents++;
        ret = btrfs_set_extent_delalloc(inode, BTRFS_MAX_EXTENT_SIZE >> 1,
-                                       (BTRFS_MAX_EXTENT_SIZE >> 1) + 4095,
+                                       (BTRFS_MAX_EXTENT_SIZE >> 1)
+                                       + sectorsize - 1,
                                        NULL);
        if (ret) {
                test_msg("btrfs_set_extent_delalloc returned %d\n", ret);
@@ -1004,16 +1031,17 @@ static int test_extent_accounting(void)
        }
 
        /*
-        * [BTRFS_MAX_EXTENT_SIZE+4K][4K HOLE][BTRFS_MAX_EXTENT_SIZE+4K]
+        * [BTRFS_MAX_EXTENT_SIZE+sectorsize][sectorsize HOLE][BTRFS_MAX_EXTENT_SIZE+sectorsize]
         *
         * I'm artificially adding 2 to outstanding_extents because in the
         * buffered IO case we'd add things up as we go, but I don't feel like
         * doing that here, this isn't the interesting case we want to test.
         */
        BTRFS_I(inode)->outstanding_extents += 2;
-       ret = btrfs_set_extent_delalloc(inode, BTRFS_MAX_EXTENT_SIZE + 8192,
-                                       (BTRFS_MAX_EXTENT_SIZE << 1) + 12287,
-                                       NULL);
+       ret = btrfs_set_extent_delalloc(inode,
+                       BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize,
+                       (BTRFS_MAX_EXTENT_SIZE << 1) + 3 * sectorsize - 1,
+                       NULL);
        if (ret) {
                test_msg("btrfs_set_extent_delalloc returned %d\n", ret);
                goto out;
@@ -1025,10 +1053,13 @@ static int test_extent_accounting(void)
                goto out;
        }
 
-       /* [BTRFS_MAX_EXTENT_SIZE+4k][4k][BTRFS_MAX_EXTENT_SIZE+4k] */
+       /*
+       * [BTRFS_MAX_EXTENT_SIZE+sectorsize][sectorsize][BTRFS_MAX_EXTENT_SIZE+sectorsize]
+       */
        BTRFS_I(inode)->outstanding_extents++;
-       ret = btrfs_set_extent_delalloc(inode, BTRFS_MAX_EXTENT_SIZE+4096,
-                                       BTRFS_MAX_EXTENT_SIZE+8191, NULL);
+       ret = btrfs_set_extent_delalloc(inode,
+                       BTRFS_MAX_EXTENT_SIZE + sectorsize,
+                       BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize - 1, NULL);
        if (ret) {
                test_msg("btrfs_set_extent_delalloc returned %d\n", ret);
                goto out;
@@ -1042,8 +1073,8 @@ static int test_extent_accounting(void)
 
        /* [BTRFS_MAX_EXTENT_SIZE+4k][4K HOLE][BTRFS_MAX_EXTENT_SIZE+4k] */
        ret = clear_extent_bit(&BTRFS_I(inode)->io_tree,
-                              BTRFS_MAX_EXTENT_SIZE+4096,
-                              BTRFS_MAX_EXTENT_SIZE+8191,
+                              BTRFS_MAX_EXTENT_SIZE + sectorsize,
+                              BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize - 1,
                               EXTENT_DIRTY | EXTENT_DELALLOC |
                               EXTENT_DO_ACCOUNTING | EXTENT_UPTODATE, 0, 0,
                               NULL, GFP_KERNEL);
@@ -1063,8 +1094,9 @@ static int test_extent_accounting(void)
         * might fail and I'd rather satisfy my paranoia at this point.
         */
        BTRFS_I(inode)->outstanding_extents++;
-       ret = btrfs_set_extent_delalloc(inode, BTRFS_MAX_EXTENT_SIZE+4096,
-                                       BTRFS_MAX_EXTENT_SIZE+8191, NULL);
+       ret = btrfs_set_extent_delalloc(inode,
+                       BTRFS_MAX_EXTENT_SIZE + sectorsize,
+                       BTRFS_MAX_EXTENT_SIZE + 2 * sectorsize - 1, NULL);
        if (ret) {
                test_msg("btrfs_set_extent_delalloc returned %d\n", ret);
                goto out;
@@ -1103,7 +1135,7 @@ out:
        return ret;
 }
 
-int btrfs_test_inodes(void)
+int btrfs_test_inodes(u32 sectorsize, u32 nodesize)
 {
        int ret;
 
@@ -1112,13 +1144,13 @@ int btrfs_test_inodes(void)
        set_bit(EXTENT_FLAG_PREALLOC, &prealloc_only);
 
        test_msg("Running btrfs_get_extent tests\n");
-       ret = test_btrfs_get_extent();
+       ret = test_btrfs_get_extent(sectorsize, nodesize);
        if (ret)
                return ret;
        test_msg("Running hole first btrfs_get_extent test\n");
-       ret = test_hole_first();
+       ret = test_hole_first(sectorsize, nodesize);
        if (ret)
                return ret;
        test_msg("Running outstanding_extents tests\n");
-       return test_extent_accounting();
+       return test_extent_accounting(sectorsize, nodesize);
 }
index 8aa4ded..57a12c0 100644 (file)
@@ -16,6 +16,7 @@
  * Boston, MA 021110-1307, USA.
  */
 
+#include <linux/types.h>
 #include "btrfs-tests.h"
 #include "../ctree.h"
 #include "../transaction.h"
@@ -216,7 +217,8 @@ static int remove_extent_ref(struct btrfs_root *root, u64 bytenr,
        return ret;
 }
 
-static int test_no_shared_qgroup(struct btrfs_root *root)
+static int test_no_shared_qgroup(struct btrfs_root *root,
+               u32 sectorsize, u32 nodesize)
 {
        struct btrfs_trans_handle trans;
        struct btrfs_fs_info *fs_info = root->fs_info;
@@ -227,7 +229,7 @@ static int test_no_shared_qgroup(struct btrfs_root *root)
        btrfs_init_dummy_trans(&trans);
 
        test_msg("Qgroup basic add\n");
-       ret = btrfs_create_qgroup(NULL, fs_info, 5);
+       ret = btrfs_create_qgroup(NULL, fs_info, BTRFS_FS_TREE_OBJECTID);
        if (ret) {
                test_msg("Couldn't create a qgroup %d\n", ret);
                return ret;
@@ -238,18 +240,19 @@ static int test_no_shared_qgroup(struct btrfs_root *root)
         * we can only call btrfs_qgroup_account_extent() directly to test
         * quota.
         */
-       ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &old_roots);
+       ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots);
        if (ret) {
                ulist_free(old_roots);
                test_msg("Couldn't find old roots: %d\n", ret);
                return ret;
        }
 
-       ret = insert_normal_tree_ref(root, 4096, 4096, 0, 5);
+       ret = insert_normal_tree_ref(root, nodesize, nodesize, 0,
+                               BTRFS_FS_TREE_OBJECTID);
        if (ret)
                return ret;
 
-       ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &new_roots);
+       ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots);
        if (ret) {
                ulist_free(old_roots);
                ulist_free(new_roots);
@@ -257,32 +260,33 @@ static int test_no_shared_qgroup(struct btrfs_root *root)
                return ret;
        }
 
-       ret = btrfs_qgroup_account_extent(&trans, fs_info, 4096, 4096,
-                                         old_roots, new_roots);
+       ret = btrfs_qgroup_account_extent(&trans, fs_info, nodesize,
+                                         nodesize, old_roots, new_roots);
        if (ret) {
                test_msg("Couldn't account space for a qgroup %d\n", ret);
                return ret;
        }
 
-       if (btrfs_verify_qgroup_counts(fs_info, 5, 4096, 4096)) {
+       if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID,
+                               nodesize, nodesize)) {
                test_msg("Qgroup counts didn't match expected values\n");
                return -EINVAL;
        }
        old_roots = NULL;
        new_roots = NULL;
 
-       ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &old_roots);
+       ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots);
        if (ret) {
                ulist_free(old_roots);
                test_msg("Couldn't find old roots: %d\n", ret);
                return ret;
        }
 
-       ret = remove_extent_item(root, 4096, 4096);
+       ret = remove_extent_item(root, nodesize, nodesize);
        if (ret)
                return -EINVAL;
 
-       ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &new_roots);
+       ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots);
        if (ret) {
                ulist_free(old_roots);
                ulist_free(new_roots);
@@ -290,14 +294,14 @@ static int test_no_shared_qgroup(struct btrfs_root *root)
                return ret;
        }
 
-       ret = btrfs_qgroup_account_extent(&trans, fs_info, 4096, 4096,
-                                         old_roots, new_roots);
+       ret = btrfs_qgroup_account_extent(&trans, fs_info, nodesize,
+                                         nodesize, old_roots, new_roots);
        if (ret) {
                test_msg("Couldn't account space for a qgroup %d\n", ret);
                return -EINVAL;
        }
 
-       if (btrfs_verify_qgroup_counts(fs_info, 5, 0, 0)) {
+       if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID, 0, 0)) {
                test_msg("Qgroup counts didn't match expected values\n");
                return -EINVAL;
        }
@@ -310,7 +314,8 @@ static int test_no_shared_qgroup(struct btrfs_root *root)
  * right, also remove one of the roots and make sure the exclusive count is
  * adjusted properly.
  */
-static int test_multiple_refs(struct btrfs_root *root)
+static int test_multiple_refs(struct btrfs_root *root,
+               u32 sectorsize, u32 nodesize)
 {
        struct btrfs_trans_handle trans;
        struct btrfs_fs_info *fs_info = root->fs_info;
@@ -322,25 +327,29 @@ static int test_multiple_refs(struct btrfs_root *root)
 
        test_msg("Qgroup multiple refs test\n");
 
-       /* We have 5 created already from the previous test */
-       ret = btrfs_create_qgroup(NULL, fs_info, 256);
+       /*
+        * We have BTRFS_FS_TREE_OBJECTID created already from the
+        * previous test.
+        */
+       ret = btrfs_create_qgroup(NULL, fs_info, BTRFS_FIRST_FREE_OBJECTID);
        if (ret) {
                test_msg("Couldn't create a qgroup %d\n", ret);
                return ret;
        }
 
-       ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &old_roots);
+       ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots);
        if (ret) {
                ulist_free(old_roots);
                test_msg("Couldn't find old roots: %d\n", ret);
                return ret;
        }
 
-       ret = insert_normal_tree_ref(root, 4096, 4096, 0, 5);
+       ret = insert_normal_tree_ref(root, nodesize, nodesize, 0,
+                               BTRFS_FS_TREE_OBJECTID);
        if (ret)
                return ret;
 
-       ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &new_roots);
+       ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots);
        if (ret) {
                ulist_free(old_roots);
                ulist_free(new_roots);
@@ -348,30 +357,32 @@ static int test_multiple_refs(struct btrfs_root *root)
                return ret;
        }
 
-       ret = btrfs_qgroup_account_extent(&trans, fs_info, 4096, 4096,
-                                         old_roots, new_roots);
+       ret = btrfs_qgroup_account_extent(&trans, fs_info, nodesize,
+                                         nodesize, old_roots, new_roots);
        if (ret) {
                test_msg("Couldn't account space for a qgroup %d\n", ret);
                return ret;
        }
 
-       if (btrfs_verify_qgroup_counts(fs_info, 5, 4096, 4096)) {
+       if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID,
+                                      nodesize, nodesize)) {
                test_msg("Qgroup counts didn't match expected values\n");
                return -EINVAL;
        }
 
-       ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &old_roots);
+       ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots);
        if (ret) {
                ulist_free(old_roots);
                test_msg("Couldn't find old roots: %d\n", ret);
                return ret;
        }
 
-       ret = add_tree_ref(root, 4096, 4096, 0, 256);
+       ret = add_tree_ref(root, nodesize, nodesize, 0,
+                       BTRFS_FIRST_FREE_OBJECTID);
        if (ret)
                return ret;
 
-       ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &new_roots);
+       ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots);
        if (ret) {
                ulist_free(old_roots);
                ulist_free(new_roots);
@@ -379,35 +390,38 @@ static int test_multiple_refs(struct btrfs_root *root)
                return ret;
        }
 
-       ret = btrfs_qgroup_account_extent(&trans, fs_info, 4096, 4096,
-                                         old_roots, new_roots);
+       ret = btrfs_qgroup_account_extent(&trans, fs_info, nodesize,
+                                         nodesize, old_roots, new_roots);
        if (ret) {
                test_msg("Couldn't account space for a qgroup %d\n", ret);
                return ret;
        }
 
-       if (btrfs_verify_qgroup_counts(fs_info, 5, 4096, 0)) {
+       if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID,
+                                       nodesize, 0)) {
                test_msg("Qgroup counts didn't match expected values\n");
                return -EINVAL;
        }
 
-       if (btrfs_verify_qgroup_counts(fs_info, 256, 4096, 0)) {
+       if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FIRST_FREE_OBJECTID,
+                                       nodesize, 0)) {
                test_msg("Qgroup counts didn't match expected values\n");
                return -EINVAL;
        }
 
-       ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &old_roots);
+       ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots);
        if (ret) {
                ulist_free(old_roots);
                test_msg("Couldn't find old roots: %d\n", ret);
                return ret;
        }
 
-       ret = remove_extent_ref(root, 4096, 4096, 0, 256);
+       ret = remove_extent_ref(root, nodesize, nodesize, 0,
+                               BTRFS_FIRST_FREE_OBJECTID);
        if (ret)
                return ret;
 
-       ret = btrfs_find_all_roots(&trans, fs_info, 4096, 0, &new_roots);
+       ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots);
        if (ret) {
                ulist_free(old_roots);
                ulist_free(new_roots);
@@ -415,19 +429,21 @@ static int test_multiple_refs(struct btrfs_root *root)
                return ret;
        }
 
-       ret = btrfs_qgroup_account_extent(&trans, fs_info, 4096, 4096,
-                                         old_roots, new_roots);
+       ret = btrfs_qgroup_account_extent(&trans, fs_info, nodesize,
+                                         nodesize, old_roots, new_roots);
        if (ret) {
                test_msg("Couldn't account space for a qgroup %d\n", ret);
                return ret;
        }
 
-       if (btrfs_verify_qgroup_counts(fs_info, 256, 0, 0)) {
+       if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FIRST_FREE_OBJECTID,
+                                       0, 0)) {
                test_msg("Qgroup counts didn't match expected values\n");
                return -EINVAL;
        }
 
-       if (btrfs_verify_qgroup_counts(fs_info, 5, 4096, 4096)) {
+       if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID,
+                                       nodesize, nodesize)) {
                test_msg("Qgroup counts didn't match expected values\n");
                return -EINVAL;
        }
@@ -435,13 +451,13 @@ static int test_multiple_refs(struct btrfs_root *root)
        return 0;
 }
 
-int btrfs_test_qgroups(void)
+int btrfs_test_qgroups(u32 sectorsize, u32 nodesize)
 {
        struct btrfs_root *root;
        struct btrfs_root *tmp_root;
        int ret = 0;
 
-       root = btrfs_alloc_dummy_root();
+       root = btrfs_alloc_dummy_root(sectorsize, nodesize);
        if (IS_ERR(root)) {
                test_msg("Couldn't allocate root\n");
                return PTR_ERR(root);
@@ -468,7 +484,8 @@ int btrfs_test_qgroups(void)
         * Can't use bytenr 0, some things freak out
         * *cough*backref walking code*cough*
         */
-       root->node = alloc_test_extent_buffer(root->fs_info, 4096);
+       root->node = alloc_test_extent_buffer(root->fs_info, nodesize,
+                                       nodesize);
        if (!root->node) {
                test_msg("Couldn't allocate dummy buffer\n");
                ret = -ENOMEM;
@@ -476,16 +493,16 @@ int btrfs_test_qgroups(void)
        }
        btrfs_set_header_level(root->node, 0);
        btrfs_set_header_nritems(root->node, 0);
-       root->alloc_bytenr += 8192;
+       root->alloc_bytenr += 2 * nodesize;
 
-       tmp_root = btrfs_alloc_dummy_root();
+       tmp_root = btrfs_alloc_dummy_root(sectorsize, nodesize);
        if (IS_ERR(tmp_root)) {
                test_msg("Couldn't allocate a fs root\n");
                ret = PTR_ERR(tmp_root);
                goto out;
        }
 
-       tmp_root->root_key.objectid = 5;
+       tmp_root->root_key.objectid = BTRFS_FS_TREE_OBJECTID;
        root->fs_info->fs_root = tmp_root;
        ret = btrfs_insert_fs_root(root->fs_info, tmp_root);
        if (ret) {
@@ -493,14 +510,14 @@ int btrfs_test_qgroups(void)
                goto out;
        }
 
-       tmp_root = btrfs_alloc_dummy_root();
+       tmp_root = btrfs_alloc_dummy_root(sectorsize, nodesize);
        if (IS_ERR(tmp_root)) {
                test_msg("Couldn't allocate a fs root\n");
                ret = PTR_ERR(tmp_root);
                goto out;
        }
 
-       tmp_root->root_key.objectid = 256;
+       tmp_root->root_key.objectid = BTRFS_FIRST_FREE_OBJECTID;
        ret = btrfs_insert_fs_root(root->fs_info, tmp_root);
        if (ret) {
                test_msg("Couldn't insert fs root %d\n", ret);
@@ -508,10 +525,10 @@ int btrfs_test_qgroups(void)
        }
 
        test_msg("Running qgroup tests\n");
-       ret = test_no_shared_qgroup(root);
+       ret = test_no_shared_qgroup(root, sectorsize, nodesize);
        if (ret)
                goto out;
-       ret = test_multiple_refs(root);
+       ret = test_multiple_refs(root, sectorsize, nodesize);
 out:
        btrfs_free_dummy_root(root);
        return ret;
index f6e24cb..948aa18 100644 (file)
@@ -818,6 +818,7 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
 {
        struct btrfs_transaction *cur_trans = trans->transaction;
        struct btrfs_fs_info *info = root->fs_info;
+       u64 transid = trans->transid;
        unsigned long cur = trans->delayed_ref_updates;
        int lock = (trans->type != TRANS_JOIN_NOLOCK);
        int err = 0;
@@ -905,7 +906,7 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
 
        kmem_cache_free(btrfs_trans_handle_cachep, trans);
        if (must_run_delayed_refs) {
-               btrfs_async_run_delayed_refs(root, cur,
+               btrfs_async_run_delayed_refs(root, cur, transid,
                                             must_run_delayed_refs == 1);
        }
        return err;
@@ -1311,11 +1312,6 @@ int btrfs_defrag_root(struct btrfs_root *root)
        return ret;
 }
 
-/* Bisesctability fixup, remove in 4.8 */
-#ifndef btrfs_std_error
-#define btrfs_std_error btrfs_handle_fs_error
-#endif
-
 /*
  * Do all special snapshot related qgroup dirty hack.
  *
@@ -1385,7 +1381,7 @@ static int qgroup_account_snapshot(struct btrfs_trans_handle *trans,
        switch_commit_roots(trans->transaction, fs_info);
        ret = btrfs_write_and_wait_transaction(trans, src);
        if (ret)
-               btrfs_std_error(fs_info, ret,
+               btrfs_handle_fs_error(fs_info, ret,
                        "Error while writing out transaction for qgroup");
 
 out:
index 9fe0ec2..c5abee4 100644 (file)
@@ -110,7 +110,6 @@ struct btrfs_trans_handle {
        u64 chunk_bytes_reserved;
        unsigned long use_count;
        unsigned long blocks_reserved;
-       unsigned long blocks_used;
        unsigned long delayed_ref_updates;
        struct btrfs_transaction *transaction;
        struct btrfs_block_rsv *block_rsv;
@@ -121,6 +120,7 @@ struct btrfs_trans_handle {
        bool can_flush_pending_bgs;
        bool reloc_reserved;
        bool sync;
+       bool dirty;
        unsigned int type;
        /*
         * this root is only needed to validate that the root passed to
index b7665af..c05f69a 100644 (file)
@@ -2422,8 +2422,8 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,
                root_owner = btrfs_header_owner(parent);
 
                next = btrfs_find_create_tree_block(root, bytenr);
-               if (!next)
-                       return -ENOMEM;
+               if (IS_ERR(next))
+                       return PTR_ERR(next);
 
                if (*level == 1) {
                        ret = wc->process_func(root, next, wc, ptr_gen);
index bdc6256..589f128 100644 (file)
@@ -2761,6 +2761,7 @@ int btrfs_remove_chunk(struct btrfs_trans_handle *trans,
        u64 dev_extent_len = 0;
        u64 chunk_objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID;
        int i, ret = 0;
+       struct btrfs_fs_devices *fs_devices = root->fs_info->fs_devices;
 
        /* Just in case */
        root = root->fs_info->chunk_root;
@@ -2787,12 +2788,19 @@ int btrfs_remove_chunk(struct btrfs_trans_handle *trans,
        check_system_chunk(trans, extent_root, map->type);
        unlock_chunks(root->fs_info->chunk_root);
 
+       /*
+        * Take the device list mutex to prevent races with the final phase of
+        * a device replace operation that replaces the device object associated
+        * with map stripes (dev-replace.c:btrfs_dev_replace_finishing()).
+        */
+       mutex_lock(&fs_devices->device_list_mutex);
        for (i = 0; i < map->num_stripes; i++) {
                struct btrfs_device *device = map->stripes[i].dev;
                ret = btrfs_free_dev_extent(trans, device,
                                            map->stripes[i].physical,
                                            &dev_extent_len);
                if (ret) {
+                       mutex_unlock(&fs_devices->device_list_mutex);
                        btrfs_abort_transaction(trans, root, ret);
                        goto out;
                }
@@ -2811,11 +2819,14 @@ int btrfs_remove_chunk(struct btrfs_trans_handle *trans,
                if (map->stripes[i].dev) {
                        ret = btrfs_update_device(trans, map->stripes[i].dev);
                        if (ret) {
+                               mutex_unlock(&fs_devices->device_list_mutex);
                                btrfs_abort_transaction(trans, root, ret);
                                goto out;
                        }
                }
        }
+       mutex_unlock(&fs_devices->device_list_mutex);
+
        ret = btrfs_free_chunk(trans, root, chunk_objectid, chunk_offset);
        if (ret) {
                btrfs_abort_transaction(trans, root, ret);
@@ -4230,6 +4241,7 @@ int btrfs_create_uuid_tree(struct btrfs_fs_info *fs_info)
        if (IS_ERR(uuid_root)) {
                ret = PTR_ERR(uuid_root);
                btrfs_abort_transaction(trans, tree_root, ret);
+               btrfs_end_transaction(trans, tree_root);
                return ret;
        }
 
@@ -4682,12 +4694,12 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
 
        if (type & BTRFS_BLOCK_GROUP_RAID5) {
                raid_stripe_len = find_raid56_stripe_len(ndevs - 1,
-                                btrfs_super_stripesize(info->super_copy));
+                                               extent_root->stripesize);
                data_stripes = num_stripes - 1;
        }
        if (type & BTRFS_BLOCK_GROUP_RAID6) {
                raid_stripe_len = find_raid56_stripe_len(ndevs - 2,
-                                btrfs_super_stripesize(info->super_copy));
+                                               extent_root->stripesize);
                data_stripes = num_stripes - 2;
        }
 
@@ -5762,20 +5774,17 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
                        }
                }
                if (found) {
-                       if (physical_of_found + map->stripe_len <=
-                           dev_replace->cursor_left) {
-                               struct btrfs_bio_stripe *tgtdev_stripe =
-                                       bbio->stripes + num_stripes;
+                       struct btrfs_bio_stripe *tgtdev_stripe =
+                               bbio->stripes + num_stripes;
 
-                               tgtdev_stripe->physical = physical_of_found;
-                               tgtdev_stripe->length =
-                                       bbio->stripes[index_srcdev].length;
-                               tgtdev_stripe->dev = dev_replace->tgtdev;
-                               bbio->tgtdev_map[index_srcdev] = num_stripes;
+                       tgtdev_stripe->physical = physical_of_found;
+                       tgtdev_stripe->length =
+                               bbio->stripes[index_srcdev].length;
+                       tgtdev_stripe->dev = dev_replace->tgtdev;
+                       bbio->tgtdev_map[index_srcdev] = num_stripes;
 
-                               tgtdev_indexes++;
-                               num_stripes++;
-                       }
+                       tgtdev_indexes++;
+                       num_stripes++;
                }
        }
 
@@ -6250,27 +6259,23 @@ struct btrfs_device *btrfs_alloc_device(struct btrfs_fs_info *fs_info,
        return dev;
 }
 
-static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
-                         struct extent_buffer *leaf,
-                         struct btrfs_chunk *chunk)
+/* Return -EIO if any error, otherwise return 0. */
+static int btrfs_check_chunk_valid(struct btrfs_root *root,
+                                  struct extent_buffer *leaf,
+                                  struct btrfs_chunk *chunk, u64 logical)
 {
-       struct btrfs_mapping_tree *map_tree = &root->fs_info->mapping_tree;
-       struct map_lookup *map;
-       struct extent_map *em;
-       u64 logical;
        u64 length;
        u64 stripe_len;
-       u64 devid;
-       u8 uuid[BTRFS_UUID_SIZE];
-       int num_stripes;
-       int ret;
-       int i;
+       u16 num_stripes;
+       u16 sub_stripes;
+       u64 type;
 
-       logical = key->offset;
        length = btrfs_chunk_length(leaf, chunk);
        stripe_len = btrfs_chunk_stripe_len(leaf, chunk);
        num_stripes = btrfs_chunk_num_stripes(leaf, chunk);
-       /* Validation check */
+       sub_stripes = btrfs_chunk_sub_stripes(leaf, chunk);
+       type = btrfs_chunk_type(leaf, chunk);
+
        if (!num_stripes) {
                btrfs_err(root->fs_info, "invalid chunk num_stripes: %u",
                          num_stripes);
@@ -6281,6 +6286,11 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
                          "invalid chunk logical %llu", logical);
                return -EIO;
        }
+       if (btrfs_chunk_sector_size(leaf, chunk) != root->sectorsize) {
+               btrfs_err(root->fs_info, "invalid chunk sectorsize %u",
+                         btrfs_chunk_sector_size(leaf, chunk));
+               return -EIO;
+       }
        if (!length || !IS_ALIGNED(length, root->sectorsize)) {
                btrfs_err(root->fs_info,
                        "invalid chunk length %llu", length);
@@ -6292,13 +6302,54 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
                return -EIO;
        }
        if (~(BTRFS_BLOCK_GROUP_TYPE_MASK | BTRFS_BLOCK_GROUP_PROFILE_MASK) &
-           btrfs_chunk_type(leaf, chunk)) {
+           type) {
                btrfs_err(root->fs_info, "unrecognized chunk type: %llu",
                          ~(BTRFS_BLOCK_GROUP_TYPE_MASK |
                            BTRFS_BLOCK_GROUP_PROFILE_MASK) &
                          btrfs_chunk_type(leaf, chunk));
                return -EIO;
        }
+       if ((type & BTRFS_BLOCK_GROUP_RAID10 && sub_stripes != 2) ||
+           (type & BTRFS_BLOCK_GROUP_RAID1 && num_stripes < 1) ||
+           (type & BTRFS_BLOCK_GROUP_RAID5 && num_stripes < 2) ||
+           (type & BTRFS_BLOCK_GROUP_RAID6 && num_stripes < 3) ||
+           (type & BTRFS_BLOCK_GROUP_DUP && num_stripes > 2) ||
+           ((type & BTRFS_BLOCK_GROUP_PROFILE_MASK) == 0 &&
+            num_stripes != 1)) {
+               btrfs_err(root->fs_info,
+                       "invalid num_stripes:sub_stripes %u:%u for profile %llu",
+                       num_stripes, sub_stripes,
+                       type & BTRFS_BLOCK_GROUP_PROFILE_MASK);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
+                         struct extent_buffer *leaf,
+                         struct btrfs_chunk *chunk)
+{
+       struct btrfs_mapping_tree *map_tree = &root->fs_info->mapping_tree;
+       struct map_lookup *map;
+       struct extent_map *em;
+       u64 logical;
+       u64 length;
+       u64 stripe_len;
+       u64 devid;
+       u8 uuid[BTRFS_UUID_SIZE];
+       int num_stripes;
+       int ret;
+       int i;
+
+       logical = key->offset;
+       length = btrfs_chunk_length(leaf, chunk);
+       stripe_len = btrfs_chunk_stripe_len(leaf, chunk);
+       num_stripes = btrfs_chunk_num_stripes(leaf, chunk);
+
+       ret = btrfs_check_chunk_valid(root, leaf, chunk, logical);
+       if (ret)
+               return ret;
 
        read_lock(&map_tree->map_tree.lock);
        em = lookup_extent_mapping(&map_tree->map_tree, logical, 1);
@@ -6546,6 +6597,7 @@ int btrfs_read_sys_array(struct btrfs_root *root)
        u32 array_size;
        u32 len = 0;
        u32 cur_offset;
+       u64 type;
        struct btrfs_key key;
 
        ASSERT(BTRFS_SUPER_INFO_SIZE <= root->nodesize);
@@ -6555,8 +6607,8 @@ int btrfs_read_sys_array(struct btrfs_root *root)
         * overallocate but we can keep it as-is, only the first page is used.
         */
        sb = btrfs_find_create_tree_block(root, BTRFS_SUPER_INFO_OFFSET);
-       if (!sb)
-               return -ENOMEM;
+       if (IS_ERR(sb))
+               return PTR_ERR(sb);
        set_extent_buffer_uptodate(sb);
        btrfs_set_buffer_lockdep_class(root->root_key.objectid, sb, 0);
        /*
@@ -6612,6 +6664,15 @@ int btrfs_read_sys_array(struct btrfs_root *root)
                                break;
                        }
 
+                       type = btrfs_chunk_type(sb, chunk);
+                       if ((type & BTRFS_BLOCK_GROUP_SYSTEM) == 0) {
+                               btrfs_err(root->fs_info,
+                           "invalid chunk type %llu in sys_array at offset %u",
+                                       type, cur_offset);
+                               ret = -EIO;
+                               break;
+                       }
+
                        len = btrfs_chunk_item_size(num_stripes);
                        if (cur_offset + len > array_size)
                                goto out_short_read;
@@ -6630,12 +6691,14 @@ int btrfs_read_sys_array(struct btrfs_root *root)
                sb_array_offset += len;
                cur_offset += len;
        }
+       clear_extent_buffer_uptodate(sb);
        free_extent_buffer_stale(sb);
        return ret;
 
 out_short_read:
        printk(KERN_ERR "BTRFS: sys_array too short to read %u bytes at offset %u\n",
                        len, cur_offset);
+       clear_extent_buffer_uptodate(sb);
        free_extent_buffer_stale(sb);
        return -EIO;
 }
@@ -6648,6 +6711,7 @@ int btrfs_read_chunk_tree(struct btrfs_root *root)
        struct btrfs_key found_key;
        int ret;
        int slot;
+       u64 total_dev = 0;
 
        root = root->fs_info->chunk_root;
 
@@ -6689,6 +6753,7 @@ int btrfs_read_chunk_tree(struct btrfs_root *root)
                        ret = read_one_dev(root, leaf, dev_item);
                        if (ret)
                                goto error;
+                       total_dev++;
                } else if (found_key.type == BTRFS_CHUNK_ITEM_KEY) {
                        struct btrfs_chunk *chunk;
                        chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk);
@@ -6698,6 +6763,28 @@ int btrfs_read_chunk_tree(struct btrfs_root *root)
                }
                path->slots[0]++;
        }
+
+       /*
+        * After loading chunk tree, we've got all device information,
+        * do another round of validation checks.
+        */
+       if (total_dev != root->fs_info->fs_devices->total_devices) {
+               btrfs_err(root->fs_info,
+          "super_num_devices %llu mismatch with num_devices %llu found here",
+                         btrfs_super_num_devices(root->fs_info->super_copy),
+                         total_dev);
+               ret = -EINVAL;
+               goto error;
+       }
+       if (btrfs_super_total_bytes(root->fs_info->super_copy) <
+           root->fs_info->fs_devices->total_rw_bytes) {
+               btrfs_err(root->fs_info,
+       "super_total_bytes %llu mismatch with fs_devices total_rw_bytes %llu",
+                         btrfs_super_total_bytes(root->fs_info->super_copy),
+                         root->fs_info->fs_devices->total_rw_bytes);
+               ret = -EINVAL;
+               goto error;
+       }
        ret = 0;
 error:
        unlock_chunks(root);
index 861d611..ce5f345 100644 (file)
@@ -380,7 +380,7 @@ static void cachefiles_sync_cache(struct fscache_cache *_cache)
  * check if the backing cache is updated to FS-Cache
  * - called by FS-Cache when evaluates if need to invalidate the cache
  */
-static bool cachefiles_check_consistency(struct fscache_operation *op)
+static int cachefiles_check_consistency(struct fscache_operation *op)
 {
        struct cachefiles_object *object;
        struct cachefiles_cache *cache;
index eeb71e5..26a9d10 100644 (file)
@@ -276,8 +276,10 @@ static void finish_read(struct ceph_osd_request *req)
        for (i = 0; i < num_pages; i++) {
                struct page *page = osd_data->pages[i];
 
-               if (rc < 0 && rc != -ENOENT)
+               if (rc < 0 && rc != -ENOENT) {
+                       ceph_fscache_readpage_cancel(inode, page);
                        goto unlock;
+               }
                if (bytes < (int)PAGE_SIZE) {
                        /* zero (remainder of) page */
                        int s = bytes < 0 ? 0 : bytes;
@@ -535,8 +537,6 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc)
            CONGESTION_ON_THRESH(fsc->mount_options->congestion_kb))
                set_bdi_congested(&fsc->backing_dev_info, BLK_RW_ASYNC);
 
-       ceph_readpage_to_fscache(inode, page);
-
        set_page_writeback(page);
        err = ceph_osdc_writepages(osdc, ceph_vino(inode),
                                   &ci->i_layout, snapc,
index c052b5b..238c55b 100644 (file)
@@ -25,6 +25,7 @@
 #include "cache.h"
 
 struct ceph_aux_inode {
+       u64             version;
        struct timespec mtime;
        loff_t          size;
 };
@@ -69,15 +70,8 @@ int ceph_fscache_register_fs(struct ceph_fs_client* fsc)
        fsc->fscache = fscache_acquire_cookie(ceph_cache_netfs.primary_index,
                                              &ceph_fscache_fsid_object_def,
                                              fsc, true);
-
-       if (fsc->fscache == NULL) {
+       if (!fsc->fscache)
                pr_err("Unable to resgister fsid: %p fscache cookie", fsc);
-               return 0;
-       }
-
-       fsc->revalidate_wq = alloc_workqueue("ceph-revalidate", 0, 1);
-       if (fsc->revalidate_wq == NULL)
-               return -ENOMEM;
 
        return 0;
 }
@@ -105,6 +99,7 @@ static uint16_t ceph_fscache_inode_get_aux(const void *cookie_netfs_data,
        const struct inode* inode = &ci->vfs_inode;
 
        memset(&aux, 0, sizeof(aux));
+       aux.version = ci->i_version;
        aux.mtime = inode->i_mtime;
        aux.size = i_size_read(inode);
 
@@ -131,6 +126,7 @@ static enum fscache_checkaux ceph_fscache_inode_check_aux(
                return FSCACHE_CHECKAUX_OBSOLETE;
 
        memset(&aux, 0, sizeof(aux));
+       aux.version = ci->i_version;
        aux.mtime = inode->i_mtime;
        aux.size = i_size_read(inode);
 
@@ -181,32 +177,26 @@ static const struct fscache_cookie_def ceph_fscache_inode_object_def = {
        .now_uncached   = ceph_fscache_inode_now_uncached,
 };
 
-void ceph_fscache_register_inode_cookie(struct ceph_fs_client* fsc,
-                                       struct ceph_inode_info* ci)
+void ceph_fscache_register_inode_cookie(struct inode *inode)
 {
-       struct inode* inode = &ci->vfs_inode;
+       struct ceph_inode_info *ci = ceph_inode(inode);
+       struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
 
        /* No caching for filesystem */
        if (fsc->fscache == NULL)
                return;
 
        /* Only cache for regular files that are read only */
-       if ((ci->vfs_inode.i_mode & S_IFREG) == 0)
+       if (!S_ISREG(inode->i_mode))
                return;
 
-       /* Avoid multiple racing open requests */
-       inode_lock(inode);
-
-       if (ci->fscache)
-               goto done;
-
-       ci->fscache = fscache_acquire_cookie(fsc->fscache,
-                                            &ceph_fscache_inode_object_def,
-                                            ci, true);
-       fscache_check_consistency(ci->fscache);
-done:
+       inode_lock_nested(inode, I_MUTEX_CHILD);
+       if (!ci->fscache) {
+               ci->fscache = fscache_acquire_cookie(fsc->fscache,
+                                       &ceph_fscache_inode_object_def,
+                                       ci, false);
+       }
        inode_unlock(inode);
-
 }
 
 void ceph_fscache_unregister_inode_cookie(struct ceph_inode_info* ci)
@@ -222,6 +212,34 @@ void ceph_fscache_unregister_inode_cookie(struct ceph_inode_info* ci)
        fscache_relinquish_cookie(cookie, 0);
 }
 
+static bool ceph_fscache_can_enable(void *data)
+{
+       struct inode *inode = data;
+       return !inode_is_open_for_write(inode);
+}
+
+void ceph_fscache_file_set_cookie(struct inode *inode, struct file *filp)
+{
+       struct ceph_inode_info *ci = ceph_inode(inode);
+
+       if (!fscache_cookie_valid(ci->fscache))
+               return;
+
+       if (inode_is_open_for_write(inode)) {
+               dout("fscache_file_set_cookie %p %p disabling cache\n",
+                    inode, filp);
+               fscache_disable_cookie(ci->fscache, false);
+               fscache_uncache_all_inode_pages(ci->fscache, inode);
+       } else {
+               fscache_enable_cookie(ci->fscache, ceph_fscache_can_enable,
+                               inode);
+               if (fscache_cookie_enabled(ci->fscache)) {
+                       dout("fscache_file_set_cookie %p %p enabing cache\n",
+                            inode, filp);
+               }
+       }
+}
+
 static void ceph_vfs_readpage_complete(struct page *page, void *data, int error)
 {
        if (!error)
@@ -238,8 +256,7 @@ static void ceph_vfs_readpage_complete_unlock(struct page *page, void *data, int
 
 static inline bool cache_valid(struct ceph_inode_info *ci)
 {
-       return ((ceph_caps_issued(ci) & CEPH_CAP_FILE_CACHE) &&
-               (ci->i_fscache_gen == ci->i_rdcache_gen));
+       return ci->i_fscache_gen == ci->i_rdcache_gen;
 }
 
 
@@ -332,69 +349,27 @@ void ceph_invalidate_fscache_page(struct inode* inode, struct page *page)
 
 void ceph_fscache_unregister_fs(struct ceph_fs_client* fsc)
 {
-       if (fsc->revalidate_wq)
-               destroy_workqueue(fsc->revalidate_wq);
-
        fscache_relinquish_cookie(fsc->fscache, 0);
        fsc->fscache = NULL;
 }
 
-static void ceph_revalidate_work(struct work_struct *work)
-{
-       int issued;
-       u32 orig_gen;
-       struct ceph_inode_info *ci = container_of(work, struct ceph_inode_info,
-                                                 i_revalidate_work);
-       struct inode *inode = &ci->vfs_inode;
-
-       spin_lock(&ci->i_ceph_lock);
-       issued = __ceph_caps_issued(ci, NULL);
-       orig_gen = ci->i_rdcache_gen;
-       spin_unlock(&ci->i_ceph_lock);
-
-       if (!(issued & CEPH_CAP_FILE_CACHE)) {
-               dout("revalidate_work lost cache before validation %p\n",
-                    inode);
-               goto out;
-       }
-
-       if (!fscache_check_consistency(ci->fscache))
-               fscache_invalidate(ci->fscache);
-
-       spin_lock(&ci->i_ceph_lock);
-       /* Update the new valid generation (backwards sanity check too) */
-       if (orig_gen > ci->i_fscache_gen) {
-               ci->i_fscache_gen = orig_gen;
-       }
-       spin_unlock(&ci->i_ceph_lock);
-
-out:
-       iput(&ci->vfs_inode);
-}
-
-void ceph_queue_revalidate(struct inode *inode)
+/*
+ * caller should hold CEPH_CAP_FILE_{RD,CACHE}
+ */
+void ceph_fscache_revalidate_cookie(struct ceph_inode_info *ci)
 {
-       struct ceph_fs_client *fsc = ceph_sb_to_client(inode->i_sb);
-       struct ceph_inode_info *ci = ceph_inode(inode);
-
-       if (fsc->revalidate_wq == NULL || ci->fscache == NULL)
+       if (cache_valid(ci))
                return;
 
-       ihold(inode);
-
-       if (queue_work(ceph_sb_to_client(inode->i_sb)->revalidate_wq,
-                      &ci->i_revalidate_work)) {
-               dout("ceph_queue_revalidate %p\n", inode);
-       } else {
-               dout("ceph_queue_revalidate %p failed\n)", inode);
-               iput(inode);
+       /* resue i_truncate_mutex. There should be no pending
+        * truncate while the caller holds CEPH_CAP_FILE_RD */
+       mutex_lock(&ci->i_truncate_mutex);
+       if (!cache_valid(ci)) {
+               if (fscache_check_consistency(ci->fscache))
+                       fscache_invalidate(ci->fscache);
+               spin_lock(&ci->i_ceph_lock);
+               ci->i_fscache_gen = ci->i_rdcache_gen;
+               spin_unlock(&ci->i_ceph_lock);
        }
-}
-
-void ceph_fscache_inode_init(struct ceph_inode_info *ci)
-{
-       ci->fscache = NULL;
-       /* The first load is verifed cookie open time */
-       ci->i_fscache_gen = 1;
-       INIT_WORK(&ci->i_revalidate_work, ceph_revalidate_work);
+       mutex_unlock(&ci->i_truncate_mutex);
 }
index 5ac591b..7e72c75 100644 (file)
@@ -34,10 +34,10 @@ void ceph_fscache_unregister(void);
 int ceph_fscache_register_fs(struct ceph_fs_client* fsc);
 void ceph_fscache_unregister_fs(struct ceph_fs_client* fsc);
 
-void ceph_fscache_inode_init(struct ceph_inode_info *ci);
-void ceph_fscache_register_inode_cookie(struct ceph_fs_client* fsc,
-                                       struct ceph_inode_info* ci);
+void ceph_fscache_register_inode_cookie(struct inode *inode);
 void ceph_fscache_unregister_inode_cookie(struct ceph_inode_info* ci);
+void ceph_fscache_file_set_cookie(struct inode *inode, struct file *filp);
+void ceph_fscache_revalidate_cookie(struct ceph_inode_info *ci);
 
 int ceph_readpage_from_fscache(struct inode *inode, struct page *page);
 int ceph_readpages_from_fscache(struct inode *inode,
@@ -46,12 +46,11 @@ int ceph_readpages_from_fscache(struct inode *inode,
                                unsigned *nr_pages);
 void ceph_readpage_to_fscache(struct inode *inode, struct page *page);
 void ceph_invalidate_fscache_page(struct inode* inode, struct page *page);
-void ceph_queue_revalidate(struct inode *inode);
 
-static inline void ceph_fscache_update_objectsize(struct inode *inode)
+static inline void ceph_fscache_inode_init(struct ceph_inode_info *ci)
 {
-       struct ceph_inode_info *ci = ceph_inode(inode);
-       fscache_attr_changed(ci->fscache);
+       ci->fscache = NULL;
+       ci->i_fscache_gen = 0;
 }
 
 static inline void ceph_fscache_invalidate(struct inode *inode)
@@ -88,6 +87,11 @@ static inline void ceph_fscache_readpages_cancel(struct inode *inode,
        return fscache_readpages_cancel(ci->fscache, pages);
 }
 
+static inline void ceph_disable_fscache_readpage(struct ceph_inode_info *ci)
+{
+       ci->i_fscache_gen = ci->i_rdcache_gen - 1;
+}
+
 #else
 
 static inline int ceph_fscache_register(void)
@@ -112,8 +116,20 @@ static inline void ceph_fscache_inode_init(struct ceph_inode_info *ci)
 {
 }
 
-static inline void ceph_fscache_register_inode_cookie(struct ceph_fs_client* parent_fsc,
-                                                     struct ceph_inode_info* ci)
+static inline void ceph_fscache_register_inode_cookie(struct inode *inode)
+{
+}
+
+static inline void ceph_fscache_unregister_inode_cookie(struct ceph_inode_info* ci)
+{
+}
+
+static inline void ceph_fscache_file_set_cookie(struct inode *inode,
+                                               struct file *filp)
+{
+}
+
+static inline void ceph_fscache_revalidate_cookie(struct ceph_inode_info *ci)
 {
 }
 
@@ -141,10 +157,6 @@ static inline void ceph_readpage_to_fscache(struct inode *inode,
 {
 }
 
-static inline void ceph_fscache_update_objectsize(struct inode *inode)
-{
-}
-
 static inline void ceph_fscache_invalidate(struct inode *inode)
 {
 }
@@ -154,10 +166,6 @@ static inline void ceph_invalidate_fscache_page(struct inode *inode,
 {
 }
 
-static inline void ceph_fscache_unregister_inode_cookie(struct ceph_inode_info* ci)
-{
-}
-
 static inline int ceph_release_fscache_page(struct page *page, gfp_t gfp)
 {
        return 1;
@@ -173,7 +181,7 @@ static inline void ceph_fscache_readpages_cancel(struct inode *inode,
 {
 }
 
-static inline void ceph_queue_revalidate(struct inode *inode)
+static inline void ceph_disable_fscache_readpage(struct ceph_inode_info *ci)
 {
 }
 
index c17b5d7..6f60d0a 100644 (file)
@@ -2393,6 +2393,9 @@ again:
                                snap_rwsem_locked = true;
                        }
                        *got = need | (have & want);
+                       if ((need & CEPH_CAP_FILE_RD) &&
+                           !(*got & CEPH_CAP_FILE_CACHE))
+                               ceph_disable_fscache_readpage(ci);
                        __take_cap_refs(ci, *got, true);
                        ret = 1;
                }
@@ -2554,6 +2557,9 @@ int ceph_get_caps(struct ceph_inode_info *ci, int need, int want,
                break;
        }
 
+       if ((_got & CEPH_CAP_FILE_RD) && (_got & CEPH_CAP_FILE_CACHE))
+               ceph_fscache_revalidate_cookie(ci);
+
        *got = _got;
        return 0;
 }
@@ -2795,7 +2801,6 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc,
        bool writeback = false;
        bool queue_trunc = false;
        bool queue_invalidate = false;
-       bool queue_revalidate = false;
        bool deleted_inode = false;
        bool fill_inline = false;
 
@@ -2837,8 +2842,6 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc,
                                ci->i_rdcache_revoking = ci->i_rdcache_gen;
                        }
                }
-
-               ceph_fscache_invalidate(inode);
        }
 
        /* side effects now are allowed */
@@ -2880,11 +2883,6 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc,
                }
        }
 
-       /* Do we need to revalidate our fscache cookie. Don't bother on the
-        * first cache cap as we already validate at cookie creation time. */
-       if ((issued & CEPH_CAP_FILE_CACHE) && ci->i_rdcache_gen > 1)
-               queue_revalidate = true;
-
        if (newcaps & CEPH_CAP_ANY_RD) {
                /* ctime/mtime/atime? */
                ceph_decode_timespec(&mtime, &grant->mtime);
@@ -2993,11 +2991,8 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc,
        if (fill_inline)
                ceph_fill_inline_data(inode, NULL, inline_data, inline_len);
 
-       if (queue_trunc) {
+       if (queue_trunc)
                ceph_queue_vmtruncate(inode);
-               ceph_queue_revalidate(inode);
-       } else if (queue_revalidate)
-               ceph_queue_revalidate(inode);
 
        if (writeback)
                /*
@@ -3199,10 +3194,8 @@ static void handle_cap_trunc(struct inode *inode,
                                          truncate_seq, truncate_size, size);
        spin_unlock(&ci->i_ceph_lock);
 
-       if (queue_trunc) {
+       if (queue_trunc)
                ceph_queue_vmtruncate(inode);
-               ceph_fscache_invalidate(inode);
-       }
 }
 
 /*
index a888df6..ce2f579 100644 (file)
@@ -137,23 +137,11 @@ static int ceph_init_file(struct inode *inode, struct file *file, int fmode)
 {
        struct ceph_file_info *cf;
        int ret = 0;
-       struct ceph_inode_info *ci = ceph_inode(inode);
-       struct ceph_fs_client *fsc = ceph_sb_to_client(inode->i_sb);
-       struct ceph_mds_client *mdsc = fsc->mdsc;
 
        switch (inode->i_mode & S_IFMT) {
        case S_IFREG:
-               /* First file open request creates the cookie, we want to keep
-                * this cookie around for the filetime of the inode as not to
-                * have to worry about fscache register / revoke / operation
-                * races.
-                *
-                * Also, if we know the operation is going to invalidate data
-                * (non readonly) just nuke the cache right away.
-                */
-               ceph_fscache_register_inode_cookie(mdsc->fsc, ci);
-               if ((fmode & CEPH_FILE_MODE_WR))
-                       ceph_fscache_invalidate(inode);
+               ceph_fscache_register_inode_cookie(inode);
+               ceph_fscache_file_set_cookie(inode, file);
        case S_IFDIR:
                dout("init_file %p %p 0%o (regular)\n", inode, file,
                     inode->i_mode);
@@ -1349,7 +1337,7 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
        }
 
 retry_snap:
-       if (ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_FULL)) {
+       if (ceph_osdmap_flag(osdc, CEPH_OSDMAP_FULL)) {
                err = -ENOSPC;
                goto out;
        }
@@ -1407,7 +1395,6 @@ retry_snap:
                        iov_iter_advance(from, written);
                ceph_put_snap_context(snapc);
        } else {
-               loff_t old_size = i_size_read(inode);
                /*
                 * No need to acquire the i_truncate_mutex. Because
                 * the MDS revokes Fwb caps before sending truncate
@@ -1418,8 +1405,6 @@ retry_snap:
                written = generic_perform_write(file, from, pos);
                if (likely(written >= 0))
                        iocb->ki_pos = pos + written;
-               if (i_size_read(inode) > old_size)
-                       ceph_fscache_update_objectsize(inode);
                inode_unlock(inode);
        }
 
@@ -1440,7 +1425,7 @@ retry_snap:
        ceph_put_cap_refs(ci, got);
 
        if (written >= 0) {
-               if (ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_NEARFULL))
+               if (ceph_osdmap_flag(osdc, CEPH_OSDMAP_NEARFULL))
                        iocb->ki_flags |= IOCB_DSYNC;
 
                written = generic_write_sync(iocb, written);
@@ -1672,8 +1657,8 @@ static long ceph_fallocate(struct file *file, int mode,
                goto unlock;
        }
 
-       if (ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_FULL) &&
-               !(mode & FALLOC_FL_PUNCH_HOLE)) {
+       if (ceph_osdmap_flag(osdc, CEPH_OSDMAP_FULL) &&
+           !(mode & FALLOC_FL_PUNCH_HOLE)) {
                ret = -ENOSPC;
                goto unlock;
        }
index 0130a85..0168b49 100644 (file)
@@ -103,7 +103,6 @@ struct ceph_fs_client {
 
 #ifdef CONFIG_CEPH_FSCACHE
        struct fscache_cookie *fscache;
-       struct workqueue_struct *revalidate_wq;
 #endif
 };
 
@@ -360,8 +359,7 @@ struct ceph_inode_info {
 
 #ifdef CONFIG_CEPH_FSCACHE
        struct fscache_cookie *fscache;
-       u32 i_fscache_gen; /* sequence, for delayed fscache validate */
-       struct work_struct i_revalidate_work;
+       u32 i_fscache_gen;
 #endif
        struct inode vfs_inode; /* at end */
 };
index 38a7ab8..281b768 100644 (file)
@@ -794,6 +794,7 @@ int dump_emit(struct coredump_params *cprm, const void *addr, int nr)
                        return 0;
                file->f_pos = pos;
                cprm->written += n;
+               cprm->pos += n;
                nr -= n;
        }
        return 1;
@@ -808,6 +809,7 @@ int dump_skip(struct coredump_params *cprm, size_t nr)
                if (dump_interrupted() ||
                    file->f_op->llseek(file, nr, SEEK_CUR) < 0)
                        return 0;
+               cprm->pos += nr;
                return 1;
        } else {
                while (nr > PAGE_SIZE) {
@@ -822,7 +824,7 @@ EXPORT_SYMBOL(dump_skip);
 
 int dump_align(struct coredump_params *cprm, int align)
 {
-       unsigned mod = cprm->file->f_pos & (align - 1);
+       unsigned mod = cprm->pos & (align - 1);
        if (align & (align - 1))
                return 0;
        return mod ? dump_skip(cprm, align - mod) : 1;
index ad4a542..d6847d7 100644 (file)
@@ -507,6 +507,44 @@ void d_drop(struct dentry *dentry)
 }
 EXPORT_SYMBOL(d_drop);
 
+static inline void dentry_unlist(struct dentry *dentry, struct dentry *parent)
+{
+       struct dentry *next;
+       /*
+        * Inform d_walk() and shrink_dentry_list() that we are no longer
+        * attached to the dentry tree
+        */
+       dentry->d_flags |= DCACHE_DENTRY_KILLED;
+       if (unlikely(list_empty(&dentry->d_child)))
+               return;
+       __list_del_entry(&dentry->d_child);
+       /*
+        * Cursors can move around the list of children.  While we'd been
+        * a normal list member, it didn't matter - ->d_child.next would've
+        * been updated.  However, from now on it won't be and for the
+        * things like d_walk() it might end up with a nasty surprise.
+        * Normally d_walk() doesn't care about cursors moving around -
+        * ->d_lock on parent prevents that and since a cursor has no children
+        * of its own, we get through it without ever unlocking the parent.
+        * There is one exception, though - if we ascend from a child that
+        * gets killed as soon as we unlock it, the next sibling is found
+        * using the value left in its ->d_child.next.  And if _that_
+        * pointed to a cursor, and cursor got moved (e.g. by lseek())
+        * before d_walk() regains parent->d_lock, we'll end up skipping
+        * everything the cursor had been moved past.
+        *
+        * Solution: make sure that the pointer left behind in ->d_child.next
+        * points to something that won't be moving around.  I.e. skip the
+        * cursors.
+        */
+       while (dentry->d_child.next != &parent->d_subdirs) {
+               next = list_entry(dentry->d_child.next, struct dentry, d_child);
+               if (likely(!(next->d_flags & DCACHE_DENTRY_CURSOR)))
+                       break;
+               dentry->d_child.next = next->d_child.next;
+       }
+}
+
 static void __dentry_kill(struct dentry *dentry)
 {
        struct dentry *parent = NULL;
@@ -532,12 +570,7 @@ static void __dentry_kill(struct dentry *dentry)
        }
        /* if it was on the hash then remove it */
        __d_drop(dentry);
-       __list_del_entry(&dentry->d_child);
-       /*
-        * Inform d_walk() that we are no longer attached to the
-        * dentry tree
-        */
-       dentry->d_flags |= DCACHE_DENTRY_KILLED;
+       dentry_unlist(dentry, parent);
        if (parent)
                spin_unlock(&parent->d_lock);
        dentry_iput(dentry);
@@ -1203,6 +1236,9 @@ resume:
                struct dentry *dentry = list_entry(tmp, struct dentry, d_child);
                next = tmp->next;
 
+               if (unlikely(dentry->d_flags & DCACHE_DENTRY_CURSOR))
+                       continue;
+
                spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
 
                ret = enter(data, dentry);
@@ -1636,7 +1672,7 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
        struct dentry *dentry = __d_alloc(parent->d_sb, name);
        if (!dentry)
                return NULL;
-
+       dentry->d_flags |= DCACHE_RCUACCESS;
        spin_lock(&parent->d_lock);
        /*
         * don't need child lock because it is not subject
@@ -1651,6 +1687,16 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
 }
 EXPORT_SYMBOL(d_alloc);
 
+struct dentry *d_alloc_cursor(struct dentry * parent)
+{
+       struct dentry *dentry = __d_alloc(parent->d_sb, NULL);
+       if (dentry) {
+               dentry->d_flags |= DCACHE_RCUACCESS | DCACHE_DENTRY_CURSOR;
+               dentry->d_parent = dget(parent);
+       }
+       return dentry;
+}
+
 /**
  * d_alloc_pseudo - allocate a dentry (for lookup-less filesystems)
  * @sb: the superblock
@@ -2358,7 +2404,6 @@ static void __d_rehash(struct dentry * entry, struct hlist_bl_head *b)
 {
        BUG_ON(!d_unhashed(entry));
        hlist_bl_lock(b);
-       entry->d_flags |= DCACHE_RCUACCESS;
        hlist_bl_add_head_rcu(&entry->d_hash, b);
        hlist_bl_unlock(b);
 }
@@ -2458,7 +2503,6 @@ retry:
                rcu_read_unlock();
                goto retry;
        }
-       rcu_read_unlock();
        /*
         * No changes for the parent since the beginning of d_lookup().
         * Since all removals from the chain happen with hlist_bl_lock(),
@@ -2471,8 +2515,6 @@ retry:
                        continue;
                if (dentry->d_parent != parent)
                        continue;
-               if (d_unhashed(dentry))
-                       continue;
                if (parent->d_flags & DCACHE_OP_COMPARE) {
                        int tlen = dentry->d_name.len;
                        const char *tname = dentry->d_name.name;
@@ -2484,9 +2526,18 @@ retry:
                        if (dentry_cmp(dentry, str, len))
                                continue;
                }
-               dget(dentry);
                hlist_bl_unlock(b);
-               /* somebody is doing lookup for it right now; wait for it */
+               /* now we can try to grab a reference */
+               if (!lockref_get_not_dead(&dentry->d_lockref)) {
+                       rcu_read_unlock();
+                       goto retry;
+               }
+
+               rcu_read_unlock();
+               /*
+                * somebody is likely to be still doing lookup for it;
+                * wait for them to finish
+                */
                spin_lock(&dentry->d_lock);
                d_wait_lookup(dentry);
                /*
@@ -2517,6 +2568,7 @@ retry:
                dput(new);
                return dentry;
        }
+       rcu_read_unlock();
        /* we can't take ->d_lock here; it's OK, though. */
        new->d_flags |= DCACHE_PAR_LOOKUP;
        new->d_wait = wq;
@@ -2843,6 +2895,7 @@ static void __d_move(struct dentry *dentry, struct dentry *target,
        /* ... and switch them in the tree */
        if (IS_ROOT(dentry)) {
                /* splicing a tree */
+               dentry->d_flags |= DCACHE_RCUACCESS;
                dentry->d_parent = target->d_parent;
                target->d_parent = target;
                list_del_init(&target->d_child);
index 9c1c9a0..592059f 100644 (file)
@@ -127,7 +127,6 @@ static int open_proxy_open(struct inode *inode, struct file *filp)
                r = real_fops->open(inode, filp);
 
 out:
-       fops_put(real_fops);
        debugfs_use_file_finish(srcu_idx);
        return r;
 }
@@ -262,8 +261,10 @@ static int full_proxy_open(struct inode *inode, struct file *filp)
 
        if (real_fops->open) {
                r = real_fops->open(inode, filp);
-
-               if (filp->f_op != proxy_fops) {
+               if (r) {
+                       replace_fops(filp, d_inode(dentry)->i_fop);
+                       goto free_proxy;
+               } else if (filp->f_op != proxy_fops) {
                        /* No protection against file removal anymore. */
                        WARN(1, "debugfs file owner replaced proxy fops: %pd",
                                dentry);
index 0b2954d..37c134a 100644 (file)
@@ -95,8 +95,6 @@ static struct ctl_table pty_root_table[] = {
 
 static DEFINE_MUTEX(allocated_ptys_lock);
 
-static struct vfsmount *devpts_mnt;
-
 struct pts_mount_opts {
        int setuid;
        int setgid;
@@ -104,7 +102,7 @@ struct pts_mount_opts {
        kgid_t   gid;
        umode_t mode;
        umode_t ptmxmode;
-       int newinstance;
+       int reserve;
        int max;
 };
 
@@ -117,11 +115,9 @@ static const match_table_t tokens = {
        {Opt_uid, "uid=%u"},
        {Opt_gid, "gid=%u"},
        {Opt_mode, "mode=%o"},
-#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
        {Opt_ptmxmode, "ptmxmode=%o"},
        {Opt_newinstance, "newinstance"},
        {Opt_max, "max=%d"},
-#endif
        {Opt_err, NULL}
 };
 
@@ -137,15 +133,48 @@ static inline struct pts_fs_info *DEVPTS_SB(struct super_block *sb)
        return sb->s_fs_info;
 }
 
-static inline struct super_block *pts_sb_from_inode(struct inode *inode)
+struct pts_fs_info *devpts_acquire(struct file *filp)
 {
-#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
-       if (inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC)
-               return inode->i_sb;
-#endif
-       if (!devpts_mnt)
-               return NULL;
-       return devpts_mnt->mnt_sb;
+       struct pts_fs_info *result;
+       struct path path;
+       struct super_block *sb;
+       int err;
+
+       path = filp->f_path;
+       path_get(&path);
+
+       /* Has the devpts filesystem already been found? */
+       sb = path.mnt->mnt_sb;
+       if (sb->s_magic != DEVPTS_SUPER_MAGIC) {
+               /* Is a devpts filesystem at "pts" in the same directory? */
+               err = path_pts(&path);
+               if (err) {
+                       result = ERR_PTR(err);
+                       goto out;
+               }
+
+               /* Is the path the root of a devpts filesystem? */
+               result = ERR_PTR(-ENODEV);
+               sb = path.mnt->mnt_sb;
+               if ((sb->s_magic != DEVPTS_SUPER_MAGIC) ||
+                   (path.mnt->mnt_root != sb->s_root))
+                       goto out;
+       }
+
+       /*
+        * pty code needs to hold extra references in case of last /dev/tty close
+        */
+       atomic_inc(&sb->s_active);
+       result = DEVPTS_SB(sb);
+
+out:
+       path_put(&path);
+       return result;
+}
+
+void devpts_release(struct pts_fs_info *fsi)
+{
+       deactivate_super(fsi->sb);
 }
 
 #define PARSE_MOUNT    0
@@ -154,9 +183,7 @@ static inline struct super_block *pts_sb_from_inode(struct inode *inode)
 /*
  * parse_mount_options():
  *     Set @opts to mount options specified in @data. If an option is not
- *     specified in @data, set it to its default value. The exception is
- *     'newinstance' option which can only be set/cleared on a mount (i.e.
- *     cannot be changed during remount).
+ *     specified in @data, set it to its default value.
  *
  * Note: @data may be NULL (in which case all options are set to default).
  */
@@ -174,9 +201,12 @@ static int parse_mount_options(char *data, int op, struct pts_mount_opts *opts)
        opts->ptmxmode = DEVPTS_DEFAULT_PTMX_MODE;
        opts->max     = NR_UNIX98_PTY_MAX;
 
-       /* newinstance makes sense only on initial mount */
+       /* Only allow instances mounted from the initial mount
+        * namespace to tap the reserve pool of ptys.
+        */
        if (op == PARSE_MOUNT)
-               opts->newinstance = 0;
+               opts->reserve =
+                       (current->nsproxy->mnt_ns == init_task.nsproxy->mnt_ns);
 
        while ((p = strsep(&data, ",")) != NULL) {
                substring_t args[MAX_OPT_ARGS];
@@ -211,16 +241,12 @@ static int parse_mount_options(char *data, int op, struct pts_mount_opts *opts)
                                return -EINVAL;
                        opts->mode = option & S_IALLUGO;
                        break;
-#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
                case Opt_ptmxmode:
                        if (match_octal(&args[0], &option))
                                return -EINVAL;
                        opts->ptmxmode = option & S_IALLUGO;
                        break;
                case Opt_newinstance:
-                       /* newinstance makes sense only on initial mount */
-                       if (op == PARSE_MOUNT)
-                               opts->newinstance = 1;
                        break;
                case Opt_max:
                        if (match_int(&args[0], &option) ||
@@ -228,7 +254,6 @@ static int parse_mount_options(char *data, int op, struct pts_mount_opts *opts)
                                return -EINVAL;
                        opts->max = option;
                        break;
-#endif
                default:
                        pr_err("called with bogus options\n");
                        return -EINVAL;
@@ -238,7 +263,6 @@ static int parse_mount_options(char *data, int op, struct pts_mount_opts *opts)
        return 0;
 }
 
-#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
 static int mknod_ptmx(struct super_block *sb)
 {
        int mode;
@@ -305,12 +329,6 @@ static void update_ptmx_mode(struct pts_fs_info *fsi)
                inode->i_mode = S_IFCHR|fsi->mount_opts.ptmxmode;
        }
 }
-#else
-static inline void update_ptmx_mode(struct pts_fs_info *fsi)
-{
-       return;
-}
-#endif
 
 static int devpts_remount(struct super_block *sb, int *flags, char *data)
 {
@@ -344,11 +362,9 @@ static int devpts_show_options(struct seq_file *seq, struct dentry *root)
                seq_printf(seq, ",gid=%u",
                           from_kgid_munged(&init_user_ns, opts->gid));
        seq_printf(seq, ",mode=%03o", opts->mode);
-#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
        seq_printf(seq, ",ptmxmode=%03o", opts->ptmxmode);
        if (opts->max < NR_UNIX98_PTY_MAX)
                seq_printf(seq, ",max=%d", opts->max);
-#endif
 
        return 0;
 }
@@ -410,40 +426,11 @@ fail:
        return -ENOMEM;
 }
 
-#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
-static int compare_init_pts_sb(struct super_block *s, void *p)
-{
-       if (devpts_mnt)
-               return devpts_mnt->mnt_sb == s;
-       return 0;
-}
-
 /*
  * devpts_mount()
  *
- *     If the '-o newinstance' mount option was specified, mount a new
- *     (private) instance of devpts.  PTYs created in this instance are
- *     independent of the PTYs in other devpts instances.
- *
- *     If the '-o newinstance' option was not specified, mount/remount the
- *     initial kernel mount of devpts.  This type of mount gives the
- *     legacy, single-instance semantics.
- *
- *     The 'newinstance' option is needed to support multiple namespace
- *     semantics in devpts while preserving backward compatibility of the
- *     current 'single-namespace' semantics. i.e all mounts of devpts
- *     without the 'newinstance' mount option should bind to the initial
- *     kernel mount, like mount_single().
- *
- *     Mounts with 'newinstance' option create a new, private namespace.
- *
- *     NOTE:
- *
- *     For single-mount semantics, devpts cannot use mount_single(),
- *     because mount_single()/sget() find and use the super-block from
- *     the most recent mount of devpts. But that recent mount may be a
- *     'newinstance' mount and mount_single() would pick the newinstance
- *     super-block instead of the initial super-block.
+ *     Mount a new (private) instance of devpts.  PTYs created in this
+ *     instance are independent of the PTYs in other devpts instances.
  */
 static struct dentry *devpts_mount(struct file_system_type *fs_type,
        int flags, const char *dev_name, void *data)
@@ -456,18 +443,7 @@ static struct dentry *devpts_mount(struct file_system_type *fs_type,
        if (error)
                return ERR_PTR(error);
 
-       /* Require newinstance for all user namespace mounts to ensure
-        * the mount options are not changed.
-        */
-       if ((current_user_ns() != &init_user_ns) && !opts.newinstance)
-               return ERR_PTR(-EINVAL);
-
-       if (opts.newinstance)
-               s = sget(fs_type, NULL, set_anon_super, flags, NULL);
-       else
-               s = sget(fs_type, compare_init_pts_sb, set_anon_super, flags,
-                        NULL);
-
+       s = sget(fs_type, NULL, set_anon_super, flags, NULL);
        if (IS_ERR(s))
                return ERR_CAST(s);
 
@@ -491,18 +467,6 @@ out_undo_sget:
        return ERR_PTR(error);
 }
 
-#else
-/*
- * This supports only the legacy single-instance semantics (no
- * multiple-instance semantics)
- */
-static struct dentry *devpts_mount(struct file_system_type *fs_type, int flags,
-               const char *dev_name, void *data)
-{
-       return mount_single(fs_type, flags, data, devpts_fill_super);
-}
-#endif
-
 static void devpts_kill_sb(struct super_block *sb)
 {
        struct pts_fs_info *fsi = DEVPTS_SB(sb);
@@ -516,9 +480,7 @@ static struct file_system_type devpts_fs_type = {
        .name           = "devpts",
        .mount          = devpts_mount,
        .kill_sb        = devpts_kill_sb,
-#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
        .fs_flags       = FS_USERNS_MOUNT | FS_USERNS_DEV_MOUNT,
-#endif
 };
 
 /*
@@ -531,16 +493,13 @@ int devpts_new_index(struct pts_fs_info *fsi)
        int index;
        int ida_ret;
 
-       if (!fsi)
-               return -ENODEV;
-
 retry:
        if (!ida_pre_get(&fsi->allocated_ptys, GFP_KERNEL))
                return -ENOMEM;
 
        mutex_lock(&allocated_ptys_lock);
-       if (pty_count >= pty_limit -
-                       (fsi->mount_opts.newinstance ? pty_reserve : 0)) {
+       if (pty_count >= (pty_limit -
+                         (fsi->mount_opts.reserve ? 0 : pty_reserve))) {
                mutex_unlock(&allocated_ptys_lock);
                return -ENOSPC;
        }
@@ -571,30 +530,6 @@ void devpts_kill_index(struct pts_fs_info *fsi, int idx)
        mutex_unlock(&allocated_ptys_lock);
 }
 
-/*
- * pty code needs to hold extra references in case of last /dev/tty close
- */
-struct pts_fs_info *devpts_get_ref(struct inode *ptmx_inode, struct file *file)
-{
-       struct super_block *sb;
-       struct pts_fs_info *fsi;
-
-       sb = pts_sb_from_inode(ptmx_inode);
-       if (!sb)
-               return NULL;
-       fsi = DEVPTS_SB(sb);
-       if (!fsi)
-               return NULL;
-
-       atomic_inc(&sb->s_active);
-       return fsi;
-}
-
-void devpts_put_ref(struct pts_fs_info *fsi)
-{
-       deactivate_super(fsi->sb);
-}
-
 /**
  * devpts_pty_new -- create a new inode in /dev/pts/
  * @ptmx_inode: inode of the master
@@ -607,16 +542,12 @@ void devpts_put_ref(struct pts_fs_info *fsi)
 struct dentry *devpts_pty_new(struct pts_fs_info *fsi, int index, void *priv)
 {
        struct dentry *dentry;
-       struct super_block *sb;
+       struct super_block *sb = fsi->sb;
        struct inode *inode;
        struct dentry *root;
        struct pts_mount_opts *opts;
        char s[12];
 
-       if (!fsi)
-               return ERR_PTR(-ENODEV);
-
-       sb = fsi->sb;
        root = sb->s_root;
        opts = &fsi->mount_opts;
 
@@ -676,20 +607,8 @@ void devpts_pty_kill(struct dentry *dentry)
 static int __init init_devpts_fs(void)
 {
        int err = register_filesystem(&devpts_fs_type);
-       struct ctl_table_header *table;
-
        if (!err) {
-               struct vfsmount *mnt;
-
-               table = register_sysctl_table(pty_root_table);
-               mnt = kern_mount(&devpts_fs_type);
-               if (IS_ERR(mnt)) {
-                       err = PTR_ERR(mnt);
-                       unregister_filesystem(&devpts_fs_type);
-                       unregister_sysctl_table(table);
-               } else {
-                       devpts_mnt = mnt;
-               }
+               register_sysctl_table(pty_root_table);
        }
        return err;
 }
index 866bb18..e818f5a 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/slab.h>
 #include <linux/wait.h>
 #include <linux/mount.h>
+#include <linux/file.h>
 #include "ecryptfs_kernel.h"
 
 struct ecryptfs_open_req {
@@ -147,7 +148,7 @@ int ecryptfs_privileged_open(struct file **lower_file,
        flags |= IS_RDONLY(d_inode(lower_dentry)) ? O_RDONLY : O_RDWR;
        (*lower_file) = dentry_open(&req.path, flags, cred);
        if (!IS_ERR(*lower_file))
-               goto out;
+               goto have_file;
        if ((flags & O_ACCMODE) == O_RDONLY) {
                rc = PTR_ERR((*lower_file));
                goto out;
@@ -165,8 +166,16 @@ int ecryptfs_privileged_open(struct file **lower_file,
        mutex_unlock(&ecryptfs_kthread_ctl.mux);
        wake_up(&ecryptfs_kthread_ctl.wait);
        wait_for_completion(&req.done);
-       if (IS_ERR(*lower_file))
+       if (IS_ERR(*lower_file)) {
                rc = PTR_ERR(*lower_file);
+               goto out;
+       }
+have_file:
+       if ((*lower_file)->f_op->mmap == NULL) {
+               fput(*lower_file);
+               *lower_file = NULL;
+               rc = -EMEDIUMTYPE;
+       }
 out:
        return rc;
 }
index 3078b67..c8c4f79 100644 (file)
@@ -887,6 +887,8 @@ void fscache_invalidate_writes(struct fscache_cookie *cookie)
                        put_page(results[i]);
        }
 
+       wake_up_bit(&cookie->flags, 0);
+
        _leave("");
 }
 
index b71deee..f57ced5 100644 (file)
@@ -130,6 +130,7 @@ extern int invalidate_inodes(struct super_block *, bool);
 extern struct dentry *__d_alloc(struct super_block *, const struct qstr *);
 extern int d_set_mounted(struct dentry *dentry);
 extern long prune_dcache_sb(struct super_block *sb, struct shrink_control *sc);
+extern struct dentry *d_alloc_cursor(struct dentry *);
 
 /*
  * read_write.c
index b31852f..e3ca4b4 100644 (file)
@@ -2329,18 +2329,10 @@ void *jbd2_alloc(size_t size, gfp_t flags)
 
        BUG_ON(size & (size-1)); /* Must be a power of 2 */
 
-       flags |= __GFP_REPEAT;
-       if (size == PAGE_SIZE)
-               ptr = (void *)__get_free_pages(flags, 0);
-       else if (size > PAGE_SIZE) {
-               int order = get_order(size);
-
-               if (order < 3)
-                       ptr = (void *)__get_free_pages(flags, order);
-               else
-                       ptr = vmalloc(size);
-       } else
+       if (size < PAGE_SIZE)
                ptr = kmem_cache_alloc(get_slab(size), flags);
+       else
+               ptr = (void *)__get_free_pages(flags, get_order(size));
 
        /* Check alignment; SLUB has gotten this wrong in the past,
         * and this can lead to user data corruption! */
@@ -2351,20 +2343,10 @@ void *jbd2_alloc(size_t size, gfp_t flags)
 
 void jbd2_free(void *ptr, size_t size)
 {
-       if (size == PAGE_SIZE) {
-               free_pages((unsigned long)ptr, 0);
-               return;
-       }
-       if (size > PAGE_SIZE) {
-               int order = get_order(size);
-
-               if (order < 3)
-                       free_pages((unsigned long)ptr, order);
-               else
-                       vfree(ptr);
-               return;
-       }
-       kmem_cache_free(get_slab(size), ptr);
+       if (size < PAGE_SIZE)
+               kmem_cache_free(get_slab(size), ptr);
+       else
+               free_pages((unsigned long)ptr, get_order(size));
 };
 
 /*
index 3db2721..cedeacb 100644 (file)
@@ -71,9 +71,7 @@ EXPORT_SYMBOL(simple_lookup);
 
 int dcache_dir_open(struct inode *inode, struct file *file)
 {
-       static struct qstr cursor_name = QSTR_INIT(".", 1);
-
-       file->private_data = d_alloc(file->f_path.dentry, &cursor_name);
+       file->private_data = d_alloc_cursor(file->f_path.dentry);
 
        return file->private_data ? 0 : -ENOMEM;
 }
index 4c4f95a..70580ab 100644 (file)
@@ -1416,21 +1416,28 @@ static void follow_mount(struct path *path)
        }
 }
 
+static int path_parent_directory(struct path *path)
+{
+       struct dentry *old = path->dentry;
+       /* rare case of legitimate dget_parent()... */
+       path->dentry = dget_parent(path->dentry);
+       dput(old);
+       if (unlikely(!path_connected(path)))
+               return -ENOENT;
+       return 0;
+}
+
 static int follow_dotdot(struct nameidata *nd)
 {
        while(1) {
-               struct dentry *old = nd->path.dentry;
-
                if (nd->path.dentry == nd->root.dentry &&
                    nd->path.mnt == nd->root.mnt) {
                        break;
                }
                if (nd->path.dentry != nd->path.mnt->mnt_root) {
-                       /* rare case of legitimate dget_parent()... */
-                       nd->path.dentry = dget_parent(nd->path.dentry);
-                       dput(old);
-                       if (unlikely(!path_connected(&nd->path)))
-                               return -ENOENT;
+                       int ret = path_parent_directory(&nd->path);
+                       if (ret)
+                               return ret;
                        break;
                }
                if (!follow_up(&nd->path))
@@ -2514,6 +2521,34 @@ struct dentry *lookup_one_len_unlocked(const char *name,
 }
 EXPORT_SYMBOL(lookup_one_len_unlocked);
 
+#ifdef CONFIG_UNIX98_PTYS
+int path_pts(struct path *path)
+{
+       /* Find something mounted on "pts" in the same directory as
+        * the input path.
+        */
+       struct dentry *child, *parent;
+       struct qstr this;
+       int ret;
+
+       ret = path_parent_directory(path);
+       if (ret)
+               return ret;
+
+       parent = path->dentry;
+       this.name = "pts";
+       this.len = 3;
+       child = d_hash_and_lookup(parent, &this);
+       if (!child)
+               return -ENOENT;
+
+       path->dentry = child;
+       dput(parent);
+       follow_mount(path);
+       return 0;
+}
+#endif
+
 int user_path_at_empty(int dfd, const char __user *name, unsigned flags,
                 struct path *path, int *empty)
 {
@@ -2995,9 +3030,13 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry,
                        }
                        if (*opened & FILE_CREATED)
                                fsnotify_create(dir, dentry);
-                       path->dentry = dentry;
-                       path->mnt = nd->path.mnt;
-                       return 1;
+                       if (unlikely(d_is_negative(dentry))) {
+                               error = -ENOENT;
+                       } else {
+                               path->dentry = dentry;
+                               path->mnt = nd->path.mnt;
+                               return 1;
+                       }
                }
        }
        dput(dentry);
@@ -3166,9 +3205,7 @@ static int do_last(struct nameidata *nd,
        int acc_mode = op->acc_mode;
        unsigned seq;
        struct inode *inode;
-       struct path save_parent = { .dentry = NULL, .mnt = NULL };
        struct path path;
-       bool retried = false;
        int error;
 
        nd->flags &= ~LOOKUP_PARENT;
@@ -3211,7 +3248,6 @@ static int do_last(struct nameidata *nd,
                        return -EISDIR;
        }
 
-retry_lookup:
        if (open_flag & (O_CREAT | O_TRUNC | O_WRONLY | O_RDWR)) {
                error = mnt_want_write(nd->path.mnt);
                if (!error)
@@ -3263,6 +3299,10 @@ retry_lookup:
                got_write = false;
        }
 
+       error = follow_managed(&path, nd);
+       if (unlikely(error < 0))
+               return error;
+
        if (unlikely(d_is_negative(path.dentry))) {
                path_to_nameidata(&path, nd);
                return -ENOENT;
@@ -3278,10 +3318,6 @@ retry_lookup:
                return -EEXIST;
        }
 
-       error = follow_managed(&path, nd);
-       if (unlikely(error < 0))
-               return error;
-
        seq = 0;        /* out of RCU mode, so the value doesn't matter */
        inode = d_backing_inode(path.dentry);
 finish_lookup:
@@ -3292,23 +3328,14 @@ finish_lookup:
        if (unlikely(error))
                return error;
 
-       if ((nd->flags & LOOKUP_RCU) || nd->path.mnt != path.mnt) {
-               path_to_nameidata(&path, nd);
-       } else {
-               save_parent.dentry = nd->path.dentry;
-               save_parent.mnt = mntget(path.mnt);
-               nd->path.dentry = path.dentry;
-
-       }
+       path_to_nameidata(&path, nd);
        nd->inode = inode;
        nd->seq = seq;
        /* Why this, you ask?  _Now_ we might have grown LOOKUP_JUMPED... */
 finish_open:
        error = complete_walk(nd);
-       if (error) {
-               path_put(&save_parent);
+       if (error)
                return error;
-       }
        audit_inode(nd->name, nd->path.dentry, 0);
        error = -EISDIR;
        if ((open_flag & O_CREAT) && d_is_dir(nd->path.dentry))
@@ -3331,13 +3358,9 @@ finish_open_created:
                goto out;
        BUG_ON(*opened & FILE_OPENED); /* once it's opened, it's opened */
        error = vfs_open(&nd->path, file, current_cred());
-       if (!error) {
-               *opened |= FILE_OPENED;
-       } else {
-               if (error == -EOPENSTALE)
-                       goto stale_open;
+       if (error)
                goto out;
-       }
+       *opened |= FILE_OPENED;
 opened:
        error = open_check_o_direct(file);
        if (!error)
@@ -3353,26 +3376,7 @@ out:
        }
        if (got_write)
                mnt_drop_write(nd->path.mnt);
-       path_put(&save_parent);
        return error;
-
-stale_open:
-       /* If no saved parent or already retried then can't retry */
-       if (!save_parent.dentry || retried)
-               goto out;
-
-       BUG_ON(save_parent.dentry != dir);
-       path_put(&nd->path);
-       nd->path = save_parent;
-       nd->inode = dir->d_inode;
-       save_parent.mnt = NULL;
-       save_parent.dentry = NULL;
-       if (got_write) {
-               mnt_drop_write(nd->path.mnt);
-               got_write = false;
-       }
-       retried = true;
-       goto retry_lookup;
 }
 
 static int do_tmpfile(struct nameidata *nd, unsigned flags,
index 4fb1691..783004a 100644 (file)
@@ -2409,8 +2409,10 @@ static int do_new_mount(struct path *path, const char *fstype, int flags,
                        mnt_flags |= MNT_NODEV | MNT_LOCK_NODEV;
                }
                if (type->fs_flags & FS_USERNS_VISIBLE) {
-                       if (!fs_fully_visible(type, &mnt_flags))
+                       if (!fs_fully_visible(type, &mnt_flags)) {
+                               put_filesystem(type);
                                return -EPERM;
+                       }
                }
        }
 
@@ -3245,6 +3247,10 @@ static bool fs_fully_visible(struct file_system_type *type, int *new_mnt_flags)
                if (mnt->mnt.mnt_sb->s_iflags & SB_I_NOEXEC)
                        mnt_flags &= ~(MNT_LOCK_NOSUID | MNT_LOCK_NOEXEC);
 
+               /* Don't miss readonly hidden in the superblock flags */
+               if (mnt->mnt.mnt_sb->s_flags & MS_RDONLY)
+                       mnt_flags |= MNT_LOCK_READONLY;
+
                /* Verify the mount flags are equal to or more permissive
                 * than the proposed new mount.
                 */
@@ -3271,7 +3277,7 @@ static bool fs_fully_visible(struct file_system_type *type, int *new_mnt_flags)
                list_for_each_entry(child, &mnt->mnt_mounts, mnt_child) {
                        struct inode *inode = child->mnt_mountpoint->d_inode;
                        /* Only worry about locked mounts */
-                       if (!(mnt_flags & MNT_LOCKED))
+                       if (!(child->mnt.mnt_flags & MNT_LOCKED))
                                continue;
                        /* Is the directory permanetly empty? */
                        if (!is_empty_dir_inode(inode))
index e55b524..31f3df1 100644 (file)
@@ -290,7 +290,7 @@ out_free_buf:
        return error;
 }
 
-#define NFSD_MDS_PR_KEY                0x0100000000000000
+#define NFSD_MDS_PR_KEY                0x0100000000000000ULL
 
 /*
  * We use the client ID as a unique key for the reservations.
index 1580ea6..d08cd88 100644 (file)
@@ -104,22 +104,21 @@ static __be32 nfsacld_proc_setacl(struct svc_rqst * rqstp,
                goto out;
 
        inode = d_inode(fh->fh_dentry);
-       if (!IS_POSIXACL(inode) || !inode->i_op->set_acl) {
-               error = -EOPNOTSUPP;
-               goto out_errno;
-       }
 
        error = fh_want_write(fh);
        if (error)
                goto out_errno;
 
-       error = inode->i_op->set_acl(inode, argp->acl_access, ACL_TYPE_ACCESS);
+       fh_lock(fh);
+
+       error = set_posix_acl(inode, ACL_TYPE_ACCESS, argp->acl_access);
        if (error)
-               goto out_drop_write;
-       error = inode->i_op->set_acl(inode, argp->acl_default,
-                                    ACL_TYPE_DEFAULT);
+               goto out_drop_lock;
+       error = set_posix_acl(inode, ACL_TYPE_DEFAULT, argp->acl_default);
        if (error)
-               goto out_drop_write;
+               goto out_drop_lock;
+
+       fh_unlock(fh);
 
        fh_drop_write(fh);
 
@@ -131,7 +130,8 @@ out:
        posix_acl_release(argp->acl_access);
        posix_acl_release(argp->acl_default);
        return nfserr;
-out_drop_write:
+out_drop_lock:
+       fh_unlock(fh);
        fh_drop_write(fh);
 out_errno:
        nfserr = nfserrno(error);
index 01df4cd..0c89034 100644 (file)
@@ -95,22 +95,20 @@ static __be32 nfsd3_proc_setacl(struct svc_rqst * rqstp,
                goto out;
 
        inode = d_inode(fh->fh_dentry);
-       if (!IS_POSIXACL(inode) || !inode->i_op->set_acl) {
-               error = -EOPNOTSUPP;
-               goto out_errno;
-       }
 
        error = fh_want_write(fh);
        if (error)
                goto out_errno;
 
-       error = inode->i_op->set_acl(inode, argp->acl_access, ACL_TYPE_ACCESS);
+       fh_lock(fh);
+
+       error = set_posix_acl(inode, ACL_TYPE_ACCESS, argp->acl_access);
        if (error)
-               goto out_drop_write;
-       error = inode->i_op->set_acl(inode, argp->acl_default,
-                                    ACL_TYPE_DEFAULT);
+               goto out_drop_lock;
+       error = set_posix_acl(inode, ACL_TYPE_DEFAULT, argp->acl_default);
 
-out_drop_write:
+out_drop_lock:
+       fh_unlock(fh);
        fh_drop_write(fh);
 out_errno:
        nfserr = nfserrno(error);
index 6adabd6..71292a0 100644 (file)
@@ -770,9 +770,6 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
        dentry = fhp->fh_dentry;
        inode = d_inode(dentry);
 
-       if (!inode->i_op->set_acl || !IS_POSIXACL(inode))
-               return nfserr_attrnotsupp;
-
        if (S_ISDIR(inode->i_mode))
                flags = NFS4_ACL_DIR;
 
@@ -782,16 +779,19 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
        if (host_error < 0)
                goto out_nfserr;
 
-       host_error = inode->i_op->set_acl(inode, pacl, ACL_TYPE_ACCESS);
+       fh_lock(fhp);
+
+       host_error = set_posix_acl(inode, ACL_TYPE_ACCESS, pacl);
        if (host_error < 0)
-               goto out_release;
+               goto out_drop_lock;
 
        if (S_ISDIR(inode->i_mode)) {
-               host_error = inode->i_op->set_acl(inode, dpacl,
-                                                 ACL_TYPE_DEFAULT);
+               host_error = set_posix_acl(inode, ACL_TYPE_DEFAULT, dpacl);
        }
 
-out_release:
+out_drop_lock:
+       fh_unlock(fhp);
+
        posix_acl_release(pacl);
        posix_acl_release(dpacl);
 out_nfserr:
index 7389cb1..04c68d9 100644 (file)
@@ -710,22 +710,6 @@ static struct rpc_cred *get_backchannel_cred(struct nfs4_client *clp, struct rpc
        }
 }
 
-static struct rpc_clnt *create_backchannel_client(struct rpc_create_args *args)
-{
-       struct rpc_xprt *xprt;
-
-       if (args->protocol != XPRT_TRANSPORT_BC_TCP)
-               return rpc_create(args);
-
-       xprt = args->bc_xprt->xpt_bc_xprt;
-       if (xprt) {
-               xprt_get(xprt);
-               return rpc_create_xprt(args, xprt);
-       }
-
-       return rpc_create(args);
-}
-
 static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn, struct nfsd4_session *ses)
 {
        int maxtime = max_cb_time(clp->net);
@@ -768,7 +752,7 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c
                args.authflavor = ses->se_cb_sec.flavor;
        }
        /* Create RPC client */
-       client = create_backchannel_client(&args);
+       client = rpc_create(&args);
        if (IS_ERR(client)) {
                dprintk("NFSD: couldn't create callback client: %ld\n",
                        PTR_ERR(client));
index f5f82e1..70d0b9b 100644 (file)
@@ -3480,12 +3480,17 @@ alloc_init_open_stateowner(unsigned int strhashval, struct nfsd4_open *open,
 }
 
 static struct nfs4_ol_stateid *
-init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp,
-               struct nfsd4_open *open)
+init_open_stateid(struct nfs4_file *fp, struct nfsd4_open *open)
 {
 
        struct nfs4_openowner *oo = open->op_openowner;
        struct nfs4_ol_stateid *retstp = NULL;
+       struct nfs4_ol_stateid *stp;
+
+       stp = open->op_stp;
+       /* We are moving these outside of the spinlocks to avoid the warnings */
+       mutex_init(&stp->st_mutex);
+       mutex_lock(&stp->st_mutex);
 
        spin_lock(&oo->oo_owner.so_client->cl_lock);
        spin_lock(&fp->fi_lock);
@@ -3493,6 +3498,8 @@ init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp,
        retstp = nfsd4_find_existing_open(fp, open);
        if (retstp)
                goto out_unlock;
+
+       open->op_stp = NULL;
        atomic_inc(&stp->st_stid.sc_count);
        stp->st_stid.sc_type = NFS4_OPEN_STID;
        INIT_LIST_HEAD(&stp->st_locks);
@@ -3502,14 +3509,19 @@ init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp,
        stp->st_access_bmap = 0;
        stp->st_deny_bmap = 0;
        stp->st_openstp = NULL;
-       init_rwsem(&stp->st_rwsem);
        list_add(&stp->st_perstateowner, &oo->oo_owner.so_stateids);
        list_add(&stp->st_perfile, &fp->fi_stateids);
 
 out_unlock:
        spin_unlock(&fp->fi_lock);
        spin_unlock(&oo->oo_owner.so_client->cl_lock);
-       return retstp;
+       if (retstp) {
+               mutex_lock(&retstp->st_mutex);
+               /* To keep mutex tracking happy */
+               mutex_unlock(&stp->st_mutex);
+               stp = retstp;
+       }
+       return stp;
 }
 
 /*
@@ -4305,7 +4317,6 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
        struct nfs4_client *cl = open->op_openowner->oo_owner.so_client;
        struct nfs4_file *fp = NULL;
        struct nfs4_ol_stateid *stp = NULL;
-       struct nfs4_ol_stateid *swapstp = NULL;
        struct nfs4_delegation *dp = NULL;
        __be32 status;
 
@@ -4335,32 +4346,28 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
         */
        if (stp) {
                /* Stateid was found, this is an OPEN upgrade */
-               down_read(&stp->st_rwsem);
+               mutex_lock(&stp->st_mutex);
                status = nfs4_upgrade_open(rqstp, fp, current_fh, stp, open);
                if (status) {
-                       up_read(&stp->st_rwsem);
+                       mutex_unlock(&stp->st_mutex);
                        goto out;
                }
        } else {
-               stp = open->op_stp;
-               open->op_stp = NULL;
-               swapstp = init_open_stateid(stp, fp, open);
-               if (swapstp) {
-                       nfs4_put_stid(&stp->st_stid);
-                       stp = swapstp;
-                       down_read(&stp->st_rwsem);
+               /* stp is returned locked. */
+               stp = init_open_stateid(fp, open);
+               /* See if we lost the race to some other thread */
+               if (stp->st_access_bmap != 0) {
                        status = nfs4_upgrade_open(rqstp, fp, current_fh,
                                                stp, open);
                        if (status) {
-                               up_read(&stp->st_rwsem);
+                               mutex_unlock(&stp->st_mutex);
                                goto out;
                        }
                        goto upgrade_out;
                }
-               down_read(&stp->st_rwsem);
                status = nfs4_get_vfs_file(rqstp, fp, current_fh, stp, open);
                if (status) {
-                       up_read(&stp->st_rwsem);
+                       mutex_unlock(&stp->st_mutex);
                        release_open_stateid(stp);
                        goto out;
                }
@@ -4372,7 +4379,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
        }
 upgrade_out:
        nfs4_inc_and_copy_stateid(&open->op_stateid, &stp->st_stid);
-       up_read(&stp->st_rwsem);
+       mutex_unlock(&stp->st_mutex);
 
        if (nfsd4_has_session(&resp->cstate)) {
                if (open->op_deleg_want & NFS4_SHARE_WANT_NO_DELEG) {
@@ -4977,12 +4984,12 @@ static __be32 nfs4_seqid_op_checks(struct nfsd4_compound_state *cstate, stateid_
                 * revoked delegations are kept only for free_stateid.
                 */
                return nfserr_bad_stateid;
-       down_write(&stp->st_rwsem);
+       mutex_lock(&stp->st_mutex);
        status = check_stateid_generation(stateid, &stp->st_stid.sc_stateid, nfsd4_has_session(cstate));
        if (status == nfs_ok)
                status = nfs4_check_fh(current_fh, &stp->st_stid);
        if (status != nfs_ok)
-               up_write(&stp->st_rwsem);
+               mutex_unlock(&stp->st_mutex);
        return status;
 }
 
@@ -5030,7 +5037,7 @@ static __be32 nfs4_preprocess_confirmed_seqid_op(struct nfsd4_compound_state *cs
                return status;
        oo = openowner(stp->st_stateowner);
        if (!(oo->oo_flags & NFS4_OO_CONFIRMED)) {
-               up_write(&stp->st_rwsem);
+               mutex_unlock(&stp->st_mutex);
                nfs4_put_stid(&stp->st_stid);
                return nfserr_bad_stateid;
        }
@@ -5062,12 +5069,12 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        oo = openowner(stp->st_stateowner);
        status = nfserr_bad_stateid;
        if (oo->oo_flags & NFS4_OO_CONFIRMED) {
-               up_write(&stp->st_rwsem);
+               mutex_unlock(&stp->st_mutex);
                goto put_stateid;
        }
        oo->oo_flags |= NFS4_OO_CONFIRMED;
        nfs4_inc_and_copy_stateid(&oc->oc_resp_stateid, &stp->st_stid);
-       up_write(&stp->st_rwsem);
+       mutex_unlock(&stp->st_mutex);
        dprintk("NFSD: %s: success, seqid=%d stateid=" STATEID_FMT "\n",
                __func__, oc->oc_seqid, STATEID_VAL(&stp->st_stid.sc_stateid));
 
@@ -5143,7 +5150,7 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp,
        nfs4_inc_and_copy_stateid(&od->od_stateid, &stp->st_stid);
        status = nfs_ok;
 put_stateid:
-       up_write(&stp->st_rwsem);
+       mutex_unlock(&stp->st_mutex);
        nfs4_put_stid(&stp->st_stid);
 out:
        nfsd4_bump_seqid(cstate, status);
@@ -5196,7 +5203,7 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        if (status)
                goto out; 
        nfs4_inc_and_copy_stateid(&close->cl_stateid, &stp->st_stid);
-       up_write(&stp->st_rwsem);
+       mutex_unlock(&stp->st_mutex);
 
        nfsd4_close_open_stateid(stp);
 
@@ -5422,7 +5429,7 @@ init_lock_stateid(struct nfs4_ol_stateid *stp, struct nfs4_lockowner *lo,
        stp->st_access_bmap = 0;
        stp->st_deny_bmap = open_stp->st_deny_bmap;
        stp->st_openstp = open_stp;
-       init_rwsem(&stp->st_rwsem);
+       mutex_init(&stp->st_mutex);
        list_add(&stp->st_locks, &open_stp->st_locks);
        list_add(&stp->st_perstateowner, &lo->lo_owner.so_stateids);
        spin_lock(&fp->fi_lock);
@@ -5591,7 +5598,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                                        &open_stp, nn);
                if (status)
                        goto out;
-               up_write(&open_stp->st_rwsem);
+               mutex_unlock(&open_stp->st_mutex);
                open_sop = openowner(open_stp->st_stateowner);
                status = nfserr_bad_stateid;
                if (!same_clid(&open_sop->oo_owner.so_client->cl_clientid,
@@ -5600,7 +5607,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                status = lookup_or_create_lock_state(cstate, open_stp, lock,
                                                        &lock_stp, &new);
                if (status == nfs_ok)
-                       down_write(&lock_stp->st_rwsem);
+                       mutex_lock(&lock_stp->st_mutex);
        } else {
                status = nfs4_preprocess_seqid_op(cstate,
                                       lock->lk_old_lock_seqid,
@@ -5704,7 +5711,7 @@ out:
                    seqid_mutating_err(ntohl(status)))
                        lock_sop->lo_owner.so_seqid++;
 
-               up_write(&lock_stp->st_rwsem);
+               mutex_unlock(&lock_stp->st_mutex);
 
                /*
                 * If this is a new, never-before-used stateid, and we are
@@ -5874,7 +5881,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 fput:
        fput(filp);
 put_stateid:
-       up_write(&stp->st_rwsem);
+       mutex_unlock(&stp->st_mutex);
        nfs4_put_stid(&stp->st_stid);
 out:
        nfsd4_bump_seqid(cstate, status);
index 986e51e..64053ea 100644 (file)
@@ -535,7 +535,7 @@ struct nfs4_ol_stateid {
        unsigned char                   st_access_bmap;
        unsigned char                   st_deny_bmap;
        struct nfs4_ol_stateid          *st_openstp;
-       struct rw_semaphore             st_rwsem;
+       struct mutex                    st_mutex;
 };
 
 static inline struct nfs4_ol_stateid *openlockstateid(struct nfs4_stid *s)
index 809bd2d..e9fd241 100644 (file)
@@ -439,7 +439,7 @@ static int nilfs_valid_sb(struct nilfs_super_block *sbp)
        if (!sbp || le16_to_cpu(sbp->s_magic) != NILFS_SUPER_MAGIC)
                return 0;
        bytes = le16_to_cpu(sbp->s_bytes);
-       if (bytes > BLOCK_SIZE)
+       if (bytes < sumoff + 4 || bytes > BLOCK_SIZE)
                return 0;
        crc = crc32_le(le32_to_cpu(sbp->s_crc_seed), (unsigned char *)sbp,
                       sumoff);
index e27e652..4342c7e 100644 (file)
@@ -1,7 +1,5 @@
 ccflags-y := -Ifs/ocfs2
 
-ccflags-y += -DCATCH_BH_JBD_RACES
-
 obj-$(CONFIG_OCFS2_FS) +=      \
        ocfs2.o                 \
        ocfs2_stackglue.o
index fe50ded..498641e 100644 (file)
@@ -139,11 +139,16 @@ int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block,
 
                lock_buffer(bh);
                if (buffer_jbd(bh)) {
+#ifdef CATCH_BH_JBD_RACES
                        mlog(ML_ERROR,
                             "block %llu had the JBD bit set "
                             "while I was in lock_buffer!",
                             (unsigned long long)bh->b_blocknr);
                        BUG();
+#else
+                       unlock_buffer(bh);
+                       continue;
+#endif
                }
 
                clear_buffer_uptodate(bh);
index 22f0253..c2a6b08 100644 (file)
@@ -405,12 +405,21 @@ static int ovl_create_or_link(struct dentry *dentry, int mode, dev_t rdev,
                err = ovl_create_upper(dentry, inode, &stat, link, hardlink);
        } else {
                const struct cred *old_cred;
+               struct cred *override_cred;
 
                old_cred = ovl_override_creds(dentry->d_sb);
 
-               err = ovl_create_over_whiteout(dentry, inode, &stat, link,
-                                              hardlink);
+               err = -ENOMEM;
+               override_cred = prepare_creds();
+               if (override_cred) {
+                       override_cred->fsuid = old_cred->fsuid;
+                       override_cred->fsgid = old_cred->fsgid;
+                       put_cred(override_creds(override_cred));
+                       put_cred(override_cred);
 
+                       err = ovl_create_over_whiteout(dentry, inode, &stat,
+                                                      link, hardlink);
+               }
                revert_creds(old_cred);
        }
 
index 0ed7c40..1dbeab6 100644 (file)
@@ -238,41 +238,27 @@ out:
        return err;
 }
 
-static bool ovl_need_xattr_filter(struct dentry *dentry,
-                                 enum ovl_path_type type)
-{
-       if ((type & (__OVL_PATH_PURE | __OVL_PATH_UPPER)) == __OVL_PATH_UPPER)
-               return S_ISDIR(dentry->d_inode->i_mode);
-       else
-               return false;
-}
-
 ssize_t ovl_getxattr(struct dentry *dentry, struct inode *inode,
                     const char *name, void *value, size_t size)
 {
-       struct path realpath;
-       enum ovl_path_type type = ovl_path_real(dentry, &realpath);
+       struct dentry *realdentry = ovl_dentry_real(dentry);
 
-       if (ovl_need_xattr_filter(dentry, type) && ovl_is_private_xattr(name))
+       if (ovl_is_private_xattr(name))
                return -ENODATA;
 
-       return vfs_getxattr(realpath.dentry, name, value, size);
+       return vfs_getxattr(realdentry, name, value, size);
 }
 
 ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size)
 {
-       struct path realpath;
-       enum ovl_path_type type = ovl_path_real(dentry, &realpath);
+       struct dentry *realdentry = ovl_dentry_real(dentry);
        ssize_t res;
        int off;
 
-       res = vfs_listxattr(realpath.dentry, list, size);
+       res = vfs_listxattr(realdentry, list, size);
        if (res <= 0 || size == 0)
                return res;
 
-       if (!ovl_need_xattr_filter(dentry, type))
-               return res;
-
        /* filter out private xattrs */
        for (off = 0; off < res;) {
                char *s = list + off;
@@ -302,7 +288,7 @@ int ovl_removexattr(struct dentry *dentry, const char *name)
                goto out;
 
        err = -ENODATA;
-       if (ovl_need_xattr_filter(dentry, type) && ovl_is_private_xattr(name))
+       if (ovl_is_private_xattr(name))
                goto out_drop_write;
 
        if (!OVL_TYPE_UPPER(type)) {
index 8a4a266..edc452c 100644 (file)
@@ -820,39 +820,43 @@ posix_acl_xattr_get(const struct xattr_handler *handler,
        return error;
 }
 
-static int
-posix_acl_xattr_set(const struct xattr_handler *handler,
-                   struct dentry *unused, struct inode *inode,
-                   const char *name, const void *value,
-                   size_t size, int flags)
+int
+set_posix_acl(struct inode *inode, int type, struct posix_acl *acl)
 {
-       struct posix_acl *acl = NULL;
-       int ret;
-
        if (!IS_POSIXACL(inode))
                return -EOPNOTSUPP;
        if (!inode->i_op->set_acl)
                return -EOPNOTSUPP;
 
-       if (handler->flags == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
-               return value ? -EACCES : 0;
+       if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
+               return acl ? -EACCES : 0;
        if (!inode_owner_or_capable(inode))
                return -EPERM;
 
+       if (acl) {
+               int ret = posix_acl_valid(acl);
+               if (ret)
+                       return ret;
+       }
+       return inode->i_op->set_acl(inode, acl, type);
+}
+EXPORT_SYMBOL(set_posix_acl);
+
+static int
+posix_acl_xattr_set(const struct xattr_handler *handler,
+                   struct dentry *unused, struct inode *inode,
+                   const char *name, const void *value,
+                   size_t size, int flags)
+{
+       struct posix_acl *acl = NULL;
+       int ret;
+
        if (value) {
                acl = posix_acl_from_xattr(&init_user_ns, value, size);
                if (IS_ERR(acl))
                        return PTR_ERR(acl);
-
-               if (acl) {
-                       ret = posix_acl_valid(acl);
-                       if (ret)
-                               goto out;
-               }
        }
-
-       ret = inode->i_op->set_acl(inode, acl, handler->flags);
-out:
+       ret = set_posix_acl(inode, handler->flags, acl);
        posix_acl_release(acl);
        return ret;
 }
index 55bc7d6..0670278 100644 (file)
@@ -121,6 +121,13 @@ static struct dentry *proc_mount(struct file_system_type *fs_type,
        if (IS_ERR(sb))
                return ERR_CAST(sb);
 
+       /*
+        * procfs isn't actually a stacking filesystem; however, there is
+        * too much magic going on inside it to permit stacking things on
+        * top of it
+        */
+       sb->s_stack_depth = FILESYSTEM_MAX_STACK_DEPTH;
+
        if (!proc_parse_options(options, ns)) {
                deactivate_locked_super(sb);
                return ERR_PTR(-EINVAL);
index b8f2d1e..c72c16c 100644 (file)
@@ -1393,7 +1393,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
        unsigned long safe_mask = 0;
        unsigned int commit_max_age = (unsigned int)-1;
        struct reiserfs_journal *journal = SB_JOURNAL(s);
-       char *new_opts = kstrdup(arg, GFP_KERNEL);
+       char *new_opts;
        int err;
        char *qf_names[REISERFS_MAXQUOTAS];
        unsigned int qfmt = 0;
@@ -1401,6 +1401,10 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
        int i;
 #endif
 
+       new_opts = kstrdup(arg, GFP_KERNEL);
+       if (arg && !new_opts)
+               return -ENOMEM;
+
        sync_filesystem(s);
        reiserfs_write_lock(s);
 
@@ -1546,7 +1550,8 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
        }
 
 out_ok_unlocked:
-       replace_mount_options(s, new_opts);
+       if (new_opts)
+               replace_mount_options(s, new_opts);
        return 0;
 
 out_err_unlock:
index 0831697..7bbf420 100644 (file)
@@ -52,6 +52,7 @@
 #include "ubifs.h"
 #include <linux/mount.h>
 #include <linux/slab.h>
+#include <linux/migrate.h>
 
 static int read_block(struct inode *inode, void *addr, unsigned int block,
                      struct ubifs_data_node *dn)
@@ -1452,6 +1453,26 @@ static int ubifs_set_page_dirty(struct page *page)
        return ret;
 }
 
+#ifdef CONFIG_MIGRATION
+static int ubifs_migrate_page(struct address_space *mapping,
+               struct page *newpage, struct page *page, enum migrate_mode mode)
+{
+       int rc;
+
+       rc = migrate_page_move_mapping(mapping, newpage, page, NULL, mode, 0);
+       if (rc != MIGRATEPAGE_SUCCESS)
+               return rc;
+
+       if (PagePrivate(page)) {
+               ClearPagePrivate(page);
+               SetPagePrivate(newpage);
+       }
+
+       migrate_page_copy(newpage, page);
+       return MIGRATEPAGE_SUCCESS;
+}
+#endif
+
 static int ubifs_releasepage(struct page *page, gfp_t unused_gfp_flags)
 {
        /*
@@ -1591,6 +1612,9 @@ const struct address_space_operations ubifs_file_address_operations = {
        .write_end      = ubifs_write_end,
        .invalidatepage = ubifs_invalidatepage,
        .set_page_dirty = ubifs_set_page_dirty,
+#ifdef CONFIG_MIGRATION
+       .migratepage    = ubifs_migrate_page,
+#endif
        .releasepage    = ubifs_releasepage,
 };
 
index 5f861ed..888c364 100644 (file)
@@ -295,7 +295,8 @@ static uint32_t udf_try_read_meta(struct inode *inode, uint32_t block,
                map = &UDF_SB(sb)->s_partmaps[partition];
                /* map to sparable/physical partition desc */
                phyblock = udf_get_pblock(sb, eloc.logicalBlockNum,
-                       map->s_partition_num, ext_offset + offset);
+                       map->s_type_specific.s_metadata.s_phys_partition_ref,
+                       ext_offset + offset);
        }
 
        brelse(epos.bh);
@@ -317,14 +318,18 @@ uint32_t udf_get_pblock_meta25(struct super_block *sb, uint32_t block,
        mdata = &map->s_type_specific.s_metadata;
        inode = mdata->s_metadata_fe ? : mdata->s_mirror_fe;
 
-       /* We shouldn't mount such media... */
-       BUG_ON(!inode);
+       if (!inode)
+               return 0xFFFFFFFF;
+
        retblk = udf_try_read_meta(inode, block, partition, offset);
        if (retblk == 0xFFFFFFFF && mdata->s_metadata_fe) {
                udf_warn(sb, "error reading from METADATA, trying to read from MIRROR\n");
                if (!(mdata->s_flags & MF_MIRROR_FE_LOADED)) {
                        mdata->s_mirror_fe = udf_find_metadata_inode_efe(sb,
-                               mdata->s_mirror_file_loc, map->s_partition_num);
+                               mdata->s_mirror_file_loc,
+                               mdata->s_phys_partition_ref);
+                       if (IS_ERR(mdata->s_mirror_fe))
+                               mdata->s_mirror_fe = NULL;
                        mdata->s_flags |= MF_MIRROR_FE_LOADED;
                }
 
index 5e2c8c8..4942549 100644 (file)
@@ -951,13 +951,13 @@ out2:
 }
 
 struct inode *udf_find_metadata_inode_efe(struct super_block *sb,
-                                       u32 meta_file_loc, u32 partition_num)
+                                       u32 meta_file_loc, u32 partition_ref)
 {
        struct kernel_lb_addr addr;
        struct inode *metadata_fe;
 
        addr.logicalBlockNum = meta_file_loc;
-       addr.partitionReferenceNum = partition_num;
+       addr.partitionReferenceNum = partition_ref;
 
        metadata_fe = udf_iget_special(sb, &addr);
 
@@ -974,7 +974,8 @@ struct inode *udf_find_metadata_inode_efe(struct super_block *sb,
        return metadata_fe;
 }
 
-static int udf_load_metadata_files(struct super_block *sb, int partition)
+static int udf_load_metadata_files(struct super_block *sb, int partition,
+                                  int type1_index)
 {
        struct udf_sb_info *sbi = UDF_SB(sb);
        struct udf_part_map *map;
@@ -984,20 +985,21 @@ static int udf_load_metadata_files(struct super_block *sb, int partition)
 
        map = &sbi->s_partmaps[partition];
        mdata = &map->s_type_specific.s_metadata;
+       mdata->s_phys_partition_ref = type1_index;
 
        /* metadata address */
        udf_debug("Metadata file location: block = %d part = %d\n",
-                 mdata->s_meta_file_loc, map->s_partition_num);
+                 mdata->s_meta_file_loc, mdata->s_phys_partition_ref);
 
        fe = udf_find_metadata_inode_efe(sb, mdata->s_meta_file_loc,
-                                        map->s_partition_num);
+                                        mdata->s_phys_partition_ref);
        if (IS_ERR(fe)) {
                /* mirror file entry */
                udf_debug("Mirror metadata file location: block = %d part = %d\n",
-                         mdata->s_mirror_file_loc, map->s_partition_num);
+                         mdata->s_mirror_file_loc, mdata->s_phys_partition_ref);
 
                fe = udf_find_metadata_inode_efe(sb, mdata->s_mirror_file_loc,
-                                                map->s_partition_num);
+                                                mdata->s_phys_partition_ref);
 
                if (IS_ERR(fe)) {
                        udf_err(sb, "Both metadata and mirror metadata inode efe can not found\n");
@@ -1015,7 +1017,7 @@ static int udf_load_metadata_files(struct super_block *sb, int partition)
        */
        if (mdata->s_bitmap_file_loc != 0xFFFFFFFF) {
                addr.logicalBlockNum = mdata->s_bitmap_file_loc;
-               addr.partitionReferenceNum = map->s_partition_num;
+               addr.partitionReferenceNum = mdata->s_phys_partition_ref;
 
                udf_debug("Bitmap file location: block = %d part = %d\n",
                          addr.logicalBlockNum, addr.partitionReferenceNum);
@@ -1283,7 +1285,7 @@ static int udf_load_partdesc(struct super_block *sb, sector_t block)
        p = (struct partitionDesc *)bh->b_data;
        partitionNumber = le16_to_cpu(p->partitionNumber);
 
-       /* First scan for TYPE1, SPARABLE and METADATA partitions */
+       /* First scan for TYPE1 and SPARABLE partitions */
        for (i = 0; i < sbi->s_partitions; i++) {
                map = &sbi->s_partmaps[i];
                udf_debug("Searching map: (%d == %d)\n",
@@ -1333,7 +1335,7 @@ static int udf_load_partdesc(struct super_block *sb, sector_t block)
                goto out_bh;
 
        if (map->s_partition_type == UDF_METADATA_MAP25) {
-               ret = udf_load_metadata_files(sb, i);
+               ret = udf_load_metadata_files(sb, i, type1_idx);
                if (ret < 0) {
                        udf_err(sb, "error loading MetaData partition map %d\n",
                                i);
index 27b5335..c13875d 100644 (file)
@@ -61,6 +61,11 @@ struct udf_meta_data {
        __u32   s_bitmap_file_loc;
        __u32   s_alloc_unit_size;
        __u16   s_align_unit_size;
+       /*
+        * Partition Reference Number of the associated physical / sparable
+        * partition
+        */
+       __u16   s_phys_partition_ref;
        int     s_flags;
        struct inode *s_metadata_fe;
        struct inode *s_mirror_fe;
index 70a41f7..5731ccb 100644 (file)
@@ -51,7 +51,8 @@ extern void acpi_video_set_dmi_backlight_type(enum acpi_backlight_type type);
  */
 extern bool acpi_video_handles_brightness_key_presses(void);
 extern int acpi_video_get_levels(struct acpi_device *device,
-                                struct acpi_video_device_brightness **dev_br);
+                                struct acpi_video_device_brightness **dev_br,
+                                int *pmax_level);
 #else
 static inline int acpi_video_register(void) { return 0; }
 static inline void acpi_video_unregister(void) { return; }
@@ -72,7 +73,8 @@ static inline bool acpi_video_handles_brightness_key_presses(void)
        return false;
 }
 static inline int acpi_video_get_levels(struct acpi_device *device,
-                       struct acpi_video_device_brightness **dev_br)
+                       struct acpi_video_device_brightness **dev_br,
+                       int *pmax_level)
 {
        return -ENODEV;
 }
index 6bd0570..05f05f1 100644 (file)
 
 #include <asm-generic/qspinlock_types.h>
 
+/**
+ * queued_spin_unlock_wait - wait until the _current_ lock holder releases the lock
+ * @lock : Pointer to queued spinlock structure
+ *
+ * There is a very slight possibility of live-lock if the lockers keep coming
+ * and the waiter is just unfortunate enough to not see any unlock state.
+ */
+#ifndef queued_spin_unlock_wait
+extern void queued_spin_unlock_wait(struct qspinlock *lock);
+#endif
+
 /**
  * queued_spin_is_locked - is the spinlock locked?
  * @lock: Pointer to queued spinlock structure
  * Return: 1 if it is locked, 0 otherwise
  */
+#ifndef queued_spin_is_locked
 static __always_inline int queued_spin_is_locked(struct qspinlock *lock)
 {
        /*
-        * queued_spin_lock_slowpath() can ACQUIRE the lock before
-        * issuing the unordered store that sets _Q_LOCKED_VAL.
-        *
-        * See both smp_cond_acquire() sites for more detail.
-        *
-        * This however means that in code like:
-        *
-        *   spin_lock(A)               spin_lock(B)
-        *   spin_unlock_wait(B)        spin_is_locked(A)
-        *   do_something()             do_something()
-        *
-        * Both CPUs can end up running do_something() because the store
-        * setting _Q_LOCKED_VAL will pass through the loads in
-        * spin_unlock_wait() and/or spin_is_locked().
+        * See queued_spin_unlock_wait().
         *
-        * Avoid this by issuing a full memory barrier between the spin_lock()
-        * and the loads in spin_unlock_wait() and spin_is_locked().
-        *
-        * Note that regular mutual exclusion doesn't care about this
-        * delayed store.
+        * Any !0 state indicates it is locked, even if _Q_LOCKED_VAL
+        * isn't immediately observable.
         */
-       smp_mb();
-       return atomic_read(&lock->val) & _Q_LOCKED_MASK;
+       return atomic_read(&lock->val);
 }
+#endif
 
 /**
  * queued_spin_value_unlocked - is the spinlock structure unlocked?
@@ -122,21 +118,6 @@ static __always_inline void queued_spin_unlock(struct qspinlock *lock)
 }
 #endif
 
-/**
- * queued_spin_unlock_wait - wait until current lock holder releases the lock
- * @lock : Pointer to queued spinlock structure
- *
- * There is a very slight possibility of live-lock if the lockers keep coming
- * and the waiter is just unfortunate enough to not see any unlock state.
- */
-static inline void queued_spin_unlock_wait(struct qspinlock *lock)
-{
-       /* See queued_spin_is_locked() */
-       smp_mb();
-       while (atomic_read(&lock->val) & _Q_LOCKED_MASK)
-               cpu_relax();
-}
-
 #ifndef virt_spin_lock
 static __always_inline bool virt_spin_lock(struct qspinlock *lock)
 {
index 576e463..314b3ca 100644 (file)
@@ -65,6 +65,7 @@ struct coredump_params {
        unsigned long limit;
        unsigned long mm_flags;
        loff_t written;
+       loff_t pos;
 };
 
 /*
index 19b1486..1b3b6e1 100644 (file)
@@ -279,6 +279,11 @@ struct ceph_osd_client {
        struct workqueue_struct *notify_wq;
 };
 
+static inline bool ceph_osdmap_flag(struct ceph_osd_client *osdc, int flag)
+{
+       return osdc->osdmap->flags & flag;
+}
+
 extern int ceph_osdc_setup(void);
 extern void ceph_osdc_cleanup(void);
 
index ddc426b..9ccf4db 100644 (file)
@@ -189,11 +189,6 @@ static inline bool ceph_osd_is_down(struct ceph_osdmap *map, int osd)
        return !ceph_osd_is_up(map, osd);
 }
 
-static inline bool ceph_osdmap_flag(struct ceph_osdmap *map, int flag)
-{
-       return map && (map->flags & flag);
-}
-
 extern char *ceph_osdmap_state_str(char *str, int len, int state);
 extern u32 ceph_get_primary_affinity(struct ceph_osdmap *map, int osd);
 
index 0c72204..fb39d5a 100644 (file)
@@ -25,7 +25,7 @@
 #define CLK_SET_PARENT_GATE    BIT(1) /* must be gated across re-parent */
 #define CLK_SET_RATE_PARENT    BIT(2) /* propagate rate change up one level */
 #define CLK_IGNORE_UNUSED      BIT(3) /* do not gate even if unused */
-#define CLK_IS_ROOT            BIT(4) /* Deprecated: Don't use */
+                               /* unused */
 #define CLK_IS_BASIC           BIT(5) /* Basic clk, can't do a to_clk_foo() */
 #define CLK_GET_RATE_NOCACHE   BIT(6) /* do not use the cached clk rate */
 #define CLK_SET_RATE_NO_REPARENT BIT(7) /* don't re-parent on rate change */
index 786ad32..07b83d3 100644 (file)
@@ -152,6 +152,8 @@ extern void cpuidle_disable_device(struct cpuidle_device *dev);
 extern int cpuidle_play_dead(void);
 
 extern struct cpuidle_driver *cpuidle_get_cpu_driver(struct cpuidle_device *dev);
+static inline struct cpuidle_device *cpuidle_get_device(void)
+{return __this_cpu_read(cpuidle_devices); }
 #else
 static inline void disable_cpuidle(void) { }
 static inline bool cpuidle_not_available(struct cpuidle_driver *drv,
@@ -187,6 +189,7 @@ static inline void cpuidle_disable_device(struct cpuidle_device *dev) { }
 static inline int cpuidle_play_dead(void) {return -ENODEV; }
 static inline struct cpuidle_driver *cpuidle_get_cpu_driver(
        struct cpuidle_device *dev) {return NULL; }
+static inline struct cpuidle_device *cpuidle_get_device(void) {return NULL; }
 #endif
 
 #if defined(CONFIG_CPU_IDLE) && defined(CONFIG_SUSPEND)
index 484c879..f53fa05 100644 (file)
@@ -212,6 +212,7 @@ struct dentry_operations {
 #define DCACHE_OP_REAL                 0x08000000
 
 #define DCACHE_PAR_LOOKUP              0x10000000 /* being looked up (with parent locked shared) */
+#define DCACHE_DENTRY_CURSOR           0x20000000
 
 extern seqlock_t rename_lock;
 
@@ -575,5 +576,17 @@ static inline struct inode *vfs_select_inode(struct dentry *dentry,
        return inode;
 }
 
+/**
+ * d_real_inode - Return the real inode
+ * @dentry: The dentry to query
+ *
+ * If dentry is on an union/overlay, then return the underlying, real inode.
+ * Otherwise return d_inode().
+ */
+static inline struct inode *d_real_inode(struct dentry *dentry)
+{
+       return d_backing_inode(d_real(dentry));
+}
+
 
 #endif /* __LINUX_DCACHE_H */
index 5871f29..277ab9a 100644 (file)
 
 #include <linux/errno.h>
 
-struct pts_fs_info;
-
 #ifdef CONFIG_UNIX98_PTYS
 
-/* Look up a pts fs info and get a ref to it */
-struct pts_fs_info *devpts_get_ref(struct inode *, struct file *);
-void devpts_put_ref(struct pts_fs_info *);
+struct pts_fs_info;
+
+struct pts_fs_info *devpts_acquire(struct file *);
+void devpts_release(struct pts_fs_info *);
 
 int devpts_new_index(struct pts_fs_info *);
 void devpts_kill_index(struct pts_fs_info *, int);
index 3fe90d4..4551c6f 100644 (file)
@@ -112,19 +112,24 @@ struct dma_buf_ops {
  * @file: file pointer used for sharing buffers across, and for refcounting.
  * @attachments: list of dma_buf_attachment that denotes all devices attached.
  * @ops: dma_buf_ops associated with this buffer object.
+ * @lock: used internally to serialize list manipulation, attach/detach and vmap/unmap
+ * @vmapping_counter: used internally to refcnt the vmaps
+ * @vmap_ptr: the current vmap ptr if vmapping_counter > 0
  * @exp_name: name of the exporter; useful for debugging.
  * @owner: pointer to exporter module; used for refcounting when exporter is a
  *         kernel module.
  * @list_node: node for dma_buf accounting and debugging.
  * @priv: exporter specific private data for this buffer object.
  * @resv: reservation object linked to this dma-buf
+ * @poll: for userspace poll support
+ * @cb_excl: for userspace poll support
+ * @cb_shared: for userspace poll support
  */
 struct dma_buf {
        size_t size;
        struct file *file;
        struct list_head attachments;
        const struct dma_buf_ops *ops;
-       /* mutex to serialize list manipulation, attach/detach and vmap/unmap */
        struct mutex lock;
        unsigned vmapping_counter;
        void *vmap_ptr;
@@ -188,9 +193,11 @@ struct dma_buf_export_info {
 
 /**
  * helper macro for exporters; zeros and fills in most common values
+ *
+ * @name: export-info name
  */
-#define DEFINE_DMA_BUF_EXPORT_INFO(a)  \
-       struct dma_buf_export_info a = { .exp_name = KBUILD_MODNAME, \
+#define DEFINE_DMA_BUF_EXPORT_INFO(name)       \
+       struct dma_buf_export_info name = { .exp_name = KBUILD_MODNAME, \
                                         .owner = THIS_MODULE }
 
 /**
index c2db3ca..f196dd0 100644 (file)
@@ -1005,7 +1005,7 @@ extern int efi_memattr_apply_permissions(struct mm_struct *mm,
 /* Iterate through an efi_memory_map */
 #define for_each_efi_memory_desc_in_map(m, md)                            \
        for ((md) = (m)->map;                                              \
-            (md) <= (efi_memory_desc_t *)((m)->map_end - (m)->desc_size); \
+            ((void *)(md) + (m)->desc_size) <= (m)->map_end;              \
             (md) = (void *)(md) + (m)->desc_size)
 
 /**
index 2b17698..2056e9f 100644 (file)
@@ -49,6 +49,8 @@ struct fence_cb;
  * @timestamp: Timestamp when the fence was signaled.
  * @status: Optional, only valid if < 0, must be set before calling
  * fence_signal, indicates that the fence has completed with an error.
+ * @child_list: list of children fences
+ * @active_list: list of active fences
  *
  * the flags member must be manipulated and read using the appropriate
  * atomic ops (bit_*), so taking the spinlock will not be needed most
index 604e152..13ba552 100644 (file)
@@ -241,7 +241,7 @@ struct fscache_cache_ops {
 
        /* check the consistency between the backing cache and the FS-Cache
         * cookie */
-       bool (*check_consistency)(struct fscache_operation *op);
+       int (*check_consistency)(struct fscache_operation *op);
 
        /* store the updated auxiliary data on an object */
        void (*update_object)(struct fscache_object *object);
index d029ffa..99403b1 100644 (file)
@@ -223,6 +223,8 @@ struct st_sensor_settings {
  * @get_irq_data_ready: Function to get the IRQ used for data ready signal.
  * @tf: Transfer function structure used by I/O operations.
  * @tb: Transfer buffers and mutex used by I/O operations.
+ * @hw_irq_trigger: if we're using the hardware interrupt on the sensor.
+ * @hw_timestamp: Latest timestamp from the interrupt handler, when in use.
  */
 struct st_sensor_data {
        struct device *dev;
@@ -247,6 +249,9 @@ struct st_sensor_data {
 
        const struct st_sensor_transfer_function *tf;
        struct st_sensor_transfer_buffer tb;
+
+       bool hw_irq_trigger;
+       s64 hw_timestamp;
 };
 
 #ifdef CONFIG_IIO_BUFFER
@@ -260,7 +265,8 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
                                const struct iio_trigger_ops *trigger_ops);
 
 void st_sensors_deallocate_trigger(struct iio_dev *indio_dev);
-
+int st_sensors_validate_device(struct iio_trigger *trig,
+                              struct iio_dev *indio_dev);
 #else
 static inline int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
                                const struct iio_trigger_ops *trigger_ops)
@@ -271,6 +277,7 @@ static inline void st_sensors_deallocate_trigger(struct iio_dev *indio_dev)
 {
        return;
 }
+#define st_sensors_validate_device NULL
 #endif
 
 int st_sensors_init_sensor(struct iio_dev *indio_dev,
index f2cb8d4..f8834f8 100644 (file)
@@ -190,7 +190,7 @@ extern struct task_group root_task_group;
 #define INIT_TASK(tsk) \
 {                                                                      \
        .state          = 0,                                            \
-       .stack          = &init_thread_info,                            \
+       .stack          = init_stack,                                   \
        .usage          = ATOMIC_INIT(2),                               \
        .flags          = PF_KTHREAD,                                   \
        .prio           = MAX_PRIO-20,                                  \
index bfbd707..dc493e0 100644 (file)
 #define ICC_SGI1R_AFFINITY_1_SHIFT     16
 #define ICC_SGI1R_AFFINITY_1_MASK      (0xff << ICC_SGI1R_AFFINITY_1_SHIFT)
 #define ICC_SGI1R_SGI_ID_SHIFT         24
-#define ICC_SGI1R_SGI_ID_MASK          (0xff << ICC_SGI1R_SGI_ID_SHIFT)
+#define ICC_SGI1R_SGI_ID_MASK          (0xfULL << ICC_SGI1R_SGI_ID_SHIFT)
 #define ICC_SGI1R_AFFINITY_2_SHIFT     32
-#define ICC_SGI1R_AFFINITY_2_MASK      (0xffULL << ICC_SGI1R_AFFINITY_1_SHIFT)
+#define ICC_SGI1R_AFFINITY_2_MASK      (0xffULL << ICC_SGI1R_AFFINITY_2_SHIFT)
 #define ICC_SGI1R_IRQ_ROUTING_MODE_BIT 40
 #define ICC_SGI1R_AFFINITY_3_SHIFT     48
-#define ICC_SGI1R_AFFINITY_3_MASK      (0xffULL << ICC_SGI1R_AFFINITY_1_SHIFT)
+#define ICC_SGI1R_AFFINITY_3_MASK      (0xffULL << ICC_SGI1R_AFFINITY_3_SHIFT)
 
 #include <asm/arch_gicv3.h>
 
index 5ab8528..f2d0258 100644 (file)
@@ -6,6 +6,7 @@
 #define __LINUX_ISA_H
 
 #include <linux/device.h>
+#include <linux/errno.h>
 #include <linux/kernel.h>
 
 struct isa_driver {
@@ -22,13 +23,13 @@ struct isa_driver {
 
 #define to_isa_driver(x) container_of((x), struct isa_driver, driver)
 
-#ifdef CONFIG_ISA
+#ifdef CONFIG_ISA_BUS_API
 int isa_register_driver(struct isa_driver *, unsigned int);
 void isa_unregister_driver(struct isa_driver *);
 #else
 static inline int isa_register_driver(struct isa_driver *d, unsigned int i)
 {
-       return 0;
+       return -ENODEV;
 }
 
 static inline void isa_unregister_driver(struct isa_driver *d)
index 0536524..6890446 100644 (file)
@@ -117,13 +117,18 @@ struct module;
 
 #include <linux/atomic.h>
 
+#ifdef HAVE_JUMP_LABEL
+
 static inline int static_key_count(struct static_key *key)
 {
-       return atomic_read(&key->enabled);
+       /*
+        * -1 means the first static_key_slow_inc() is in progress.
+        *  static_key_enabled() must return true, so return 1 here.
+        */
+       int n = atomic_read(&key->enabled);
+       return n >= 0 ? n : 1;
 }
 
-#ifdef HAVE_JUMP_LABEL
-
 #define JUMP_TYPE_FALSE        0UL
 #define JUMP_TYPE_TRUE 1UL
 #define JUMP_TYPE_MASK 1UL
@@ -162,6 +167,11 @@ extern void jump_label_apply_nops(struct module *mod);
 
 #else  /* !HAVE_JUMP_LABEL */
 
+static inline int static_key_count(struct static_key *key)
+{
+       return atomic_read(&key->enabled);
+}
+
 static __always_inline void jump_label_init(void)
 {
        static_key_initialized = true;
index 611927f..ac4b3c4 100644 (file)
@@ -59,14 +59,13 @@ void kasan_poison_object_data(struct kmem_cache *cache, void *object);
 
 void kasan_kmalloc_large(const void *ptr, size_t size, gfp_t flags);
 void kasan_kfree_large(const void *ptr);
-void kasan_kfree(void *ptr);
+void kasan_poison_kfree(void *ptr);
 void kasan_kmalloc(struct kmem_cache *s, const void *object, size_t size,
                  gfp_t flags);
 void kasan_krealloc(const void *object, size_t new_size, gfp_t flags);
 
 void kasan_slab_alloc(struct kmem_cache *s, void *object, gfp_t flags);
 bool kasan_slab_free(struct kmem_cache *s, void *object);
-void kasan_poison_slab_free(struct kmem_cache *s, void *object);
 
 struct kasan_cache {
        int alloc_meta_offset;
@@ -76,6 +75,9 @@ struct kasan_cache {
 int kasan_module_alloc(void *addr, size_t size);
 void kasan_free_shadow(const struct vm_struct *vm);
 
+size_t ksize(const void *);
+static inline void kasan_unpoison_slab(const void *ptr) { ksize(ptr); }
+
 #else /* CONFIG_KASAN */
 
 static inline void kasan_unpoison_shadow(const void *address, size_t size) {}
@@ -102,7 +104,7 @@ static inline void kasan_poison_object_data(struct kmem_cache *cache,
 
 static inline void kasan_kmalloc_large(void *ptr, size_t size, gfp_t flags) {}
 static inline void kasan_kfree_large(const void *ptr) {}
-static inline void kasan_kfree(void *ptr) {}
+static inline void kasan_poison_kfree(void *ptr) {}
 static inline void kasan_kmalloc(struct kmem_cache *s, const void *object,
                                size_t size, gfp_t flags) {}
 static inline void kasan_krealloc(const void *object, size_t new_size,
@@ -114,11 +116,12 @@ static inline bool kasan_slab_free(struct kmem_cache *s, void *object)
 {
        return false;
 }
-static inline void kasan_poison_slab_free(struct kmem_cache *s, void *object) {}
 
 static inline int kasan_module_alloc(void *addr, size_t size) { return 0; }
 static inline void kasan_free_shadow(const struct vm_struct *vm) {}
 
+static inline void kasan_unpoison_slab(const void *ptr) { }
+
 #endif /* CONFIG_KASAN */
 
 #endif /* LINUX_KASAN_H */
index d2b1306..e5e7f2e 100644 (file)
@@ -42,15 +42,16 @@ struct led_classdev {
 #define LED_UNREGISTERING      (1 << 1)
        /* Upper 16 bits reflect control information */
 #define LED_CORE_SUSPENDRESUME (1 << 16)
-#define LED_BLINK_ONESHOT      (1 << 17)
-#define LED_BLINK_ONESHOT_STOP (1 << 18)
-#define LED_BLINK_INVERT       (1 << 19)
-#define LED_BLINK_BRIGHTNESS_CHANGE (1 << 20)
-#define LED_BLINK_DISABLE      (1 << 21)
-#define LED_SYSFS_DISABLE      (1 << 22)
-#define LED_DEV_CAP_FLASH      (1 << 23)
-#define LED_HW_PLUGGABLE       (1 << 24)
-#define LED_PANIC_INDICATOR    (1 << 25)
+#define LED_BLINK_SW           (1 << 17)
+#define LED_BLINK_ONESHOT      (1 << 18)
+#define LED_BLINK_ONESHOT_STOP (1 << 19)
+#define LED_BLINK_INVERT       (1 << 20)
+#define LED_BLINK_BRIGHTNESS_CHANGE (1 << 21)
+#define LED_BLINK_DISABLE      (1 << 22)
+#define LED_SYSFS_DISABLE      (1 << 23)
+#define LED_DEV_CAP_FLASH      (1 << 24)
+#define LED_HW_PLUGGABLE       (1 << 25)
+#define LED_PANIC_INDICATOR    (1 << 26)
 
        /* Set LED brightness level
         * Must not sleep. Use brightness_set_blocking for drivers
@@ -72,8 +73,8 @@ struct led_classdev {
         * and if both are zero then a sensible default should be chosen.
         * The call should adjust the timings in that case and if it can't
         * match the values specified exactly.
-        * Deactivate blinking again when the brightness is set to a fixed
-        * value via the brightness_set() callback.
+        * Deactivate blinking again when the brightness is set to LED_OFF
+        * via the brightness_set() callback.
         */
        int             (*blink_set)(struct led_classdev *led_cdev,
                                     unsigned long *delay_on,
index 035abdf..73a4847 100644 (file)
@@ -1240,8 +1240,6 @@ struct mlx5_destroy_psv_out {
        u8                      rsvd[8];
 };
 
-#define MLX5_CMD_OP_MAX 0x920
-
 enum {
        VPORT_STATE_DOWN                = 0x0,
        VPORT_STATE_UP                  = 0x1,
@@ -1369,6 +1367,12 @@ enum mlx5_cap_type {
 #define MLX5_CAP_FLOWTABLE_MAX(mdev, cap) \
        MLX5_GET(flow_table_nic_cap, mdev->hca_caps_max[MLX5_CAP_FLOW_TABLE], cap)
 
+#define MLX5_CAP_FLOWTABLE_NIC_RX(mdev, cap) \
+       MLX5_CAP_FLOWTABLE(mdev, flow_table_properties_nic_receive.cap)
+
+#define MLX5_CAP_FLOWTABLE_NIC_RX_MAX(mdev, cap) \
+       MLX5_CAP_FLOWTABLE_MAX(mdev, flow_table_properties_nic_receive.cap)
+
 #define MLX5_CAP_ESW_FLOWTABLE(mdev, cap) \
        MLX5_GET(flow_table_eswitch_cap, \
                 mdev->hca_caps_cur[MLX5_CAP_ESWITCH_FLOW_TABLE], cap)
index 9a05cd7..e955a28 100644 (file)
@@ -205,7 +205,8 @@ enum {
        MLX5_CMD_OP_ALLOC_FLOW_COUNTER            = 0x939,
        MLX5_CMD_OP_DEALLOC_FLOW_COUNTER          = 0x93a,
        MLX5_CMD_OP_QUERY_FLOW_COUNTER            = 0x93b,
-       MLX5_CMD_OP_MODIFY_FLOW_TABLE             = 0x93c
+       MLX5_CMD_OP_MODIFY_FLOW_TABLE             = 0x93c,
+       MLX5_CMD_OP_MAX
 };
 
 struct mlx5_ifc_flow_table_fields_supported_bits {
@@ -500,7 +501,9 @@ struct mlx5_ifc_e_switch_cap_bits {
        u8         vport_svlan_insert[0x1];
        u8         vport_cvlan_insert_if_not_exist[0x1];
        u8         vport_cvlan_insert_overwrite[0x1];
-       u8         reserved_at_5[0x1b];
+       u8         reserved_at_5[0x19];
+       u8         nic_vport_node_guid_modify[0x1];
+       u8         nic_vport_port_guid_modify[0x1];
 
        u8         reserved_at_20[0x7e0];
 };
@@ -4583,7 +4586,10 @@ struct mlx5_ifc_modify_nic_vport_context_out_bits {
 };
 
 struct mlx5_ifc_modify_nic_vport_field_select_bits {
-       u8         reserved_at_0[0x19];
+       u8         reserved_at_0[0x16];
+       u8         node_guid[0x1];
+       u8         port_guid[0x1];
+       u8         reserved_at_18[0x1];
        u8         mtu[0x1];
        u8         change_event[0x1];
        u8         promisc[0x1];
index 6422102..ab31081 100644 (file)
@@ -172,6 +172,7 @@ enum {
 enum {
        MLX5_FENCE_MODE_NONE                    = 0 << 5,
        MLX5_FENCE_MODE_INITIATOR_SMALL         = 1 << 5,
+       MLX5_FENCE_MODE_FENCE                   = 2 << 5,
        MLX5_FENCE_MODE_STRONG_ORDERING         = 3 << 5,
        MLX5_FENCE_MODE_SMALL_AND_FENCE         = 4 << 5,
 };
@@ -460,10 +461,9 @@ struct mlx5_core_qp {
 };
 
 struct mlx5_qp_path {
-       u8                      fl;
+       u8                      fl_free_ar;
        u8                      rsvd3;
-       u8                      free_ar;
-       u8                      pkey_index;
+       __be16                  pkey_index;
        u8                      rsvd0;
        u8                      grh_mlid;
        __be16                  rlid;
@@ -560,6 +560,7 @@ struct mlx5_modify_qp_mbox_in {
        __be32                  optparam;
        u8                      rsvd0[4];
        struct mlx5_qp_context  ctx;
+       u8                      rsvd2[16];
 };
 
 struct mlx5_modify_qp_mbox_out {
index 301da4a..6c16c19 100644 (file)
@@ -50,6 +50,8 @@ int mlx5_modify_nic_vport_mtu(struct mlx5_core_dev *mdev, u16 mtu);
 int mlx5_query_nic_vport_system_image_guid(struct mlx5_core_dev *mdev,
                                           u64 *system_image_guid);
 int mlx5_query_nic_vport_node_guid(struct mlx5_core_dev *mdev, u64 *node_guid);
+int mlx5_modify_nic_vport_node_guid(struct mlx5_core_dev *mdev,
+                                   u32 vport, u64 node_guid);
 int mlx5_query_nic_vport_qkey_viol_cntr(struct mlx5_core_dev *mdev,
                                        u16 *qkey_viol_cntr);
 int mlx5_query_hca_vport_gid(struct mlx5_core_dev *dev, u8 other_vport,
index 5df5feb..ece042d 100644 (file)
@@ -602,7 +602,7 @@ static inline pte_t maybe_mkwrite(pte_t pte, struct vm_area_struct *vma)
 }
 
 void do_set_pte(struct vm_area_struct *vma, unsigned long address,
-               struct page *page, pte_t *pte, bool write, bool anon, bool old);
+               struct page *page, pte_t *pte, bool write, bool anon);
 #endif
 
 /*
index ec5ec28..d3d0398 100644 (file)
@@ -45,6 +45,8 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND};
 #define LOOKUP_ROOT            0x2000
 #define LOOKUP_EMPTY           0x4000
 
+extern int path_pts(struct path *path);
+
 extern int user_path_at_empty(int, const char __user *, unsigned, struct path *, int *empty);
 
 static inline int user_path_at(int dfd, const char __user *name, unsigned flags,
index c7292e8..74eb28c 100644 (file)
@@ -614,7 +614,7 @@ static inline struct device_node *of_parse_phandle(const struct device_node *np,
        return NULL;
 }
 
-static inline int of_parse_phandle_with_args(struct device_node *np,
+static inline int of_parse_phandle_with_args(const struct device_node *np,
                                             const char *list_name,
                                             const char *cells_name,
                                             int index,
index f6e9e85..b969e94 100644 (file)
@@ -8,7 +8,7 @@ struct pci_dev;
 struct of_phandle_args;
 struct device_node;
 
-#ifdef CONFIG_OF
+#ifdef CONFIG_OF_PCI
 int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq);
 struct device_node *of_pci_find_child_device(struct device_node *parent,
                                             unsigned int devfn);
index ad2f670..c201060 100644 (file)
@@ -31,6 +31,13 @@ typedef int (*reservedmem_of_init_fn)(struct reserved_mem *rmem);
 int of_reserved_mem_device_init(struct device *dev);
 void of_reserved_mem_device_release(struct device *dev);
 
+int early_init_dt_alloc_reserved_memory_arch(phys_addr_t size,
+                                            phys_addr_t align,
+                                            phys_addr_t start,
+                                            phys_addr_t end,
+                                            bool nomap,
+                                            phys_addr_t *res_base);
+
 void fdt_init_reserved_mem(void);
 void fdt_reserved_mem_save_node(unsigned long node, const char *uname,
                               phys_addr_t base, phys_addr_t size);
index bf268fa..fec4027 100644 (file)
@@ -46,33 +46,62 @@ extern struct page_ext_operations page_idle_ops;
 
 static inline bool page_is_young(struct page *page)
 {
-       return test_bit(PAGE_EXT_YOUNG, &lookup_page_ext(page)->flags);
+       struct page_ext *page_ext = lookup_page_ext(page);
+
+       if (unlikely(!page_ext))
+               return false;
+
+       return test_bit(PAGE_EXT_YOUNG, &page_ext->flags);
 }
 
 static inline void set_page_young(struct page *page)
 {
-       set_bit(PAGE_EXT_YOUNG, &lookup_page_ext(page)->flags);
+       struct page_ext *page_ext = lookup_page_ext(page);
+
+       if (unlikely(!page_ext))
+               return;
+
+       set_bit(PAGE_EXT_YOUNG, &page_ext->flags);
 }
 
 static inline bool test_and_clear_page_young(struct page *page)
 {
-       return test_and_clear_bit(PAGE_EXT_YOUNG,
-                                 &lookup_page_ext(page)->flags);
+       struct page_ext *page_ext = lookup_page_ext(page);
+
+       if (unlikely(!page_ext))
+               return false;
+
+       return test_and_clear_bit(PAGE_EXT_YOUNG, &page_ext->flags);
 }
 
 static inline bool page_is_idle(struct page *page)
 {
-       return test_bit(PAGE_EXT_IDLE, &lookup_page_ext(page)->flags);
+       struct page_ext *page_ext = lookup_page_ext(page);
+
+       if (unlikely(!page_ext))
+               return false;
+
+       return test_bit(PAGE_EXT_IDLE, &page_ext->flags);
 }
 
 static inline void set_page_idle(struct page *page)
 {
-       set_bit(PAGE_EXT_IDLE, &lookup_page_ext(page)->flags);
+       struct page_ext *page_ext = lookup_page_ext(page);
+
+       if (unlikely(!page_ext))
+               return;
+
+       set_bit(PAGE_EXT_IDLE, &page_ext->flags);
 }
 
 static inline void clear_page_idle(struct page *page)
 {
-       clear_bit(PAGE_EXT_IDLE, &lookup_page_ext(page)->flags);
+       struct page_ext *page_ext = lookup_page_ext(page);
+
+       if (unlikely(!page_ext))
+               return;
+
+       clear_bit(PAGE_EXT_IDLE, &page_ext->flags);
 }
 #endif /* CONFIG_64BIT */
 
index 17018f3..908b67c 100644 (file)
@@ -235,6 +235,9 @@ static inline int pwm_config(struct pwm_device *pwm, int duty_ns,
        if (!pwm)
                return -EINVAL;
 
+       if (duty_ns < 0 || period_ns < 0)
+               return -EINVAL;
+
        pwm_get_state(pwm, &state);
        if (state.duty_cycle == duty_ns && state.period == period_ns)
                return 0;
index 49d0576..b0f305e 100644 (file)
@@ -49,12 +49,27 @@ extern struct ww_class reservation_ww_class;
 extern struct lock_class_key reservation_seqcount_class;
 extern const char reservation_seqcount_string[];
 
+/**
+ * struct reservation_object_list - a list of shared fences
+ * @rcu: for internal use
+ * @shared_count: table of shared fences
+ * @shared_max: for growing shared fence table
+ * @shared: shared fence table
+ */
 struct reservation_object_list {
        struct rcu_head rcu;
        u32 shared_count, shared_max;
        struct fence __rcu *shared[];
 };
 
+/**
+ * struct reservation_object - a reservation object manages fences for a buffer
+ * @lock: update side lock
+ * @seq: sequence count for managing RCU read-side synchronization
+ * @fence_excl: the exclusive fence, if there is one currently
+ * @fence: list of current shared fences
+ * @staged: staged copy of shared fences for RCU updates
+ */
 struct reservation_object {
        struct ww_mutex lock;
        seqcount_t seq;
@@ -68,6 +83,10 @@ struct reservation_object {
 #define reservation_object_assert_held(obj) \
        lockdep_assert_held(&(obj)->lock.base)
 
+/**
+ * reservation_object_init - initialize a reservation object
+ * @obj: the reservation object
+ */
 static inline void
 reservation_object_init(struct reservation_object *obj)
 {
@@ -79,6 +98,10 @@ reservation_object_init(struct reservation_object *obj)
        obj->staged = NULL;
 }
 
+/**
+ * reservation_object_fini - destroys a reservation object
+ * @obj: the reservation object
+ */
 static inline void
 reservation_object_fini(struct reservation_object *obj)
 {
@@ -106,6 +129,14 @@ reservation_object_fini(struct reservation_object *obj)
        ww_mutex_destroy(&obj->lock);
 }
 
+/**
+ * reservation_object_get_list - get the reservation object's
+ * shared fence list, with update-side lock held
+ * @obj: the reservation object
+ *
+ * Returns the shared fence list.  Does NOT take references to
+ * the fence.  The obj->lock must be held.
+ */
 static inline struct reservation_object_list *
 reservation_object_get_list(struct reservation_object *obj)
 {
@@ -113,6 +144,17 @@ reservation_object_get_list(struct reservation_object *obj)
                                         reservation_object_held(obj));
 }
 
+/**
+ * reservation_object_get_excl - get the reservation object's
+ * exclusive fence, with update-side lock held
+ * @obj: the reservation object
+ *
+ * Returns the exclusive fence (if any).  Does NOT take a
+ * reference.  The obj->lock must be held.
+ *
+ * RETURNS
+ * The exclusive fence or NULL
+ */
 static inline struct fence *
 reservation_object_get_excl(struct reservation_object *obj)
 {
@@ -120,6 +162,17 @@ reservation_object_get_excl(struct reservation_object *obj)
                                         reservation_object_held(obj));
 }
 
+/**
+ * reservation_object_get_excl_rcu - get the reservation object's
+ * exclusive fence, without lock held.
+ * @obj: the reservation object
+ *
+ * If there is an exclusive fence, this atomically increments it's
+ * reference count and returns it.
+ *
+ * RETURNS
+ * The exclusive fence or NULL if none
+ */
 static inline struct fence *
 reservation_object_get_excl_rcu(struct reservation_object *obj)
 {
index 6e42ada..253538f 100644 (file)
@@ -3007,7 +3007,7 @@ static inline int object_is_on_stack(void *obj)
        return (obj >= stack) && (obj < (stack + THREAD_SIZE));
 }
 
-extern void thread_info_cache_init(void);
+extern void thread_stack_cache_init(void);
 
 #ifdef CONFIG_DEBUG_STACK_USAGE
 static inline unsigned long stack_not_used(struct task_struct *p)
index dacb5e7..de1f643 100644 (file)
@@ -765,6 +765,8 @@ struct sctp_info {
        __u8    sctpi_s_disable_fragments;
        __u8    sctpi_s_v4mapped;
        __u8    sctpi_s_frag_interleave;
+       __u32   sctpi_s_type;
+       __u32   __reserved3;
 };
 
 struct sctp_infox {
index 7973a82..ead9765 100644 (file)
@@ -277,7 +277,10 @@ static inline void raw_write_seqcount_barrier(seqcount_t *s)
 
 static inline int raw_read_seqcount_latch(seqcount_t *s)
 {
-       return lockless_dereference(s)->sequence;
+       int seq = READ_ONCE(s->sequence);
+       /* Pairs with the first smp_wmb() in raw_write_seqcount_latch() */
+       smp_read_barrier_depends();
+       return seq;
 }
 
 /**
@@ -331,7 +334,7 @@ static inline int raw_read_seqcount_latch(seqcount_t *s)
  *     unsigned seq, idx;
  *
  *     do {
- *             seq = lockless_dereference(latch)->seq;
+ *             seq = raw_read_seqcount_latch(&latch->seq);
  *
  *             idx = seq & 0x01;
  *             entry = data_query(latch->data[idx], ...);
index 19c659d..b6810c9 100644 (file)
@@ -137,8 +137,6 @@ struct rpc_create_args {
 #define RPC_CLNT_CREATE_NO_RETRANS_TIMEOUT     (1UL << 9)
 
 struct rpc_clnt *rpc_create(struct rpc_create_args *args);
-struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args,
-                                       struct rpc_xprt *xprt);
 struct rpc_clnt        *rpc_bind_new_program(struct rpc_clnt *,
                                const struct rpc_program *, u32);
 struct rpc_clnt *rpc_clone_client(struct rpc_clnt *);
index b7dabc4..79ba508 100644 (file)
@@ -84,6 +84,7 @@ struct svc_xprt {
 
        struct net              *xpt_net;
        struct rpc_xprt         *xpt_bc_xprt;   /* NFSv4.1 backchannel */
+       struct rpc_xprt_switch  *xpt_bc_xps;    /* NFSv4.1 backchannel */
 };
 
 static inline void unregister_xpt_user(struct svc_xprt *xpt, struct svc_xpt_user *u)
index 5aa3834..5e3e1b6 100644 (file)
@@ -297,6 +297,7 @@ struct xprt_create {
        size_t                  addrlen;
        const char              *servername;
        struct svc_xprt         *bc_xprt;       /* NFSv4.1 backchannel */
+       struct rpc_xprt_switch  *bc_xps;
        unsigned int            flags;
 };
 
index e45abe7..ee517be 100644 (file)
@@ -335,6 +335,8 @@ struct thermal_genl_event {
  * @get_trend: a pointer to a function that reads the sensor temperature trend.
  * @set_emul_temp: a pointer to a function that sets sensor emulated
  *                temperature.
+ * @set_trip_temp: a pointer to a function that sets the trip temperature on
+ *                hardware.
  */
 struct thermal_zone_of_device_ops {
        int (*get_temp)(void *, int *);
index 37dbacf..816b754 100644 (file)
@@ -21,6 +21,9 @@ static inline int do_sys_settimeofday(const struct timespec *tv,
        struct timespec64 ts64;
 
        if (!tv)
+               return do_sys_settimeofday64(NULL, tz);
+
+       if (!timespec_valid(tv))
                return -EINVAL;
 
        ts64 = timespec_to_timespec64(*tv);
index 457651b..fefe8b0 100644 (file)
@@ -1034,6 +1034,8 @@ static inline int usb_gadget_activate(struct usb_gadget *gadget)
  * @udc_name: A name of UDC this driver should be bound to. If udc_name is NULL,
  *     this driver will be bound to any available UDC.
  * @pending: UDC core private data used for deferred probe of this driver.
+ * @match_existing_only: If udc is not found, return an error and don't add this
+ *      gadget driver to list of pending driver
  *
  * Devices are disabled till a gadget driver successfully bind()s, which
  * means the driver will handle setup() requests needed to enumerate (and
@@ -1097,6 +1099,7 @@ struct usb_gadget_driver {
 
        char                    *udc_name;
        struct list_head        pending;
+       unsigned                match_existing_only:1;
 };
 
 
index 0b3da40..d315c89 100644 (file)
@@ -142,10 +142,11 @@ enum musb_vbus_id_status {
 };
 
 #if IS_ENABLED(CONFIG_USB_MUSB_HDRC)
-void musb_mailbox(enum musb_vbus_id_status status);
+int musb_mailbox(enum musb_vbus_id_status status);
 #else
-static inline void musb_mailbox(enum musb_vbus_id_status status)
+static inline int musb_mailbox(enum musb_vbus_id_status status)
 {
+       return 0;
 }
 #endif
 
index 98a938a..7a8d603 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * v4l2-mc.h - Media Controller V4L2 types and prototypes
  *
- * Copyright (C) 2016 Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+ * Copyright (C) 2016 Mauro Carvalho Chehab <mchehab@kernel.org>
  * Copyright (C) 2006-2010 Nokia Corporation
  * Copyright (c) 2016 Intel Corporation.
  *
index 48103cf..13de0cc 100644 (file)
@@ -42,6 +42,7 @@ int compat_sock_get_timestampns(struct sock *, struct timespec __user *);
 
 int get_compat_msghdr(struct msghdr *, struct compat_msghdr __user *,
                      struct sockaddr __user **, struct iovec **);
+struct sock_fprog __user *get_compat_bpf_fprog(char __user *optval);
 asmlinkage long compat_sys_sendmsg(int, struct compat_msghdr __user *,
                                   unsigned int);
 asmlinkage long compat_sys_sendmmsg(int, struct compat_mmsghdr __user *,
index d325c81..43a5a0e 100644 (file)
@@ -63,6 +63,8 @@ struct ip6_tnl_encap_ops {
                            u8 *protocol, struct flowi6 *fl6);
 };
 
+#ifdef CONFIG_INET
+
 extern const struct ip6_tnl_encap_ops __rcu *
                ip6tun_encaps[MAX_IPTUN_ENCAP_OPS];
 
@@ -138,7 +140,6 @@ struct net *ip6_tnl_get_link_net(const struct net_device *dev);
 int ip6_tnl_get_iflink(const struct net_device *dev);
 int ip6_tnl_change_mtu(struct net_device *dev, int new_mtu);
 
-#ifdef CONFIG_INET
 static inline void ip6tunnel_xmit(struct sock *sk, struct sk_buff *skb,
                                  struct net_device *dev)
 {
index af4c10e..cd6018a 100644 (file)
@@ -1232,7 +1232,7 @@ void ip_vs_conn_expire_now(struct ip_vs_conn *cp);
 const char *ip_vs_state_name(__u16 proto, int state);
 
 void ip_vs_tcp_conn_listen(struct ip_vs_conn *cp);
-int ip_vs_check_template(struct ip_vs_conn *ct);
+int ip_vs_check_template(struct ip_vs_conn *ct, struct ip_vs_dest *cdest);
 void ip_vs_random_dropentry(struct netns_ipvs *ipvs);
 int ip_vs_conn_init(void);
 void ip_vs_conn_cleanup(void);
index 9c5638a..0dbce55 100644 (file)
@@ -28,8 +28,8 @@ struct nf_queue_handler {
                                                struct nf_hook_ops *ops);
 };
 
-void nf_register_queue_handler(const struct nf_queue_handler *qh);
-void nf_unregister_queue_handler(void);
+void nf_register_queue_handler(struct net *net, const struct nf_queue_handler *qh);
+void nf_unregister_queue_handler(struct net *net);
 void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);
 
 void nf_queue_entry_get_refs(struct nf_queue_entry *entry);
index 38aa498..36d7235 100644 (file)
@@ -5,11 +5,13 @@
 
 struct proc_dir_entry;
 struct nf_logger;
+struct nf_queue_handler;
 
 struct netns_nf {
 #if defined CONFIG_PROC_FS
        struct proc_dir_entry *proc_netfilter;
 #endif
+       const struct nf_queue_handler __rcu *queue_handler;
        const struct nf_logger __rcu *nf_loggers[NFPROTO_NUMPROTO];
 #ifdef CONFIG_SYSCTL
        struct ctl_table_header *nf_log_dir_header;
index 0f7efa8..3722dda 100644 (file)
@@ -392,16 +392,20 @@ struct tc_cls_u32_offload {
        };
 };
 
-static inline bool tc_should_offload(struct net_device *dev, u32 flags)
+static inline bool tc_should_offload(const struct net_device *dev,
+                                    const struct tcf_proto *tp, u32 flags)
 {
+       const struct Qdisc *sch = tp->q;
+       const struct Qdisc_class_ops *cops = sch->ops->cl_ops;
+
        if (!(dev->features & NETIF_F_HW_TC))
                return false;
-
        if (flags & TCA_CLS_FLAGS_SKIP_HW)
                return false;
-
        if (!dev->netdev_ops->ndo_setup_tc)
                return false;
+       if (cops && cops->tcf_cl_offload)
+               return cops->tcf_cl_offload(tp->classid);
 
        return true;
 }
index 401038d..fea53f4 100644 (file)
@@ -61,6 +61,7 @@ psched_tdiff_bounded(psched_time_t tv1, psched_time_t tv2, psched_time_t bound)
 }
 
 struct qdisc_watchdog {
+       u64             last_expires;
        struct hrtimer  timer;
        struct Qdisc    *qdisc;
 };
index a1fd76c..62d5531 100644 (file)
@@ -168,6 +168,7 @@ struct Qdisc_class_ops {
 
        /* Filter manipulation */
        struct tcf_proto __rcu ** (*tcf_chain)(struct Qdisc *, unsigned long);
+       bool                    (*tcf_cl_offload)(u32 classid);
        unsigned long           (*bind_tcf)(struct Qdisc *, unsigned long,
                                        u32 classid);
        void                    (*unbind_tcf)(struct Qdisc *, unsigned long);
@@ -691,9 +692,11 @@ static inline struct sk_buff *qdisc_peek_dequeued(struct Qdisc *sch)
        /* we can reuse ->gso_skb because peek isn't called for root qdiscs */
        if (!sch->gso_skb) {
                sch->gso_skb = sch->dequeue(sch);
-               if (sch->gso_skb)
+               if (sch->gso_skb) {
                        /* it's still part of the queue */
+                       qdisc_qstats_backlog_inc(sch, sch->gso_skb);
                        sch->q.qlen++;
+               }
        }
 
        return sch->gso_skb;
@@ -706,6 +709,7 @@ static inline struct sk_buff *qdisc_dequeue_peeked(struct Qdisc *sch)
 
        if (skb) {
                sch->gso_skb = NULL;
+               qdisc_qstats_backlog_dec(sch, skb);
                sch->q.qlen--;
        } else {
                skb = sch->dequeue(sch);
index 432bed5..7e440d4 100644 (file)
@@ -217,10 +217,10 @@ enum ib_device_cap_flags {
        IB_DEVICE_CROSS_CHANNEL         = (1 << 27),
        IB_DEVICE_MANAGED_FLOW_STEERING         = (1 << 29),
        IB_DEVICE_SIGNATURE_HANDOVER            = (1 << 30),
-       IB_DEVICE_ON_DEMAND_PAGING              = (1 << 31),
+       IB_DEVICE_ON_DEMAND_PAGING              = (1ULL << 31),
        IB_DEVICE_SG_GAPS_REG                   = (1ULL << 32),
-       IB_DEVICE_VIRTUAL_FUNCTION              = ((u64)1 << 33),
-       IB_DEVICE_RAW_SCATTER_FCS               = ((u64)1 << 34),
+       IB_DEVICE_VIRTUAL_FUNCTION              = (1ULL << 33),
+       IB_DEVICE_RAW_SCATTER_FCS               = (1ULL << 34),
 };
 
 enum ib_signature_prot_cap {
index 16274e2..9c9a27d 100644 (file)
@@ -203,7 +203,9 @@ struct rvt_driver_provided {
 
        /*
         * Allocate a private queue pair data structure for driver specific
-        * information which is opaque to rdmavt.
+        * information which is opaque to rdmavt.  Errors are returned via
+        * ERR_PTR(err).  The driver is free to return NULL or a valid
+        * pointer.
         */
        void * (*qp_priv_alloc)(struct rvt_dev_info *rdi, struct rvt_qp *qp,
                                gfp_t gfp);
index 23c6960..2bdd1e3 100644 (file)
@@ -118,7 +118,7 @@ struct btrfs_ioctl_vol_args_v2 {
        };
        union {
                char name[BTRFS_SUBVOL_NAME_MAX + 1];
-               u64 devid;
+               __u64 devid;
        };
 };
 
index 9222db8..5f030b4 100644 (file)
@@ -1353,6 +1353,15 @@ enum ethtool_link_mode_bit_indices {
        ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT = 28,
        ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT = 29,
        ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT = 30,
+       ETHTOOL_LINK_MODE_25000baseCR_Full_BIT  = 31,
+       ETHTOOL_LINK_MODE_25000baseKR_Full_BIT  = 32,
+       ETHTOOL_LINK_MODE_25000baseSR_Full_BIT  = 33,
+       ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT = 34,
+       ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT = 35,
+       ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT        = 36,
+       ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT        = 37,
+       ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT        = 38,
+       ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT    = 39,
 
        /* Last allowed bit for __ETHTOOL_LINK_MODE_LEGACY_MASK is bit
         * 31. Please do NOT define any SUPPORTED_* or ADVERTISED_*
@@ -1361,7 +1370,7 @@ enum ethtool_link_mode_bit_indices {
         */
 
        __ETHTOOL_LINK_MODE_LAST
-         = ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT,
+         = ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT,
 };
 
 #define __ETHTOOL_LINK_MODE_LEGACY_MASK(base_name)     \
index ca1054d..72a04a0 100644 (file)
@@ -1,5 +1,5 @@
 #ifndef _UAPI_LINUX_GTP_H_
-#define _UAPI_LINUX_GTP_H__
+#define _UAPI_LINUX_GTP_H_
 
 enum gtp_genl_cmds {
        GTP_CMD_NEWPDP,
index eba5914..f4297c8 100644 (file)
@@ -145,6 +145,8 @@ enum {
        TCA_POLICE_PEAKRATE,
        TCA_POLICE_AVRATE,
        TCA_POLICE_RESULT,
+       TCA_POLICE_TM,
+       TCA_POLICE_PAD,
        __TCA_POLICE_MAX
 #define TCA_POLICE_RESULT TCA_POLICE_RESULT
 };
@@ -173,7 +175,7 @@ enum {
        TCA_U32_DIVISOR,
        TCA_U32_SEL,
        TCA_U32_POLICE,
-       TCA_U32_ACT,   
+       TCA_U32_ACT,
        TCA_U32_INDEV,
        TCA_U32_PCNT,
        TCA_U32_MARK,
index a7f2770..691984c 100644 (file)
@@ -1,5 +1,6 @@
 # UAPI Header export list
 header-y += asequencer.h
+header-y += asoc.h
 header-y += asound.h
 header-y += asound_fm.h
 header-y += compress_offload.h
@@ -10,3 +11,5 @@ header-y += hdsp.h
 header-y += hdspm.h
 header-y += sb16_csp.h
 header-y += sfnt_info.h
+header-y += tlv.h
+header-y += usb_stream.h
index 4c17fda..eae02aa 100644 (file)
@@ -453,7 +453,7 @@ void __init __weak smp_setup_processor_id(void)
 }
 
 # if THREAD_SIZE >= PAGE_SIZE
-void __init __weak thread_info_cache_init(void)
+void __init __weak thread_stack_cache_init(void)
 {
 }
 #endif
@@ -627,7 +627,7 @@ asmlinkage __visible void __init start_kernel(void)
        /* Should be run before the first non-init thread is created */
        init_espfix_bsp();
 #endif
-       thread_info_cache_init();
+       thread_stack_cache_init();
        cred_init();
        fork_init();
        proc_caches_init();
@@ -708,11 +708,13 @@ static bool __init_or_module initcall_blacklisted(initcall_t fn)
 {
        struct blacklist_entry *entry;
        char fn_name[KSYM_SYMBOL_LEN];
+       unsigned long addr;
 
        if (list_empty(&blacklisted_initcalls))
                return false;
 
-       sprint_symbol_no_offset(fn_name, (unsigned long)fn);
+       addr = (unsigned long) dereference_function_descriptor(fn);
+       sprint_symbol_no_offset(fn_name, addr);
 
        list_for_each_entry(entry, &blacklisted_initcalls, next) {
                if (!strcmp(fn_name, entry->buf)) {
index 04be702..318858e 100644 (file)
@@ -365,7 +365,6 @@ static struct file_system_type bpf_fs_type = {
        .name           = "bpf",
        .mount          = bpf_mount,
        .kill_sb        = kill_litter_super,
-       .fs_flags       = FS_USERNS_MOUNT,
 };
 
 MODULE_ALIAS_FS("bpf");
index 274450e..9c51ec3 100644 (file)
@@ -3862,10 +3862,8 @@ static void _free_event(struct perf_event *event)
        if (event->ctx)
                put_ctx(event->ctx);
 
-       if (event->pmu) {
-               exclusive_event_destroy(event);
-               module_put(event->pmu->module);
-       }
+       exclusive_event_destroy(event);
+       module_put(event->pmu->module);
 
        call_rcu(&event->rcu_head, free_event_rcu);
 }
index 5c2c355..4a7ec0c 100644 (file)
@@ -148,18 +148,18 @@ static inline void free_task_struct(struct task_struct *tsk)
 }
 #endif
 
-void __weak arch_release_thread_info(struct thread_info *ti)
+void __weak arch_release_thread_stack(unsigned long *stack)
 {
 }
 
-#ifndef CONFIG_ARCH_THREAD_INFO_ALLOCATOR
+#ifndef CONFIG_ARCH_THREAD_STACK_ALLOCATOR
 
 /*
  * Allocate pages if THREAD_SIZE is >= PAGE_SIZE, otherwise use a
  * kmemcache based allocator.
  */
 # if THREAD_SIZE >= PAGE_SIZE
-static struct thread_info *alloc_thread_info_node(struct task_struct *tsk,
+static unsigned long *alloc_thread_stack_node(struct task_struct *tsk,
                                                  int node)
 {
        struct page *page = alloc_kmem_pages_node(node, THREADINFO_GFP,
@@ -172,33 +172,33 @@ static struct thread_info *alloc_thread_info_node(struct task_struct *tsk,
        return page ? page_address(page) : NULL;
 }
 
-static inline void free_thread_info(struct thread_info *ti)
+static inline void free_thread_stack(unsigned long *stack)
 {
-       struct page *page = virt_to_page(ti);
+       struct page *page = virt_to_page(stack);
 
        memcg_kmem_update_page_stat(page, MEMCG_KERNEL_STACK,
                                    -(1 << THREAD_SIZE_ORDER));
        __free_kmem_pages(page, THREAD_SIZE_ORDER);
 }
 # else
-static struct kmem_cache *thread_info_cache;
+static struct kmem_cache *thread_stack_cache;
 
-static struct thread_info *alloc_thread_info_node(struct task_struct *tsk,
+static unsigned long *alloc_thread_stack_node(struct task_struct *tsk,
                                                  int node)
 {
-       return kmem_cache_alloc_node(thread_info_cache, THREADINFO_GFP, node);
+       return kmem_cache_alloc_node(thread_stack_cache, THREADINFO_GFP, node);
 }
 
-static void free_thread_info(struct thread_info *ti)
+static void free_thread_stack(unsigned long *stack)
 {
-       kmem_cache_free(thread_info_cache, ti);
+       kmem_cache_free(thread_stack_cache, stack);
 }
 
-void thread_info_cache_init(void)
+void thread_stack_cache_init(void)
 {
-       thread_info_cache = kmem_cache_create("thread_info", THREAD_SIZE,
+       thread_stack_cache = kmem_cache_create("thread_stack", THREAD_SIZE,
                                              THREAD_SIZE, 0, NULL);
-       BUG_ON(thread_info_cache == NULL);
+       BUG_ON(thread_stack_cache == NULL);
 }
 # endif
 #endif
@@ -221,9 +221,9 @@ struct kmem_cache *vm_area_cachep;
 /* SLAB cache for mm_struct structures (tsk->mm) */
 static struct kmem_cache *mm_cachep;
 
-static void account_kernel_stack(struct thread_info *ti, int account)
+static void account_kernel_stack(unsigned long *stack, int account)
 {
-       struct zone *zone = page_zone(virt_to_page(ti));
+       struct zone *zone = page_zone(virt_to_page(stack));
 
        mod_zone_page_state(zone, NR_KERNEL_STACK, account);
 }
@@ -231,8 +231,8 @@ static void account_kernel_stack(struct thread_info *ti, int account)
 void free_task(struct task_struct *tsk)
 {
        account_kernel_stack(tsk->stack, -1);
-       arch_release_thread_info(tsk->stack);
-       free_thread_info(tsk->stack);
+       arch_release_thread_stack(tsk->stack);
+       free_thread_stack(tsk->stack);
        rt_mutex_debug_task_free(tsk);
        ftrace_graph_exit_task(tsk);
        put_seccomp_filter(tsk);
@@ -343,7 +343,7 @@ void set_task_stack_end_magic(struct task_struct *tsk)
 static struct task_struct *dup_task_struct(struct task_struct *orig, int node)
 {
        struct task_struct *tsk;
-       struct thread_info *ti;
+       unsigned long *stack;
        int err;
 
        if (node == NUMA_NO_NODE)
@@ -352,15 +352,15 @@ static struct task_struct *dup_task_struct(struct task_struct *orig, int node)
        if (!tsk)
                return NULL;
 
-       ti = alloc_thread_info_node(tsk, node);
-       if (!ti)
+       stack = alloc_thread_stack_node(tsk, node);
+       if (!stack)
                goto free_tsk;
 
        err = arch_dup_task_struct(tsk, orig);
        if (err)
-               goto free_ti;
+               goto free_stack;
 
-       tsk->stack = ti;
+       tsk->stack = stack;
 #ifdef CONFIG_SECCOMP
        /*
         * We must handle setting up seccomp filters once we're under
@@ -392,14 +392,14 @@ static struct task_struct *dup_task_struct(struct task_struct *orig, int node)
        tsk->task_frag.page = NULL;
        tsk->wake_q.next = NULL;
 
-       account_kernel_stack(ti, 1);
+       account_kernel_stack(stack, 1);
 
        kcov_task_init(tsk);
 
        return tsk;
 
-free_ti:
-       free_thread_info(ti);
+free_stack:
+       free_thread_stack(stack);
 free_tsk:
        free_task_struct(tsk);
        return NULL;
index ee25f5b..33664f7 100644 (file)
@@ -469,7 +469,7 @@ get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, int rw)
 {
        unsigned long address = (unsigned long)uaddr;
        struct mm_struct *mm = current->mm;
-       struct page *page;
+       struct page *page, *tail;
        struct address_space *mapping;
        int err, ro = 0;
 
@@ -530,7 +530,15 @@ again:
         * considered here and page lock forces unnecessarily serialization
         * From this point on, mapping will be re-verified if necessary and
         * page lock will be acquired only if it is unavoidable
-        */
+        *
+        * Mapping checks require the head page for any compound page so the
+        * head page and mapping is looked up now. For anonymous pages, it
+        * does not matter if the page splits in the future as the key is
+        * based on the address. For filesystem-backed pages, the tail is
+        * required as the index of the page determines the key. For
+        * base pages, there is no tail page and tail == page.
+        */
+       tail = page;
        page = compound_head(page);
        mapping = READ_ONCE(page->mapping);
 
@@ -654,7 +662,7 @@ again:
 
                key->both.offset |= FUT_OFF_INODE; /* inode-based key */
                key->shared.inode = inode;
-               key->shared.pgoff = basepage_index(page);
+               key->shared.pgoff = basepage_index(tail);
                rcu_read_unlock();
        }
 
index c427422..89b49f6 100644 (file)
@@ -125,7 +125,7 @@ int irq_destroy_ipi(unsigned int irq, const struct cpumask *dest)
 
        domain = data->domain;
        if (WARN_ON(domain == NULL))
-               return;
+               return -EINVAL;
 
        if (!irq_domain_is_ipi(domain)) {
                pr_warn("Trying to destroy a non IPI domain!\n");
index 05254ee..4b353e0 100644 (file)
@@ -58,13 +58,36 @@ static void jump_label_update(struct static_key *key);
 
 void static_key_slow_inc(struct static_key *key)
 {
+       int v, v1;
+
        STATIC_KEY_CHECK_USE();
-       if (atomic_inc_not_zero(&key->enabled))
-               return;
+
+       /*
+        * Careful if we get concurrent static_key_slow_inc() calls;
+        * later calls must wait for the first one to _finish_ the
+        * jump_label_update() process.  At the same time, however,
+        * the jump_label_update() call below wants to see
+        * static_key_enabled(&key) for jumps to be updated properly.
+        *
+        * So give a special meaning to negative key->enabled: it sends
+        * static_key_slow_inc() down the slow path, and it is non-zero
+        * so it counts as "enabled" in jump_label_update().  Note that
+        * atomic_inc_unless_negative() checks >= 0, so roll our own.
+        */
+       for (v = atomic_read(&key->enabled); v > 0; v = v1) {
+               v1 = atomic_cmpxchg(&key->enabled, v, v + 1);
+               if (likely(v1 == v))
+                       return;
+       }
 
        jump_label_lock();
-       if (atomic_inc_return(&key->enabled) == 1)
+       if (atomic_read(&key->enabled) == 0) {
+               atomic_set(&key->enabled, -1);
                jump_label_update(key);
+               atomic_set(&key->enabled, 1);
+       } else {
+               atomic_inc(&key->enabled);
+       }
        jump_label_unlock();
 }
 EXPORT_SYMBOL_GPL(static_key_slow_inc);
@@ -72,6 +95,13 @@ EXPORT_SYMBOL_GPL(static_key_slow_inc);
 static void __static_key_slow_dec(struct static_key *key,
                unsigned long rate_limit, struct delayed_work *work)
 {
+       /*
+        * The negative count check is valid even when a negative
+        * key->enabled is in use by static_key_slow_inc(); a
+        * __static_key_slow_dec() before the first static_key_slow_inc()
+        * returns is unbalanced, because all other static_key_slow_inc()
+        * instances block while the update is in progress.
+        */
        if (!atomic_dec_and_mutex_lock(&key->enabled, &jump_label_mutex)) {
                WARN(atomic_read(&key->enabled) < 0,
                     "jump label: negative count!\n");
index a02f2dd..8d44b3f 100644 (file)
@@ -264,7 +264,12 @@ static const struct file_operations kcov_fops = {
 
 static int __init kcov_init(void)
 {
-       if (!debugfs_create_file("kcov", 0600, NULL, NULL, &kcov_fops)) {
+       /*
+        * The kcov debugfs file won't ever get removed and thus,
+        * there is no need to protect it against removal races. The
+        * use of debugfs_create_file_unsafe() is actually safe here.
+        */
+       if (!debugfs_create_file_unsafe("kcov", 0600, NULL, NULL, &kcov_fops)) {
                pr_err("failed to create kcov in debugfs\n");
                return -ENOMEM;
        }
index 3ef3736..9c951fa 100644 (file)
@@ -49,21 +49,21 @@ void debug_mutex_free_waiter(struct mutex_waiter *waiter)
 }
 
 void debug_mutex_add_waiter(struct mutex *lock, struct mutex_waiter *waiter,
-                           struct thread_info *ti)
+                           struct task_struct *task)
 {
        SMP_DEBUG_LOCKS_WARN_ON(!spin_is_locked(&lock->wait_lock));
 
        /* Mark the current thread as blocked on the lock: */
-       ti->task->blocked_on = waiter;
+       task->blocked_on = waiter;
 }
 
 void mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter,
-                        struct thread_info *ti)
+                        struct task_struct *task)
 {
        DEBUG_LOCKS_WARN_ON(list_empty(&waiter->list));
-       DEBUG_LOCKS_WARN_ON(waiter->task != ti->task);
-       DEBUG_LOCKS_WARN_ON(ti->task->blocked_on != waiter);
-       ti->task->blocked_on = NULL;
+       DEBUG_LOCKS_WARN_ON(waiter->task != task);
+       DEBUG_LOCKS_WARN_ON(task->blocked_on != waiter);
+       task->blocked_on = NULL;
 
        list_del_init(&waiter->list);
        waiter->task = NULL;
index 0799fd3..d06ae3b 100644 (file)
@@ -20,9 +20,9 @@ extern void debug_mutex_wake_waiter(struct mutex *lock,
 extern void debug_mutex_free_waiter(struct mutex_waiter *waiter);
 extern void debug_mutex_add_waiter(struct mutex *lock,
                                   struct mutex_waiter *waiter,
-                                  struct thread_info *ti);
+                                  struct task_struct *task);
 extern void mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter,
-                               struct thread_info *ti);
+                               struct task_struct *task);
 extern void debug_mutex_unlock(struct mutex *lock);
 extern void debug_mutex_init(struct mutex *lock, const char *name,
                             struct lock_class_key *key);
index e364b42..a70b90d 100644 (file)
@@ -486,9 +486,6 @@ __ww_mutex_lock_check_stamp(struct mutex *lock, struct ww_acquire_ctx *ctx)
        if (!hold_ctx)
                return 0;
 
-       if (unlikely(ctx == hold_ctx))
-               return -EALREADY;
-
        if (ctx->stamp - hold_ctx->stamp <= LONG_MAX &&
            (ctx->stamp != hold_ctx->stamp || ctx > hold_ctx)) {
 #ifdef CONFIG_DEBUG_MUTEXES
@@ -514,6 +511,12 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
        unsigned long flags;
        int ret;
 
+       if (use_ww_ctx) {
+               struct ww_mutex *ww = container_of(lock, struct ww_mutex, base);
+               if (unlikely(ww_ctx == READ_ONCE(ww->ctx)))
+                       return -EALREADY;
+       }
+
        preempt_disable();
        mutex_acquire_nest(&lock->dep_map, subclass, 0, nest_lock, ip);
 
@@ -534,7 +537,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
                goto skip_wait;
 
        debug_mutex_lock_common(lock, &waiter);
-       debug_mutex_add_waiter(lock, &waiter, task_thread_info(task));
+       debug_mutex_add_waiter(lock, &waiter, task);
 
        /* add waiting tasks to the end of the waitqueue (FIFO): */
        list_add_tail(&waiter.list, &lock->wait_list);
@@ -581,7 +584,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
        }
        __set_task_state(task, TASK_RUNNING);
 
-       mutex_remove_waiter(lock, &waiter, current_thread_info());
+       mutex_remove_waiter(lock, &waiter, task);
        /* set it to 0 if there are no waiters left: */
        if (likely(list_empty(&lock->wait_list)))
                atomic_set(&lock->count, 0);
@@ -602,7 +605,7 @@ skip_wait:
        return 0;
 
 err:
-       mutex_remove_waiter(lock, &waiter, task_thread_info(task));
+       mutex_remove_waiter(lock, &waiter, task);
        spin_unlock_mutex(&lock->wait_lock, flags);
        debug_mutex_free_waiter(&waiter);
        mutex_release(&lock->dep_map, 1, ip);
index 5cda397..a68bae5 100644 (file)
@@ -13,7 +13,7 @@
                do { spin_lock(lock); (void)(flags); } while (0)
 #define spin_unlock_mutex(lock, flags) \
                do { spin_unlock(lock); (void)(flags); } while (0)
-#define mutex_remove_waiter(lock, waiter, ti) \
+#define mutex_remove_waiter(lock, waiter, task) \
                __list_del((waiter)->list.prev, (waiter)->list.next)
 
 #ifdef CONFIG_MUTEX_SPIN_ON_OWNER
index ce2f75e..5fc8c31 100644 (file)
@@ -267,6 +267,66 @@ static __always_inline u32  __pv_wait_head_or_lock(struct qspinlock *lock,
 #define queued_spin_lock_slowpath      native_queued_spin_lock_slowpath
 #endif
 
+/*
+ * queued_spin_lock_slowpath() can (load-)ACQUIRE the lock before
+ * issuing an _unordered_ store to set _Q_LOCKED_VAL.
+ *
+ * This means that the store can be delayed, but no later than the
+ * store-release from the unlock. This means that simply observing
+ * _Q_LOCKED_VAL is not sufficient to determine if the lock is acquired.
+ *
+ * There are two paths that can issue the unordered store:
+ *
+ *  (1) clear_pending_set_locked():    *,1,0 -> *,0,1
+ *
+ *  (2) set_locked():                  t,0,0 -> t,0,1 ; t != 0
+ *      atomic_cmpxchg_relaxed():      t,0,0 -> 0,0,1
+ *
+ * However, in both cases we have other !0 state we've set before to queue
+ * ourseves:
+ *
+ * For (1) we have the atomic_cmpxchg_acquire() that set _Q_PENDING_VAL, our
+ * load is constrained by that ACQUIRE to not pass before that, and thus must
+ * observe the store.
+ *
+ * For (2) we have a more intersting scenario. We enqueue ourselves using
+ * xchg_tail(), which ends up being a RELEASE. This in itself is not
+ * sufficient, however that is followed by an smp_cond_acquire() on the same
+ * word, giving a RELEASE->ACQUIRE ordering. This again constrains our load and
+ * guarantees we must observe that store.
+ *
+ * Therefore both cases have other !0 state that is observable before the
+ * unordered locked byte store comes through. This means we can use that to
+ * wait for the lock store, and then wait for an unlock.
+ */
+#ifndef queued_spin_unlock_wait
+void queued_spin_unlock_wait(struct qspinlock *lock)
+{
+       u32 val;
+
+       for (;;) {
+               val = atomic_read(&lock->val);
+
+               if (!val) /* not locked, we're done */
+                       goto done;
+
+               if (val & _Q_LOCKED_MASK) /* locked, go wait for unlock */
+                       break;
+
+               /* not locked, but pending, wait until we observe the lock */
+               cpu_relax();
+       }
+
+       /* any unlock is good */
+       while (atomic_read(&lock->val) & _Q_LOCKED_MASK)
+               cpu_relax();
+
+done:
+       smp_rmb(); /* CTRL + RMB -> ACQUIRE */
+}
+EXPORT_SYMBOL(queued_spin_unlock_wait);
+#endif
+
 #endif /* _GEN_PV_LOCK_SLOWPATH */
 
 /**
index df058be..0c2ee97 100644 (file)
@@ -146,6 +146,18 @@ int freeze_processes(void)
        if (!error && !oom_killer_disable())
                error = -EBUSY;
 
+       /*
+        * There is a hard to fix race between oom_reaper kernel thread
+        * and oom_killer_disable. oom_reaper calls exit_oom_victim
+        * before the victim reaches exit_mm so try to freeze all the tasks
+        * again and catch such a left over task.
+        */
+       if (!error) {
+               pr_info("Double checking all user space processes after OOM killer disable... ");
+               error = try_to_freeze_tasks(true);
+               pr_cont("\n");
+       }
+
        if (error)
                thaw_processes();
        return error;
index 074994b..04d7cf3 100644 (file)
@@ -614,6 +614,7 @@ free_bufs:
 
        kref_put(&chan->kref, relay_destroy_channel);
        mutex_unlock(&relay_channels_mutex);
+       kfree(chan);
        return NULL;
 }
 EXPORT_SYMBOL_GPL(relay_open);
index 7f2cae4..51d7105 100644 (file)
@@ -1536,7 +1536,9 @@ static int select_fallback_rq(int cpu, struct task_struct *p)
        for (;;) {
                /* Any allowed, online CPU? */
                for_each_cpu(dest_cpu, tsk_cpus_allowed(p)) {
-                       if (!cpu_active(dest_cpu))
+                       if (!(p->flags & PF_KTHREAD) && !cpu_active(dest_cpu))
+                               continue;
+                       if (!cpu_online(dest_cpu))
                                continue;
                        goto out;
                }
@@ -2253,9 +2255,11 @@ int sysctl_numa_balancing(struct ctl_table *table, int write,
 #endif
 #endif
 
+#ifdef CONFIG_SCHEDSTATS
+
 DEFINE_STATIC_KEY_FALSE(sched_schedstats);
+static bool __initdata __sched_schedstats = false;
 
-#ifdef CONFIG_SCHEDSTATS
 static void set_schedstats(bool enabled)
 {
        if (enabled)
@@ -2278,11 +2282,16 @@ static int __init setup_schedstats(char *str)
        if (!str)
                goto out;
 
+       /*
+        * This code is called before jump labels have been set up, so we can't
+        * change the static branch directly just yet.  Instead set a temporary
+        * variable so init_schedstats() can do it later.
+        */
        if (!strcmp(str, "enable")) {
-               set_schedstats(true);
+               __sched_schedstats = true;
                ret = 1;
        } else if (!strcmp(str, "disable")) {
-               set_schedstats(false);
+               __sched_schedstats = false;
                ret = 1;
        }
 out:
@@ -2293,6 +2302,11 @@ out:
 }
 __setup("schedstats=", setup_schedstats);
 
+static void __init init_schedstats(void)
+{
+       set_schedstats(__sched_schedstats);
+}
+
 #ifdef CONFIG_PROC_SYSCTL
 int sysctl_schedstats(struct ctl_table *table, int write,
                         void __user *buffer, size_t *lenp, loff_t *ppos)
@@ -2313,8 +2327,10 @@ int sysctl_schedstats(struct ctl_table *table, int write,
                set_schedstats(state);
        return err;
 }
-#endif
-#endif
+#endif /* CONFIG_PROC_SYSCTL */
+#else  /* !CONFIG_SCHEDSTATS */
+static inline void init_schedstats(void) {}
+#endif /* CONFIG_SCHEDSTATS */
 
 /*
  * fork()/clone()-time setup:
@@ -2521,10 +2537,9 @@ void wake_up_new_task(struct task_struct *p)
         */
        set_task_cpu(p, select_task_rq(p, task_cpu(p), SD_BALANCE_FORK, 0));
 #endif
-       /* Post initialize new task's util average when its cfs_rq is set */
+       rq = __task_rq_lock(p, &rf);
        post_init_entity_util_avg(&p->se);
 
-       rq = __task_rq_lock(p, &rf);
        activate_task(rq, p, 0);
        p->on_rq = TASK_ON_RQ_QUEUED;
        trace_sched_wakeup_new(p);
@@ -3156,7 +3171,8 @@ static noinline void __schedule_bug(struct task_struct *prev)
 static inline void schedule_debug(struct task_struct *prev)
 {
 #ifdef CONFIG_SCHED_STACK_END_CHECK
-       BUG_ON(task_stack_end_corrupted(prev));
+       if (task_stack_end_corrupted(prev))
+               panic("corrupted stack end detected inside scheduler\n");
 #endif
 
        if (unlikely(in_atomic_preempt_off())) {
@@ -5133,14 +5149,16 @@ void show_state_filter(unsigned long state_filter)
                /*
                 * reset the NMI-timeout, listing all files on a slow
                 * console might take a lot of time:
+                * Also, reset softlockup watchdogs on all CPUs, because
+                * another CPU might be blocked waiting for us to process
+                * an IPI.
                 */
                touch_nmi_watchdog();
+               touch_all_softlockup_watchdogs();
                if (!state_filter || (p->state & state_filter))
                        sched_show_task(p);
        }
 
-       touch_all_softlockup_watchdogs();
-
 #ifdef CONFIG_SCHED_DEBUG
        if (!state_filter)
                sysrq_sched_debug_show();
@@ -7487,6 +7505,8 @@ void __init sched_init(void)
 #endif
        init_sched_fair_class();
 
+       init_schedstats();
+
        scheduler_running = 1;
 }
 
index cf905f6..0368c39 100644 (file)
@@ -427,19 +427,12 @@ print_task(struct seq_file *m, struct rq *rq, struct task_struct *p)
                SPLIT_NS(p->se.vruntime),
                (long long)(p->nvcsw + p->nivcsw),
                p->prio);
-#ifdef CONFIG_SCHEDSTATS
-       if (schedstat_enabled()) {
-               SEQ_printf(m, "%9Ld.%06ld %9Ld.%06ld %9Ld.%06ld",
-                       SPLIT_NS(p->se.statistics.wait_sum),
-                       SPLIT_NS(p->se.sum_exec_runtime),
-                       SPLIT_NS(p->se.statistics.sum_sleep_runtime));
-       }
-#else
+
        SEQ_printf(m, "%9Ld.%06ld %9Ld.%06ld %9Ld.%06ld",
-               0LL, 0L,
+               SPLIT_NS(schedstat_val(p, se.statistics.wait_sum)),
                SPLIT_NS(p->se.sum_exec_runtime),
-               0LL, 0L);
-#endif
+               SPLIT_NS(schedstat_val(p, se.statistics.sum_sleep_runtime)));
+
 #ifdef CONFIG_NUMA_BALANCING
        SEQ_printf(m, " %d %d", task_node(p), task_numa_group_id(p));
 #endif
index 218f8e8..bdcbeea 100644 (file)
@@ -2904,6 +2904,23 @@ static inline void cfs_rq_util_change(struct cfs_rq *cfs_rq)
        }
 }
 
+/*
+ * Unsigned subtract and clamp on underflow.
+ *
+ * Explicitly do a load-store to ensure the intermediate value never hits
+ * memory. This allows lockless observations without ever seeing the negative
+ * values.
+ */
+#define sub_positive(_ptr, _val) do {                          \
+       typeof(_ptr) ptr = (_ptr);                              \
+       typeof(*ptr) val = (_val);                              \
+       typeof(*ptr) res, var = READ_ONCE(*ptr);                \
+       res = var - val;                                        \
+       if (res > var)                                          \
+               res = 0;                                        \
+       WRITE_ONCE(*ptr, res);                                  \
+} while (0)
+
 /* Group cfs_rq's load_avg is used for task_h_load and update_cfs_share */
 static inline int
 update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq, bool update_freq)
@@ -2913,15 +2930,15 @@ update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq, bool update_freq)
 
        if (atomic_long_read(&cfs_rq->removed_load_avg)) {
                s64 r = atomic_long_xchg(&cfs_rq->removed_load_avg, 0);
-               sa->load_avg = max_t(long, sa->load_avg - r, 0);
-               sa->load_sum = max_t(s64, sa->load_sum - r * LOAD_AVG_MAX, 0);
+               sub_positive(&sa->load_avg, r);
+               sub_positive(&sa->load_sum, r * LOAD_AVG_MAX);
                removed_load = 1;
        }
 
        if (atomic_long_read(&cfs_rq->removed_util_avg)) {
                long r = atomic_long_xchg(&cfs_rq->removed_util_avg, 0);
-               sa->util_avg = max_t(long, sa->util_avg - r, 0);
-               sa->util_sum = max_t(s32, sa->util_sum - r * LOAD_AVG_MAX, 0);
+               sub_positive(&sa->util_avg, r);
+               sub_positive(&sa->util_sum, r * LOAD_AVG_MAX);
                removed_util = 1;
        }
 
@@ -2994,10 +3011,10 @@ static void detach_entity_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *s
                          &se->avg, se->on_rq * scale_load_down(se->load.weight),
                          cfs_rq->curr == se, NULL);
 
-       cfs_rq->avg.load_avg = max_t(long, cfs_rq->avg.load_avg - se->avg.load_avg, 0);
-       cfs_rq->avg.load_sum = max_t(s64,  cfs_rq->avg.load_sum - se->avg.load_sum, 0);
-       cfs_rq->avg.util_avg = max_t(long, cfs_rq->avg.util_avg - se->avg.util_avg, 0);
-       cfs_rq->avg.util_sum = max_t(s32,  cfs_rq->avg.util_sum - se->avg.util_sum, 0);
+       sub_positive(&cfs_rq->avg.load_avg, se->avg.load_avg);
+       sub_positive(&cfs_rq->avg.load_sum, se->avg.load_sum);
+       sub_positive(&cfs_rq->avg.util_avg, se->avg.util_avg);
+       sub_positive(&cfs_rq->avg.util_sum, se->avg.util_sum);
 
        cfs_rq_util_change(cfs_rq);
 }
@@ -3246,7 +3263,7 @@ static inline void check_schedstat_required(void)
                        trace_sched_stat_iowait_enabled()  ||
                        trace_sched_stat_blocked_enabled() ||
                        trace_sched_stat_runtime_enabled())  {
-               pr_warn_once("Scheduler tracepoints stat_sleep, stat_iowait, "
+               printk_deferred_once("Scheduler tracepoints stat_sleep, stat_iowait, "
                             "stat_blocked and stat_runtime require the "
                             "kernel parameter schedstats=enabled or "
                             "kernel.sched_schedstats=1\n");
@@ -4185,6 +4202,26 @@ static void check_enqueue_throttle(struct cfs_rq *cfs_rq)
        if (!cfs_bandwidth_used())
                return;
 
+       /* Synchronize hierarchical throttle counter: */
+       if (unlikely(!cfs_rq->throttle_uptodate)) {
+               struct rq *rq = rq_of(cfs_rq);
+               struct cfs_rq *pcfs_rq;
+               struct task_group *tg;
+
+               cfs_rq->throttle_uptodate = 1;
+
+               /* Get closest up-to-date node, because leaves go first: */
+               for (tg = cfs_rq->tg->parent; tg; tg = tg->parent) {
+                       pcfs_rq = tg->cfs_rq[cpu_of(rq)];
+                       if (pcfs_rq->throttle_uptodate)
+                               break;
+               }
+               if (tg) {
+                       cfs_rq->throttle_count = pcfs_rq->throttle_count;
+                       cfs_rq->throttled_clock_task = rq_clock_task(rq);
+               }
+       }
+
        /* an active group must be handled by the update_curr()->put() path */
        if (!cfs_rq->runtime_enabled || cfs_rq->curr)
                return;
@@ -4500,15 +4537,14 @@ static void dequeue_task_fair(struct rq *rq, struct task_struct *p, int flags)
 
                /* Don't dequeue parent if it has other entities besides us */
                if (cfs_rq->load.weight) {
+                       /* Avoid re-evaluating load for this entity: */
+                       se = parent_entity(se);
                        /*
                         * Bias pick_next to pick a task from this cfs_rq, as
                         * p is sleeping when it is within its sched_slice.
                         */
-                       if (task_sleep && parent_entity(se))
-                               set_next_buddy(parent_entity(se));
-
-                       /* avoid re-evaluating load for this entity */
-                       se = parent_entity(se);
+                       if (task_sleep && se && !throttled_hierarchy(cfs_rq))
+                               set_next_buddy(se);
                        break;
                }
                flags |= DEQUEUE_SLEEP;
@@ -8496,8 +8532,9 @@ void free_fair_sched_group(struct task_group *tg)
 
 int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent)
 {
-       struct cfs_rq *cfs_rq;
        struct sched_entity *se;
+       struct cfs_rq *cfs_rq;
+       struct rq *rq;
        int i;
 
        tg->cfs_rq = kzalloc(sizeof(cfs_rq) * nr_cpu_ids, GFP_KERNEL);
@@ -8512,6 +8549,8 @@ int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent)
        init_cfs_bandwidth(tg_cfs_bandwidth(tg));
 
        for_each_possible_cpu(i) {
+               rq = cpu_rq(i);
+
                cfs_rq = kzalloc_node(sizeof(struct cfs_rq),
                                      GFP_KERNEL, cpu_to_node(i));
                if (!cfs_rq)
@@ -8525,7 +8564,10 @@ int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent)
                init_cfs_rq(cfs_rq);
                init_tg_cfs_entry(tg, cfs_rq, se, i, parent->se[i]);
                init_entity_runnable_average(se);
+
+               raw_spin_lock_irq(&rq->lock);
                post_init_entity_util_avg(se);
+               raw_spin_unlock_irq(&rq->lock);
        }
 
        return 1;
index bd12c6c..c5aeedf 100644 (file)
@@ -127,7 +127,7 @@ static int call_cpuidle(struct cpuidle_driver *drv, struct cpuidle_device *dev,
  */
 static void cpuidle_idle_call(void)
 {
-       struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices);
+       struct cpuidle_device *dev = cpuidle_get_device();
        struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
        int next_state, entered_state;
 
index 72f1f30..7cbeb92 100644 (file)
@@ -437,7 +437,7 @@ struct cfs_rq {
 
        u64 throttled_clock, throttled_clock_task;
        u64 throttled_clock_task_time;
-       int throttled, throttle_count;
+       int throttled, throttle_count, throttle_uptodate;
        struct list_head throttled_list;
 #endif /* CONFIG_CFS_BANDWIDTH */
 #endif /* CONFIG_FAIR_GROUP_SCHED */
index 70b3b6a..78955cb 100644 (file)
@@ -33,6 +33,8 @@ rq_sched_info_dequeued(struct rq *rq, unsigned long long delta)
 # define schedstat_inc(rq, field)      do { if (schedstat_enabled()) { (rq)->field++; } } while (0)
 # define schedstat_add(rq, field, amt) do { if (schedstat_enabled()) { (rq)->field += (amt); } } while (0)
 # define schedstat_set(var, val)       do { if (schedstat_enabled()) { var = (val); } } while (0)
+# define schedstat_val(rq, field)      ((schedstat_enabled()) ? (rq)->field : 0)
+
 #else /* !CONFIG_SCHEDSTATS */
 static inline void
 rq_sched_info_arrive(struct rq *rq, unsigned long long delta)
@@ -47,6 +49,7 @@ rq_sched_info_depart(struct rq *rq, unsigned long long delta)
 # define schedstat_inc(rq, field)      do { } while (0)
 # define schedstat_add(rq, field, amt) do { } while (0)
 # define schedstat_set(var, val)       do { } while (0)
+# define schedstat_val(rq, field)      0
 #endif
 
 #ifdef CONFIG_SCHED_INFO
index 8c7392c..e99df0f 100644 (file)
@@ -425,6 +425,7 @@ void destroy_hrtimer_on_stack(struct hrtimer *timer)
 {
        debug_object_free(timer, &hrtimer_debug_descr);
 }
+EXPORT_SYMBOL_GPL(destroy_hrtimer_on_stack);
 
 #else
 static inline void debug_hrtimer_init(struct hrtimer *timer) { }
index 780bcbe..720b7bb 100644 (file)
@@ -198,7 +198,7 @@ static u64 bpf_perf_event_read(u64 r1, u64 index, u64 r3, u64 r4, u64 r5)
        if (unlikely(index >= array->map.max_entries))
                return -E2BIG;
 
-       file = (struct file *)array->ptrs[index];
+       file = READ_ONCE(array->ptrs[index]);
        if (unlikely(!file))
                return -ENOENT;
 
@@ -247,7 +247,7 @@ static u64 bpf_perf_event_output(u64 r1, u64 r2, u64 flags, u64 r4, u64 size)
        if (unlikely(index >= array->map.max_entries))
                return -E2BIG;
 
-       file = (struct file *)array->ptrs[index];
+       file = READ_ONCE(array->ptrs[index]);
        if (unlikely(!file))
                return -ENOENT;
 
index f96f038..ad1d616 100644 (file)
@@ -36,6 +36,10 @@ struct trace_bprintk_fmt {
 static inline struct trace_bprintk_fmt *lookup_format(const char *fmt)
 {
        struct trace_bprintk_fmt *pos;
+
+       if (!fmt)
+               return ERR_PTR(-EINVAL);
+
        list_for_each_entry(pos, &trace_bprintk_fmt_list, list) {
                if (!strcmp(pos->fmt, fmt))
                        return pos;
@@ -57,7 +61,8 @@ void hold_module_trace_bprintk_format(const char **start, const char **end)
        for (iter = start; iter < end; iter++) {
                struct trace_bprintk_fmt *tb_fmt = lookup_format(*iter);
                if (tb_fmt) {
-                       *iter = tb_fmt->fmt;
+                       if (!IS_ERR(tb_fmt))
+                               *iter = tb_fmt->fmt;
                        continue;
                }
 
index 77d7d03..b9cfdbf 100644 (file)
@@ -1841,6 +1841,9 @@ config TEST_BITMAP
 
          If unsure, say N.
 
+config TEST_UUID
+       tristate "Test functions located in the uuid module at runtime"
+
 config TEST_RHASHTABLE
        tristate "Perform selftest on resizable hash table"
        default n
index 499fb35..ff6a7a6 100644 (file)
@@ -58,6 +58,7 @@ obj-$(CONFIG_TEST_STATIC_KEYS) += test_static_keys.o
 obj-$(CONFIG_TEST_STATIC_KEYS) += test_static_key_base.o
 obj-$(CONFIG_TEST_PRINTF) += test_printf.o
 obj-$(CONFIG_TEST_BITMAP) += test_bitmap.o
+obj-$(CONFIG_TEST_UUID) += test_uuid.o
 
 ifeq ($(CONFIG_DEBUG_KOBJECT),y)
 CFLAGS_kobject.o += -DDEBUG
diff --git a/lib/test_uuid.c b/lib/test_uuid.c
new file mode 100644 (file)
index 0000000..547d312
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Test cases for lib/uuid.c module.
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/uuid.h>
+
+struct test_uuid_data {
+       const char *uuid;
+       uuid_le le;
+       uuid_be be;
+};
+
+static const struct test_uuid_data test_uuid_test_data[] = {
+       {
+               .uuid = "c33f4995-3701-450e-9fbf-206a2e98e576",
+               .le = UUID_LE(0xc33f4995, 0x3701, 0x450e, 0x9f, 0xbf, 0x20, 0x6a, 0x2e, 0x98, 0xe5, 0x76),
+               .be = UUID_BE(0xc33f4995, 0x3701, 0x450e, 0x9f, 0xbf, 0x20, 0x6a, 0x2e, 0x98, 0xe5, 0x76),
+       },
+       {
+               .uuid = "64b4371c-77c1-48f9-8221-29f054fc023b",
+               .le = UUID_LE(0x64b4371c, 0x77c1, 0x48f9, 0x82, 0x21, 0x29, 0xf0, 0x54, 0xfc, 0x02, 0x3b),
+               .be = UUID_BE(0x64b4371c, 0x77c1, 0x48f9, 0x82, 0x21, 0x29, 0xf0, 0x54, 0xfc, 0x02, 0x3b),
+       },
+       {
+               .uuid = "0cb4ddff-a545-4401-9d06-688af53e7f84",
+               .le = UUID_LE(0x0cb4ddff, 0xa545, 0x4401, 0x9d, 0x06, 0x68, 0x8a, 0xf5, 0x3e, 0x7f, 0x84),
+               .be = UUID_BE(0x0cb4ddff, 0xa545, 0x4401, 0x9d, 0x06, 0x68, 0x8a, 0xf5, 0x3e, 0x7f, 0x84),
+       },
+};
+
+static const char * const test_uuid_wrong_data[] = {
+       "c33f4995-3701-450e-9fbf206a2e98e576 ", /* no hyphen(s) */
+       "64b4371c-77c1-48f9-8221-29f054XX023b", /* invalid character(s) */
+       "0cb4ddff-a545-4401-9d06-688af53e",     /* not enough data */
+};
+
+static unsigned total_tests __initdata;
+static unsigned failed_tests __initdata;
+
+static void __init test_uuid_failed(const char *prefix, bool wrong, bool be,
+                                   const char *data, const char *actual)
+{
+       pr_err("%s test #%u %s %s data: '%s'\n",
+              prefix,
+              total_tests,
+              wrong ? "passed on wrong" : "failed on",
+              be ? "BE" : "LE",
+              data);
+       if (actual && *actual)
+               pr_err("%s test #%u actual data: '%s'\n",
+                      prefix,
+                      total_tests,
+                      actual);
+       failed_tests++;
+}
+
+static void __init test_uuid_test(const struct test_uuid_data *data)
+{
+       uuid_le le;
+       uuid_be be;
+       char buf[48];
+
+       /* LE */
+       total_tests++;
+       if (uuid_le_to_bin(data->uuid, &le))
+               test_uuid_failed("conversion", false, false, data->uuid, NULL);
+
+       total_tests++;
+       if (uuid_le_cmp(data->le, le)) {
+               sprintf(buf, "%pUl", &le);
+               test_uuid_failed("cmp", false, false, data->uuid, buf);
+       }
+
+       /* BE */
+       total_tests++;
+       if (uuid_be_to_bin(data->uuid, &be))
+               test_uuid_failed("conversion", false, true, data->uuid, NULL);
+
+       total_tests++;
+       if (uuid_be_cmp(data->be, be)) {
+               sprintf(buf, "%pUb", &be);
+               test_uuid_failed("cmp", false, true, data->uuid, buf);
+       }
+}
+
+static void __init test_uuid_wrong(const char *data)
+{
+       uuid_le le;
+       uuid_be be;
+
+       /* LE */
+       total_tests++;
+       if (!uuid_le_to_bin(data, &le))
+               test_uuid_failed("negative", true, false, data, NULL);
+
+       /* BE */
+       total_tests++;
+       if (!uuid_be_to_bin(data, &be))
+               test_uuid_failed("negative", true, true, data, NULL);
+}
+
+static int __init test_uuid_init(void)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(test_uuid_test_data); i++)
+               test_uuid_test(&test_uuid_test_data[i]);
+
+       for (i = 0; i < ARRAY_SIZE(test_uuid_wrong_data); i++)
+               test_uuid_wrong(test_uuid_wrong_data[i]);
+
+       if (failed_tests == 0)
+               pr_info("all %u tests passed\n", total_tests);
+       else
+               pr_err("failed %u out of %u tests\n", failed_tests, total_tests);
+
+       return failed_tests ? -EINVAL : 0;
+}
+module_init(test_uuid_init);
+
+static void __exit test_uuid_exit(void)
+{
+       /* do nothing */
+}
+module_exit(test_uuid_exit);
+
+MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
+MODULE_LICENSE("Dual BSD/GPL");
index e116ae5..37687af 100644 (file)
@@ -106,8 +106,8 @@ static int __uuid_to_bin(const char *uuid, __u8 b[16], const u8 ei[16])
                return -EINVAL;
 
        for (i = 0; i < 16; i++) {
-               int hi = hex_to_bin(uuid[si[i]] + 0);
-               int lo = hex_to_bin(uuid[si[i]] + 1);
+               int hi = hex_to_bin(uuid[si[i] + 0]);
+               int lo = hex_to_bin(uuid[si[i] + 1]);
 
                b[ei[i]] = (hi << 4) | lo;
        }
index 1427366..79bfe0e 100644 (file)
@@ -441,25 +441,23 @@ static unsigned long isolate_freepages_block(struct compact_control *cc,
 
                /* Found a free page, break it into order-0 pages */
                isolated = split_free_page(page);
+               if (!isolated)
+                       break;
+
                total_isolated += isolated;
+               cc->nr_freepages += isolated;
                for (i = 0; i < isolated; i++) {
                        list_add(&page->lru, freelist);
                        page++;
                }
-
-               /* If a page was split, advance to the end of it */
-               if (isolated) {
-                       cc->nr_freepages += isolated;
-                       if (!strict &&
-                               cc->nr_migratepages <= cc->nr_freepages) {
-                               blockpfn += isolated;
-                               break;
-                       }
-
-                       blockpfn += isolated - 1;
-                       cursor += isolated - 1;
-                       continue;
+               if (!strict && cc->nr_migratepages <= cc->nr_freepages) {
+                       blockpfn += isolated;
+                       break;
                }
+               /* Advance to the end of split page */
+               blockpfn += isolated - 1;
+               cursor += isolated - 1;
+               continue;
 
 isolate_fail:
                if (strict)
@@ -469,6 +467,9 @@ isolate_fail:
 
        }
 
+       if (locked)
+               spin_unlock_irqrestore(&cc->zone->lock, flags);
+
        /*
         * There is a tiny chance that we have read bogus compound_order(),
         * so be careful to not go outside of the pageblock.
@@ -490,9 +491,6 @@ isolate_fail:
        if (strict && blockpfn < end_pfn)
                total_isolated = 0;
 
-       if (locked)
-               spin_unlock_irqrestore(&cc->zone->lock, flags);
-
        /* Update the pageblock-skip if the whole pageblock was scanned */
        if (blockpfn == end_pfn)
                update_pageblock_skip(cc, valid_page, total_isolated, false);
@@ -1011,6 +1009,7 @@ static void isolate_freepages(struct compact_control *cc)
                                block_end_pfn = block_start_pfn,
                                block_start_pfn -= pageblock_nr_pages,
                                isolate_start_pfn = block_start_pfn) {
+               unsigned long isolated;
 
                /*
                 * This can iterate a massively long zone without finding any
@@ -1035,8 +1034,12 @@ static void isolate_freepages(struct compact_control *cc)
                        continue;
 
                /* Found a block suitable for isolating free pages from. */
-               isolate_freepages_block(cc, &isolate_start_pfn,
-                                       block_end_pfn, freelist, false);
+               isolated = isolate_freepages_block(cc, &isolate_start_pfn,
+                                               block_end_pfn, freelist, false);
+               /* If isolation failed early, do not continue needlessly */
+               if (!isolated && isolate_start_pfn < block_end_pfn &&
+                   cc->nr_migratepages > cc->nr_freepages)
+                       break;
 
                /*
                 * If we isolated enough freepages, or aborted due to async
index b8024fa..6c707bf 100644 (file)
@@ -126,6 +126,17 @@ SYSCALL_DEFINE4(fadvise64_64, int, fd, loff_t, offset, loff_t, len, int, advice)
                 */
                start_index = (offset+(PAGE_SIZE-1)) >> PAGE_SHIFT;
                end_index = (endbyte >> PAGE_SHIFT);
+               if ((endbyte & ~PAGE_MASK) != ~PAGE_MASK) {
+                       /* First page is tricky as 0 - 1 = -1, but pgoff_t
+                        * is unsigned, so the end_index >= start_index
+                        * check below would be true and we'll discard the whole
+                        * file cache which is not what was asked.
+                        */
+                       if (end_index == 0)
+                               break;
+
+                       end_index--;
+               }
 
                if (end_index >= start_index) {
                        unsigned long count = invalidate_mapping_pages(mapping,
index 00ae878..20f3b1f 100644 (file)
@@ -2186,7 +2186,7 @@ repeat:
                if (file->f_ra.mmap_miss > 0)
                        file->f_ra.mmap_miss--;
                addr = address + (page->index - vmf->pgoff) * PAGE_SIZE;
-               do_set_pte(vma, addr, page, pte, false, false, true);
+               do_set_pte(vma, addr, page, pte, false, false);
                unlock_page(page);
                goto next;
 unlock:
index d26162e..c1f3c0b 100644 (file)
@@ -832,8 +832,27 @@ static bool vma_has_reserves(struct vm_area_struct *vma, long chg)
         * Only the process that called mmap() has reserves for
         * private mappings.
         */
-       if (is_vma_resv_set(vma, HPAGE_RESV_OWNER))
-               return true;
+       if (is_vma_resv_set(vma, HPAGE_RESV_OWNER)) {
+               /*
+                * Like the shared case above, a hole punch or truncate
+                * could have been performed on the private mapping.
+                * Examine the value of chg to determine if reserves
+                * actually exist or were previously consumed.
+                * Very Subtle - The value of chg comes from a previous
+                * call to vma_needs_reserves().  The reserve map for
+                * private mappings has different (opposite) semantics
+                * than that of shared mappings.  vma_needs_reserves()
+                * has already taken this difference in semantics into
+                * account.  Therefore, the meaning of chg is the same
+                * as in the shared case above.  Code could easily be
+                * combined, but keeping it separate draws attention to
+                * subtle differences.
+                */
+               if (chg)
+                       return false;
+               else
+                       return true;
+       }
 
        return false;
 }
@@ -1011,6 +1030,7 @@ static void destroy_compound_gigantic_page(struct page *page,
        int nr_pages = 1 << order;
        struct page *p = page + 1;
 
+       atomic_set(compound_mapcount_ptr(page), 0);
        for (i = 1; i < nr_pages; i++, p = mem_map_next(p, page, i)) {
                clear_compound_head(p);
                set_page_refcounted(p);
@@ -1816,6 +1836,25 @@ static long __vma_reservation_common(struct hstate *h,
 
        if (vma->vm_flags & VM_MAYSHARE)
                return ret;
+       else if (is_vma_resv_set(vma, HPAGE_RESV_OWNER) && ret >= 0) {
+               /*
+                * In most cases, reserves always exist for private mappings.
+                * However, a file associated with mapping could have been
+                * hole punched or truncated after reserves were consumed.
+                * As subsequent fault on such a range will not use reserves.
+                * Subtle - The reserve map for private mappings has the
+                * opposite meaning than that of shared mappings.  If NO
+                * entry is in the reserve map, it means a reservation exists.
+                * If an entry exists in the reserve map, it means the
+                * reservation has already been consumed.  As a result, the
+                * return value of this routine is the opposite of the
+                * value returned from reserve map manipulation routines above.
+                */
+               if (ret)
+                       return 0;
+               else
+                       return 1;
+       }
        else
                return ret < 0 ? ret : 0;
 }
@@ -4190,7 +4229,6 @@ pte_t *huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud)
                if (saddr) {
                        spte = huge_pte_offset(svma->vm_mm, saddr);
                        if (spte) {
-                               mm_inc_nr_pmds(mm);
                                get_page(virt_to_page(spte));
                                break;
                        }
@@ -4205,9 +4243,9 @@ pte_t *huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud)
        if (pud_none(*pud)) {
                pud_populate(mm, pud,
                                (pmd_t *)((unsigned long)spte & PAGE_MASK));
+               mm_inc_nr_pmds(mm);
        } else {
                put_page(virt_to_page(spte));
-               mm_inc_nr_pmds(mm);
        }
        spin_unlock(ptl);
 out:
index a37e5b6..2524ec8 100644 (file)
@@ -24,7 +24,8 @@
  */
 #define GFP_RECLAIM_MASK (__GFP_RECLAIM|__GFP_HIGH|__GFP_IO|__GFP_FS|\
                        __GFP_NOWARN|__GFP_REPEAT|__GFP_NOFAIL|\
-                       __GFP_NORETRY|__GFP_MEMALLOC|__GFP_NOMEMALLOC)
+                       __GFP_NORETRY|__GFP_MEMALLOC|__GFP_NOMEMALLOC|\
+                       __GFP_ATOMIC)
 
 /* The GFP flags allowed during early boot */
 #define GFP_BOOT_MASK (__GFP_BITS_MASK & ~(__GFP_RECLAIM|__GFP_IO|__GFP_FS))
index 18b6a2b..6845f92 100644 (file)
@@ -508,7 +508,7 @@ void kasan_slab_alloc(struct kmem_cache *cache, void *object, gfp_t flags)
        kasan_kmalloc(cache, object, cache->object_size, flags);
 }
 
-void kasan_poison_slab_free(struct kmem_cache *cache, void *object)
+static void kasan_poison_slab_free(struct kmem_cache *cache, void *object)
 {
        unsigned long size = cache->object_size;
        unsigned long rounded_up_size = round_up(size, KASAN_SHADOW_SCALE_SIZE);
@@ -626,7 +626,7 @@ void kasan_krealloc(const void *object, size_t size, gfp_t flags)
                kasan_kmalloc(page->slab_cache, object, size, flags);
 }
 
-void kasan_kfree(void *ptr)
+void kasan_poison_kfree(void *ptr)
 {
        struct page *page;
 
@@ -636,7 +636,7 @@ void kasan_kfree(void *ptr)
                kasan_poison_shadow(ptr, PAGE_SIZE << compound_order(page),
                                KASAN_FREE_PAGE);
        else
-               kasan_slab_free(page->slab_cache, ptr);
+               kasan_poison_slab_free(page->slab_cache, ptr);
 }
 
 void kasan_kfree_large(const void *ptr)
@@ -763,8 +763,8 @@ static int kasan_mem_notifier(struct notifier_block *nb,
 
 static int __init kasan_memhotplug_init(void)
 {
-       pr_err("WARNING: KASAN doesn't support memory hot-add\n");
-       pr_err("Memory hot-add will be disabled\n");
+       pr_info("WARNING: KASAN doesn't support memory hot-add\n");
+       pr_info("Memory hot-add will be disabled\n");
 
        hotplug_memory_notifier(kasan_mem_notifier, 0);
 
index e642992..04320d3 100644 (file)
@@ -307,8 +307,10 @@ static void hex_dump_object(struct seq_file *seq,
        len = min_t(size_t, object->size, HEX_MAX_LINES * HEX_ROW_SIZE);
 
        seq_printf(seq, "  hex dump (first %zu bytes):\n", len);
+       kasan_disable_current();
        seq_hex_dump(seq, "    ", DUMP_PREFIX_NONE, HEX_ROW_SIZE,
                     HEX_GROUP_SIZE, ptr, len, HEX_ASCII);
+       kasan_enable_current();
 }
 
 /*
index 925b431..ac8664d 100644 (file)
@@ -1608,7 +1608,7 @@ static void memcg_oom_recover(struct mem_cgroup *memcg)
 
 static void mem_cgroup_oom(struct mem_cgroup *memcg, gfp_t mask, int order)
 {
-       if (!current->memcg_may_oom || current->memcg_in_oom)
+       if (!current->memcg_may_oom)
                return;
        /*
         * We are in the middle of the charge context here, so we
@@ -2896,6 +2896,7 @@ static void memcg_offline_kmem(struct mem_cgroup *memcg)
         * ordering is imposed by list_lru_node->lock taken by
         * memcg_drain_all_list_lrus().
         */
+       rcu_read_lock(); /* can be called from css_free w/o cgroup_mutex */
        css_for_each_descendant_pre(css, &memcg->css) {
                child = mem_cgroup_from_css(css);
                BUG_ON(child->kmemcg_id != kmemcg_id);
@@ -2903,6 +2904,8 @@ static void memcg_offline_kmem(struct mem_cgroup *memcg)
                if (!memcg->use_hierarchy)
                        break;
        }
+       rcu_read_unlock();
+
        memcg_drain_all_list_lrus(kmemcg_id, parent->kmemcg_id);
 
        memcg_free_cache_id(kmemcg_id);
@@ -4200,7 +4203,7 @@ mem_cgroup_css_alloc(struct cgroup_subsys_state *parent_css)
        return &memcg->css;
 fail:
        mem_cgroup_free(memcg);
-       return NULL;
+       return ERR_PTR(-ENOMEM);
 }
 
 static int
@@ -5541,6 +5544,7 @@ void mem_cgroup_migrate(struct page *oldpage, struct page *newpage)
        struct mem_cgroup *memcg;
        unsigned int nr_pages;
        bool compound;
+       unsigned long flags;
 
        VM_BUG_ON_PAGE(!PageLocked(oldpage), oldpage);
        VM_BUG_ON_PAGE(!PageLocked(newpage), newpage);
@@ -5571,10 +5575,10 @@ void mem_cgroup_migrate(struct page *oldpage, struct page *newpage)
 
        commit_charge(newpage, memcg, false);
 
-       local_irq_disable();
+       local_irq_save(flags);
        mem_cgroup_charge_statistics(memcg, newpage, compound, nr_pages);
        memcg_check_events(memcg, newpage);
-       local_irq_enable();
+       local_irq_restore(flags);
 }
 
 DEFINE_STATIC_KEY_FALSE(memcg_sockets_enabled_key);
index 15322b7..cd1f29e 100644 (file)
@@ -2877,7 +2877,7 @@ static int __do_fault(struct vm_area_struct *vma, unsigned long address,
  * vm_ops->map_pages.
  */
 void do_set_pte(struct vm_area_struct *vma, unsigned long address,
-               struct page *page, pte_t *pte, bool write, bool anon, bool old)
+               struct page *page, pte_t *pte, bool write, bool anon)
 {
        pte_t entry;
 
@@ -2885,8 +2885,6 @@ void do_set_pte(struct vm_area_struct *vma, unsigned long address,
        entry = mk_pte(page, vma->vm_page_prot);
        if (write)
                entry = maybe_mkwrite(pte_mkdirty(entry), vma);
-       if (old)
-               entry = pte_mkold(entry);
        if (anon) {
                inc_mm_counter_fast(vma->vm_mm, MM_ANONPAGES);
                page_add_new_anon_rmap(page, vma, address, false);
@@ -2900,16 +2898,8 @@ void do_set_pte(struct vm_area_struct *vma, unsigned long address,
        update_mmu_cache(vma, address, pte);
 }
 
-/*
- * If architecture emulates "accessed" or "young" bit without HW support,
- * there is no much gain with fault_around.
- */
 static unsigned long fault_around_bytes __read_mostly =
-#ifndef __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
-       PAGE_SIZE;
-#else
        rounddown_pow_of_two(65536);
-#endif
 
 #ifdef CONFIG_DEBUG_FS
 static int fault_around_bytes_get(void *data, u64 *val)
@@ -3032,20 +3022,9 @@ static int do_read_fault(struct mm_struct *mm, struct vm_area_struct *vma,
         */
        if (vma->vm_ops->map_pages && fault_around_bytes >> PAGE_SHIFT > 1) {
                pte = pte_offset_map_lock(mm, pmd, address, &ptl);
-               if (!pte_same(*pte, orig_pte))
-                       goto unlock_out;
                do_fault_around(vma, address, pte, pgoff, flags);
-               /* Check if the fault is handled by faultaround */
-               if (!pte_same(*pte, orig_pte)) {
-                       /*
-                        * Faultaround produce old pte, but the pte we've
-                        * handler fault for should be young.
-                        */
-                       pte_t entry = pte_mkyoung(*pte);
-                       if (ptep_set_access_flags(vma, address, pte, entry, 0))
-                               update_mmu_cache(vma, address, pte);
+               if (!pte_same(*pte, orig_pte))
                        goto unlock_out;
-               }
                pte_unmap_unlock(pte, ptl);
        }
 
@@ -3060,7 +3039,7 @@ static int do_read_fault(struct mm_struct *mm, struct vm_area_struct *vma,
                put_page(fault_page);
                return ret;
        }
-       do_set_pte(vma, address, fault_page, pte, false, false, false);
+       do_set_pte(vma, address, fault_page, pte, false, false);
        unlock_page(fault_page);
 unlock_out:
        pte_unmap_unlock(pte, ptl);
@@ -3111,7 +3090,7 @@ static int do_cow_fault(struct mm_struct *mm, struct vm_area_struct *vma,
                }
                goto uncharge_out;
        }
-       do_set_pte(vma, address, new_page, pte, true, true, false);
+       do_set_pte(vma, address, new_page, pte, true, true);
        mem_cgroup_commit_charge(new_page, memcg, false, false);
        lru_cache_add_active_or_unevictable(new_page, vma);
        pte_unmap_unlock(pte, ptl);
@@ -3164,7 +3143,7 @@ static int do_shared_fault(struct mm_struct *mm, struct vm_area_struct *vma,
                put_page(fault_page);
                return ret;
        }
-       do_set_pte(vma, address, fault_page, pte, true, false, false);
+       do_set_pte(vma, address, fault_page, pte, true, false);
        pte_unmap_unlock(pte, ptl);
 
        if (set_page_dirty(fault_page))
index 9e075f8..8f65464 100644 (file)
@@ -104,20 +104,16 @@ static inline void poison_element(mempool_t *pool, void *element)
 
 static void kasan_poison_element(mempool_t *pool, void *element)
 {
-       if (pool->alloc == mempool_alloc_slab)
-               kasan_poison_slab_free(pool->pool_data, element);
-       if (pool->alloc == mempool_kmalloc)
-               kasan_kfree(element);
+       if (pool->alloc == mempool_alloc_slab || pool->alloc == mempool_kmalloc)
+               kasan_poison_kfree(element);
        if (pool->alloc == mempool_alloc_pages)
                kasan_free_pages(element, (unsigned long)pool->pool_data);
 }
 
 static void kasan_unpoison_element(mempool_t *pool, void *element, gfp_t flags)
 {
-       if (pool->alloc == mempool_alloc_slab)
-               kasan_slab_alloc(pool->pool_data, element, flags);
-       if (pool->alloc == mempool_kmalloc)
-               kasan_krealloc(element, (size_t)pool->pool_data, flags);
+       if (pool->alloc == mempool_alloc_slab || pool->alloc == mempool_kmalloc)
+               kasan_unpoison_slab(element);
        if (pool->alloc == mempool_alloc_pages)
                kasan_alloc_pages(element, (unsigned long)pool->pool_data);
 }
index 9baf41c..bd3fdc2 100644 (file)
@@ -431,6 +431,7 @@ int migrate_page_move_mapping(struct address_space *mapping,
 
        return MIGRATEPAGE_SUCCESS;
 }
+EXPORT_SYMBOL(migrate_page_move_mapping);
 
 /*
  * The expected number of remaining references is the same as that
@@ -586,6 +587,7 @@ void migrate_page_copy(struct page *newpage, struct page *page)
 
        mem_cgroup_migrate(page, newpage);
 }
+EXPORT_SYMBOL(migrate_page_copy);
 
 /************************************************************
  *                    Migration functions
index dfb1ab6..ddf7448 100644 (file)
@@ -474,13 +474,8 @@ static bool __oom_reap_task(struct task_struct *tsk)
        p = find_lock_task_mm(tsk);
        if (!p)
                goto unlock_oom;
-
        mm = p->mm;
-       if (!atomic_inc_not_zero(&mm->mm_users)) {
-               task_unlock(p);
-               goto unlock_oom;
-       }
-
+       atomic_inc(&mm->mm_users);
        task_unlock(p);
 
        if (!down_read_trylock(&mm->mmap_sem)) {
@@ -625,8 +620,6 @@ void try_oom_reaper(struct task_struct *tsk)
        if (atomic_read(&mm->mm_users) > 1) {
                rcu_read_lock();
                for_each_process(p) {
-                       bool exiting;
-
                        if (!process_shares_mm(p, mm))
                                continue;
                        if (fatal_signal_pending(p))
@@ -636,10 +629,7 @@ void try_oom_reaper(struct task_struct *tsk)
                         * If the task is exiting make sure the whole thread group
                         * is exiting and cannot acces mm anymore.
                         */
-                       spin_lock_irq(&p->sighand->siglock);
-                       exiting = signal_group_exit(p->signal);
-                       spin_unlock_irq(&p->sighand->siglock);
-                       if (exiting)
+                       if (signal_group_exit(p->signal))
                                continue;
 
                        /* Give up */
index b9956fd..e248194 100644 (file)
@@ -373,8 +373,9 @@ static void domain_dirty_limits(struct dirty_throttle_control *dtc)
        struct dirty_throttle_control *gdtc = mdtc_gdtc(dtc);
        unsigned long bytes = vm_dirty_bytes;
        unsigned long bg_bytes = dirty_background_bytes;
-       unsigned long ratio = vm_dirty_ratio;
-       unsigned long bg_ratio = dirty_background_ratio;
+       /* convert ratios to per-PAGE_SIZE for higher precision */
+       unsigned long ratio = (vm_dirty_ratio * PAGE_SIZE) / 100;
+       unsigned long bg_ratio = (dirty_background_ratio * PAGE_SIZE) / 100;
        unsigned long thresh;
        unsigned long bg_thresh;
        struct task_struct *tsk;
@@ -386,26 +387,28 @@ static void domain_dirty_limits(struct dirty_throttle_control *dtc)
                /*
                 * The byte settings can't be applied directly to memcg
                 * domains.  Convert them to ratios by scaling against
-                * globally available memory.
+                * globally available memory.  As the ratios are in
+                * per-PAGE_SIZE, they can be obtained by dividing bytes by
+                * number of pages.
                 */
                if (bytes)
-                       ratio = min(DIV_ROUND_UP(bytes, PAGE_SIZE) * 100 /
-                                   global_avail, 100UL);
+                       ratio = min(DIV_ROUND_UP(bytes, global_avail),
+                                   PAGE_SIZE);
                if (bg_bytes)
-                       bg_ratio = min(DIV_ROUND_UP(bg_bytes, PAGE_SIZE) * 100 /
-                                      global_avail, 100UL);
+                       bg_ratio = min(DIV_ROUND_UP(bg_bytes, global_avail),
+                                      PAGE_SIZE);
                bytes = bg_bytes = 0;
        }
 
        if (bytes)
                thresh = DIV_ROUND_UP(bytes, PAGE_SIZE);
        else
-               thresh = (ratio * available_memory) / 100;
+               thresh = (ratio * available_memory) / PAGE_SIZE;
 
        if (bg_bytes)
                bg_thresh = DIV_ROUND_UP(bg_bytes, PAGE_SIZE);
        else
-               bg_thresh = (bg_ratio * available_memory) / 100;
+               bg_thresh = (bg_ratio * available_memory) / PAGE_SIZE;
 
        if (bg_thresh >= thresh)
                bg_thresh = thresh / 2;
index f8f3bfc..6903b69 100644 (file)
@@ -656,6 +656,9 @@ static inline void set_page_guard(struct zone *zone, struct page *page,
                return;
 
        page_ext = lookup_page_ext(page);
+       if (unlikely(!page_ext))
+               return;
+
        __set_bit(PAGE_EXT_DEBUG_GUARD, &page_ext->flags);
 
        INIT_LIST_HEAD(&page->lru);
@@ -673,6 +676,9 @@ static inline void clear_page_guard(struct zone *zone, struct page *page,
                return;
 
        page_ext = lookup_page_ext(page);
+       if (unlikely(!page_ext))
+               return;
+
        __clear_bit(PAGE_EXT_DEBUG_GUARD, &page_ext->flags);
 
        set_page_private(page, 0);
@@ -2609,11 +2615,12 @@ struct page *buffered_rmqueue(struct zone *preferred_zone,
                                page = list_last_entry(list, struct page, lru);
                        else
                                page = list_first_entry(list, struct page, lru);
-               } while (page && check_new_pcp(page));
 
-               __dec_zone_state(zone, NR_ALLOC_BATCH);
-               list_del(&page->lru);
-               pcp->count--;
+                       __dec_zone_state(zone, NR_ALLOC_BATCH);
+                       list_del(&page->lru);
+                       pcp->count--;
+
+               } while (check_new_pcp(page));
        } else {
                /*
                 * We most definitely don't want callers attempting to
@@ -3023,6 +3030,7 @@ reset_fair:
                apply_fair = false;
                fair_skipped = false;
                reset_alloc_batches(ac->preferred_zoneref->zone);
+               z = ac->preferred_zoneref;
                goto zonelist_scan;
        }
 
@@ -3596,6 +3604,17 @@ retry:
         */
        alloc_flags = gfp_to_alloc_flags(gfp_mask);
 
+       /*
+        * Reset the zonelist iterators if memory policies can be ignored.
+        * These allocations are high priority and system rather than user
+        * orientated.
+        */
+       if ((alloc_flags & ALLOC_NO_WATERMARKS) || !(alloc_flags & ALLOC_CPUSET)) {
+               ac->zonelist = node_zonelist(numa_node_id(), gfp_mask);
+               ac->preferred_zoneref = first_zones_zonelist(ac->zonelist,
+                                       ac->high_zoneidx, ac->nodemask);
+       }
+
        /* This is the last chance, in general, before the goto nopage. */
        page = get_page_from_freelist(gfp_mask, order,
                                alloc_flags & ~ALLOC_NO_WATERMARKS, ac);
@@ -3604,12 +3623,6 @@ retry:
 
        /* Allocate without watermarks if the context allows */
        if (alloc_flags & ALLOC_NO_WATERMARKS) {
-               /*
-                * Ignore mempolicies if ALLOC_NO_WATERMARKS on the grounds
-                * the allocation is high priority and these type of
-                * allocations are system rather than user orientated
-                */
-               ac->zonelist = node_zonelist(numa_node_id(), gfp_mask);
                page = get_page_from_freelist(gfp_mask, order,
                                                ALLOC_NO_WATERMARKS, ac);
                if (page)
@@ -3808,7 +3821,11 @@ retry_cpuset:
        /* Dirty zone balancing only done in the fast path */
        ac.spread_dirty_pages = (gfp_mask & __GFP_WRITE);
 
-       /* The preferred zone is used for statistics later */
+       /*
+        * The preferred zone is used for statistics but crucially it is
+        * also used as the starting point for the zonelist iterator. It
+        * may get reset for allocations that ignore memory policies.
+        */
        ac.preferred_zoneref = first_zones_zonelist(ac.zonelist,
                                        ac.high_zoneidx, ac.nodemask);
        if (!ac.preferred_zoneref) {
index 792b56d..fedeba8 100644 (file)
@@ -55,6 +55,8 @@ void __reset_page_owner(struct page *page, unsigned int order)
 
        for (i = 0; i < (1 << order); i++) {
                page_ext = lookup_page_ext(page + i);
+               if (unlikely(!page_ext))
+                       continue;
                __clear_bit(PAGE_EXT_OWNER, &page_ext->flags);
        }
 }
@@ -62,6 +64,7 @@ void __reset_page_owner(struct page *page, unsigned int order)
 void __set_page_owner(struct page *page, unsigned int order, gfp_t gfp_mask)
 {
        struct page_ext *page_ext = lookup_page_ext(page);
+
        struct stack_trace trace = {
                .nr_entries = 0,
                .max_entries = ARRAY_SIZE(page_ext->trace_entries),
@@ -69,6 +72,9 @@ void __set_page_owner(struct page *page, unsigned int order, gfp_t gfp_mask)
                .skip = 3,
        };
 
+       if (unlikely(!page_ext))
+               return;
+
        save_stack_trace(&trace);
 
        page_ext->order = order;
@@ -82,6 +88,8 @@ void __set_page_owner(struct page *page, unsigned int order, gfp_t gfp_mask)
 void __set_page_owner_migrate_reason(struct page *page, int reason)
 {
        struct page_ext *page_ext = lookup_page_ext(page);
+       if (unlikely(!page_ext))
+               return;
 
        page_ext->last_migrate_reason = reason;
 }
@@ -89,6 +97,12 @@ void __set_page_owner_migrate_reason(struct page *page, int reason)
 gfp_t __get_page_owner_gfp(struct page *page)
 {
        struct page_ext *page_ext = lookup_page_ext(page);
+       if (unlikely(!page_ext))
+               /*
+                * The caller just returns 0 if no valid gfp
+                * So return 0 here too.
+                */
+               return 0;
 
        return page_ext->gfp_mask;
 }
@@ -99,6 +113,9 @@ void __copy_page_owner(struct page *oldpage, struct page *newpage)
        struct page_ext *new_ext = lookup_page_ext(newpage);
        int i;
 
+       if (unlikely(!old_ext || !new_ext))
+               return;
+
        new_ext->order = old_ext->order;
        new_ext->gfp_mask = old_ext->gfp_mask;
        new_ext->nr_entries = old_ext->nr_entries;
@@ -190,8 +207,15 @@ void __dump_page_owner(struct page *page)
                .nr_entries = page_ext->nr_entries,
                .entries = &page_ext->trace_entries[0],
        };
-       gfp_t gfp_mask = page_ext->gfp_mask;
-       int mt = gfpflags_to_migratetype(gfp_mask);
+       gfp_t gfp_mask;
+       int mt;
+
+       if (unlikely(!page_ext)) {
+               pr_alert("There is not page extension available.\n");
+               return;
+       }
+       gfp_mask = page_ext->gfp_mask;
+       mt = gfpflags_to_migratetype(gfp_mask);
 
        if (!test_bit(PAGE_EXT_OWNER, &page_ext->flags)) {
                pr_alert("page_owner info is not active (free page?)\n");
@@ -251,6 +275,8 @@ read_page_owner(struct file *file, char __user *buf, size_t count, loff_t *ppos)
                }
 
                page_ext = lookup_page_ext(page);
+               if (unlikely(!page_ext))
+                       continue;
 
                /*
                 * Some pages could be missed by concurrent allocation or free,
@@ -317,6 +343,8 @@ static void init_pages_in_zone(pg_data_t *pgdat, struct zone *zone)
                                continue;
 
                        page_ext = lookup_page_ext(page);
+                       if (unlikely(!page_ext))
+                               continue;
 
                        /* Maybe overraping zone */
                        if (test_bit(PAGE_EXT_OWNER, &page_ext->flags))
index 1eae5fa..2e647c6 100644 (file)
@@ -54,6 +54,9 @@ static inline void set_page_poison(struct page *page)
        struct page_ext *page_ext;
 
        page_ext = lookup_page_ext(page);
+       if (unlikely(!page_ext))
+               return;
+
        __set_bit(PAGE_EXT_DEBUG_POISON, &page_ext->flags);
 }
 
@@ -62,6 +65,9 @@ static inline void clear_page_poison(struct page *page)
        struct page_ext *page_ext;
 
        page_ext = lookup_page_ext(page);
+       if (unlikely(!page_ext))
+               return;
+
        __clear_bit(PAGE_EXT_DEBUG_POISON, &page_ext->flags);
 }
 
@@ -70,7 +76,7 @@ bool page_is_poisoned(struct page *page)
        struct page_ext *page_ext;
 
        page_ext = lookup_page_ext(page);
-       if (!page_ext)
+       if (unlikely(!page_ext))
                return false;
 
        return test_bit(PAGE_EXT_DEBUG_POISON, &page_ext->flags);
index 0c59684..9903830 100644 (file)
@@ -112,7 +112,7 @@ struct pcpu_chunk {
        int                     map_used;       /* # of map entries used before the sentry */
        int                     map_alloc;      /* # of map entries allocated */
        int                     *map;           /* allocation map */
-       struct work_struct      map_extend_work;/* async ->map[] extension */
+       struct list_head        map_extend_list;/* on pcpu_map_extend_chunks */
 
        void                    *data;          /* chunk data */
        int                     first_free;     /* no free below this */
@@ -162,10 +162,13 @@ static struct pcpu_chunk *pcpu_reserved_chunk;
 static int pcpu_reserved_chunk_limit;
 
 static DEFINE_SPINLOCK(pcpu_lock);     /* all internal data structures */
-static DEFINE_MUTEX(pcpu_alloc_mutex); /* chunk create/destroy, [de]pop */
+static DEFINE_MUTEX(pcpu_alloc_mutex); /* chunk create/destroy, [de]pop, map ext */
 
 static struct list_head *pcpu_slot __read_mostly; /* chunk list slots */
 
+/* chunks which need their map areas extended, protected by pcpu_lock */
+static LIST_HEAD(pcpu_map_extend_chunks);
+
 /*
  * The number of empty populated pages, protected by pcpu_lock.  The
  * reserved chunk doesn't contribute to the count.
@@ -395,13 +398,19 @@ static int pcpu_need_to_extend(struct pcpu_chunk *chunk, bool is_atomic)
 {
        int margin, new_alloc;
 
+       lockdep_assert_held(&pcpu_lock);
+
        if (is_atomic) {
                margin = 3;
 
                if (chunk->map_alloc <
-                   chunk->map_used + PCPU_ATOMIC_MAP_MARGIN_LOW &&
-                   pcpu_async_enabled)
-                       schedule_work(&chunk->map_extend_work);
+                   chunk->map_used + PCPU_ATOMIC_MAP_MARGIN_LOW) {
+                       if (list_empty(&chunk->map_extend_list)) {
+                               list_add_tail(&chunk->map_extend_list,
+                                             &pcpu_map_extend_chunks);
+                               pcpu_schedule_balance_work();
+                       }
+               }
        } else {
                margin = PCPU_ATOMIC_MAP_MARGIN_HIGH;
        }
@@ -435,6 +444,8 @@ static int pcpu_extend_area_map(struct pcpu_chunk *chunk, int new_alloc)
        size_t old_size = 0, new_size = new_alloc * sizeof(new[0]);
        unsigned long flags;
 
+       lockdep_assert_held(&pcpu_alloc_mutex);
+
        new = pcpu_mem_zalloc(new_size);
        if (!new)
                return -ENOMEM;
@@ -467,20 +478,6 @@ out_unlock:
        return 0;
 }
 
-static void pcpu_map_extend_workfn(struct work_struct *work)
-{
-       struct pcpu_chunk *chunk = container_of(work, struct pcpu_chunk,
-                                               map_extend_work);
-       int new_alloc;
-
-       spin_lock_irq(&pcpu_lock);
-       new_alloc = pcpu_need_to_extend(chunk, false);
-       spin_unlock_irq(&pcpu_lock);
-
-       if (new_alloc)
-               pcpu_extend_area_map(chunk, new_alloc);
-}
-
 /**
  * pcpu_fit_in_area - try to fit the requested allocation in a candidate area
  * @chunk: chunk the candidate area belongs to
@@ -740,7 +737,7 @@ static struct pcpu_chunk *pcpu_alloc_chunk(void)
        chunk->map_used = 1;
 
        INIT_LIST_HEAD(&chunk->list);
-       INIT_WORK(&chunk->map_extend_work, pcpu_map_extend_workfn);
+       INIT_LIST_HEAD(&chunk->map_extend_list);
        chunk->free_size = pcpu_unit_size;
        chunk->contig_hint = pcpu_unit_size;
 
@@ -895,6 +892,9 @@ static void __percpu *pcpu_alloc(size_t size, size_t align, bool reserved,
                return NULL;
        }
 
+       if (!is_atomic)
+               mutex_lock(&pcpu_alloc_mutex);
+
        spin_lock_irqsave(&pcpu_lock, flags);
 
        /* serve reserved allocations from the reserved chunk if available */
@@ -967,12 +967,9 @@ restart:
        if (is_atomic)
                goto fail;
 
-       mutex_lock(&pcpu_alloc_mutex);
-
        if (list_empty(&pcpu_slot[pcpu_nr_slots - 1])) {
                chunk = pcpu_create_chunk();
                if (!chunk) {
-                       mutex_unlock(&pcpu_alloc_mutex);
                        err = "failed to allocate new chunk";
                        goto fail;
                }
@@ -983,7 +980,6 @@ restart:
                spin_lock_irqsave(&pcpu_lock, flags);
        }
 
-       mutex_unlock(&pcpu_alloc_mutex);
        goto restart;
 
 area_found:
@@ -993,8 +989,6 @@ area_found:
        if (!is_atomic) {
                int page_start, page_end, rs, re;
 
-               mutex_lock(&pcpu_alloc_mutex);
-
                page_start = PFN_DOWN(off);
                page_end = PFN_UP(off + size);
 
@@ -1005,7 +999,6 @@ area_found:
 
                        spin_lock_irqsave(&pcpu_lock, flags);
                        if (ret) {
-                               mutex_unlock(&pcpu_alloc_mutex);
                                pcpu_free_area(chunk, off, &occ_pages);
                                err = "failed to populate";
                                goto fail_unlock;
@@ -1045,6 +1038,8 @@ fail:
                /* see the flag handling in pcpu_blance_workfn() */
                pcpu_atomic_alloc_failed = true;
                pcpu_schedule_balance_work();
+       } else {
+               mutex_unlock(&pcpu_alloc_mutex);
        }
        return NULL;
 }
@@ -1129,6 +1124,7 @@ static void pcpu_balance_workfn(struct work_struct *work)
                if (chunk == list_first_entry(free_head, struct pcpu_chunk, list))
                        continue;
 
+               list_del_init(&chunk->map_extend_list);
                list_move(&chunk->list, &to_free);
        }
 
@@ -1146,6 +1142,25 @@ static void pcpu_balance_workfn(struct work_struct *work)
                pcpu_destroy_chunk(chunk);
        }
 
+       /* service chunks which requested async area map extension */
+       do {
+               int new_alloc = 0;
+
+               spin_lock_irq(&pcpu_lock);
+
+               chunk = list_first_entry_or_null(&pcpu_map_extend_chunks,
+                                       struct pcpu_chunk, map_extend_list);
+               if (chunk) {
+                       list_del_init(&chunk->map_extend_list);
+                       new_alloc = pcpu_need_to_extend(chunk, false);
+               }
+
+               spin_unlock_irq(&pcpu_lock);
+
+               if (new_alloc)
+                       pcpu_extend_area_map(chunk, new_alloc);
+       } while (chunk);
+
        /*
         * Ensure there are certain number of free populated pages for
         * atomic allocs.  Fill up from the most packed so that atomic
@@ -1644,7 +1659,7 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
         */
        schunk = memblock_virt_alloc(pcpu_chunk_struct_size, 0);
        INIT_LIST_HEAD(&schunk->list);
-       INIT_WORK(&schunk->map_extend_work, pcpu_map_extend_workfn);
+       INIT_LIST_HEAD(&schunk->map_extend_list);
        schunk->base_addr = base_addr;
        schunk->map = smap;
        schunk->map_alloc = ARRAY_SIZE(smap);
@@ -1673,7 +1688,7 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
        if (dyn_size) {
                dchunk = memblock_virt_alloc(pcpu_chunk_struct_size, 0);
                INIT_LIST_HEAD(&dchunk->list);
-               INIT_WORK(&dchunk->map_extend_work, pcpu_map_extend_workfn);
+               INIT_LIST_HEAD(&dchunk->map_extend_list);
                dchunk->base_addr = base_addr;
                dchunk->map = dmap;
                dchunk->map_alloc = ARRAY_SIZE(dmap);
index a361449..24463b6 100644 (file)
@@ -2227,7 +2227,7 @@ static long shmem_fallocate(struct file *file, int mode, loff_t offset,
                        /* Remove the !PageUptodate pages we added */
                        shmem_undo_range(inode,
                                (loff_t)start << PAGE_SHIFT,
-                               (loff_t)index << PAGE_SHIFT, true);
+                               ((loff_t)index << PAGE_SHIFT) - 1, true);
                        goto undone;
                }
 
index 9591614..90530ff 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -242,7 +242,7 @@ void rotate_reclaimable_page(struct page *page)
                get_page(page);
                local_irq_save(flags);
                pvec = this_cpu_ptr(&lru_rotate_pvecs);
-               if (!pagevec_add(pvec, page))
+               if (!pagevec_add(pvec, page) || PageCompound(page))
                        pagevec_move_tail(pvec);
                local_irq_restore(flags);
        }
@@ -296,7 +296,7 @@ void activate_page(struct page *page)
                struct pagevec *pvec = &get_cpu_var(activate_page_pvecs);
 
                get_page(page);
-               if (!pagevec_add(pvec, page))
+               if (!pagevec_add(pvec, page) || PageCompound(page))
                        pagevec_lru_move_fn(pvec, __activate_page, NULL);
                put_cpu_var(activate_page_pvecs);
        }
@@ -391,9 +391,8 @@ static void __lru_cache_add(struct page *page)
        struct pagevec *pvec = &get_cpu_var(lru_add_pvec);
 
        get_page(page);
-       if (!pagevec_space(pvec))
+       if (!pagevec_add(pvec, page) || PageCompound(page))
                __pagevec_lru_add(pvec);
-       pagevec_add(pvec, page);
        put_cpu_var(lru_add_pvec);
 }
 
@@ -628,7 +627,7 @@ void deactivate_file_page(struct page *page)
        if (likely(get_page_unless_zero(page))) {
                struct pagevec *pvec = &get_cpu_var(lru_deactivate_file_pvecs);
 
-               if (!pagevec_add(pvec, page))
+               if (!pagevec_add(pvec, page) || PageCompound(page))
                        pagevec_lru_move_fn(pvec, lru_deactivate_file_fn, NULL);
                put_cpu_var(lru_deactivate_file_pvecs);
        }
@@ -648,7 +647,7 @@ void deactivate_page(struct page *page)
                struct pagevec *pvec = &get_cpu_var(lru_deactivate_pvecs);
 
                get_page(page);
-               if (!pagevec_add(pvec, page))
+               if (!pagevec_add(pvec, page) || PageCompound(page))
                        pagevec_lru_move_fn(pvec, lru_deactivate_fn, NULL);
                put_cpu_var(lru_deactivate_pvecs);
        }
@@ -667,6 +666,24 @@ static void lru_add_drain_per_cpu(struct work_struct *dummy)
 
 static DEFINE_PER_CPU(struct work_struct, lru_add_drain_work);
 
+/*
+ * lru_add_drain_wq is used to do lru_add_drain_all() from a WQ_MEM_RECLAIM
+ * workqueue, aiding in getting memory freed.
+ */
+static struct workqueue_struct *lru_add_drain_wq;
+
+static int __init lru_init(void)
+{
+       lru_add_drain_wq = alloc_workqueue("lru-add-drain", WQ_MEM_RECLAIM, 0);
+
+       if (WARN(!lru_add_drain_wq,
+               "Failed to create workqueue lru_add_drain_wq"))
+               return -ENOMEM;
+
+       return 0;
+}
+early_initcall(lru_init);
+
 void lru_add_drain_all(void)
 {
        static DEFINE_MUTEX(lock);
@@ -686,7 +703,7 @@ void lru_add_drain_all(void)
                    pagevec_count(&per_cpu(lru_deactivate_pvecs, cpu)) ||
                    need_activate_page_drain(cpu)) {
                        INIT_WORK(work, lru_add_drain_per_cpu);
-                       schedule_work_on(cpu, work);
+                       queue_work_on(cpu, lru_add_drain_wq, work);
                        cpumask_set_cpu(cpu, &has_work);
                }
        }
index 0d457e7..c99463a 100644 (file)
@@ -252,7 +252,10 @@ static inline void free_swap_cache(struct page *page)
 void free_page_and_swap_cache(struct page *page)
 {
        free_swap_cache(page);
-       put_page(page);
+       if (is_huge_zero_page(page))
+               put_huge_zero_page();
+       else
+               put_page(page);
 }
 
 /*
index cf7ad1a..e11475c 100644 (file)
@@ -1105,7 +1105,7 @@ EXPORT_SYMBOL_GPL(vm_unmap_aliases);
  */
 void vm_unmap_ram(const void *mem, unsigned int count)
 {
-       unsigned long size = count << PAGE_SHIFT;
+       unsigned long size = (unsigned long)count << PAGE_SHIFT;
        unsigned long addr = (unsigned long)mem;
 
        BUG_ON(!addr);
@@ -1140,7 +1140,7 @@ EXPORT_SYMBOL(vm_unmap_ram);
  */
 void *vm_map_ram(struct page **pages, unsigned int count, int node, pgprot_t prot)
 {
-       unsigned long size = count << PAGE_SHIFT;
+       unsigned long size = (unsigned long)count << PAGE_SHIFT;
        unsigned long addr;
        void *mem;
 
@@ -1574,14 +1574,15 @@ void *vmap(struct page **pages, unsigned int count,
                unsigned long flags, pgprot_t prot)
 {
        struct vm_struct *area;
+       unsigned long size;             /* In bytes */
 
        might_sleep();
 
        if (count > totalram_pages)
                return NULL;
 
-       area = get_vm_area_caller((count << PAGE_SHIFT), flags,
-                                       __builtin_return_address(0));
+       size = (unsigned long)count << PAGE_SHIFT;
+       area = get_vm_area_caller(size, flags, __builtin_return_address(0));
        if (!area)
                return NULL;
 
index 77e42ef..cb2a67b 100644 (file)
@@ -1061,6 +1061,8 @@ static void pagetypeinfo_showmixedcount_print(struct seq_file *m,
                                continue;
 
                        page_ext = lookup_page_ext(page);
+                       if (unlikely(!page_ext))
+                               continue;
 
                        if (!test_bit(PAGE_EXT_OWNER, &page_ext->flags))
                                continue;
index 34917d5..8f9e89c 100644 (file)
@@ -412,7 +412,7 @@ static void z3fold_free(struct z3fold_pool *pool, unsigned long handle)
                /* HEADLESS page stored */
                bud = HEADLESS;
        } else {
-               bud = (handle - zhdr->first_num) & BUDDY_MASK;
+               bud = handle_to_buddy(handle);
 
                switch (bud) {
                case FIRST:
@@ -572,15 +572,19 @@ next:
                        pool->pages_nr--;
                        spin_unlock(&pool->lock);
                        return 0;
-               } else if (zhdr->first_chunks != 0 &&
-                          zhdr->last_chunks != 0 && zhdr->middle_chunks != 0) {
-                       /* Full, add to buddied list */
-                       list_add(&zhdr->buddy, &pool->buddied);
-               } else if (!test_bit(PAGE_HEADLESS, &page->private)) {
-                       z3fold_compact_page(zhdr);
-                       /* add to unbuddied list */
-                       freechunks = num_free_chunks(zhdr);
-                       list_add(&zhdr->buddy, &pool->unbuddied[freechunks]);
+               }  else if (!test_bit(PAGE_HEADLESS, &page->private)) {
+                       if (zhdr->first_chunks != 0 &&
+                           zhdr->last_chunks != 0 &&
+                           zhdr->middle_chunks != 0) {
+                               /* Full, add to buddied list */
+                               list_add(&zhdr->buddy, &pool->buddied);
+                       } else {
+                               z3fold_compact_page(zhdr);
+                               /* add to unbuddied list */
+                               freechunks = num_free_chunks(zhdr);
+                               list_add(&zhdr->buddy,
+                                        &pool->unbuddied[freechunks]);
+                       }
                }
 
                /* add to beginning of LRU */
index a1e273a..82a116b 100644 (file)
@@ -290,6 +290,10 @@ static void vlan_sync_address(struct net_device *dev,
        if (ether_addr_equal(vlan->real_dev_addr, dev->dev_addr))
                return;
 
+       /* vlan continues to inherit address of lower device */
+       if (vlan_dev_inherit_address(vlandev, dev))
+               goto out;
+
        /* vlan address was different from the old address and is equal to
         * the new address */
        if (!ether_addr_equal(vlandev->dev_addr, vlan->real_dev_addr) &&
@@ -302,6 +306,7 @@ static void vlan_sync_address(struct net_device *dev,
            !ether_addr_equal(vlandev->dev_addr, dev->dev_addr))
                dev_uc_add(dev, vlandev->dev_addr);
 
+out:
        ether_addr_copy(vlan->real_dev_addr, dev->dev_addr);
 }
 
index 9d010a0..cc15579 100644 (file)
@@ -109,6 +109,8 @@ int vlan_check_real_dev(struct net_device *real_dev,
 void vlan_setup(struct net_device *dev);
 int register_vlan_dev(struct net_device *dev);
 void unregister_vlan_dev(struct net_device *dev, struct list_head *head);
+bool vlan_dev_inherit_address(struct net_device *dev,
+                             struct net_device *real_dev);
 
 static inline u32 vlan_get_ingress_priority(struct net_device *dev,
                                            u16 vlan_tci)
index e7e6257..86ae75b 100644 (file)
@@ -245,6 +245,17 @@ void vlan_dev_get_realdev_name(const struct net_device *dev, char *result)
        strncpy(result, vlan_dev_priv(dev)->real_dev->name, 23);
 }
 
+bool vlan_dev_inherit_address(struct net_device *dev,
+                             struct net_device *real_dev)
+{
+       if (dev->addr_assign_type != NET_ADDR_STOLEN)
+               return false;
+
+       ether_addr_copy(dev->dev_addr, real_dev->dev_addr);
+       call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
+       return true;
+}
+
 static int vlan_dev_open(struct net_device *dev)
 {
        struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
@@ -255,7 +266,8 @@ static int vlan_dev_open(struct net_device *dev)
            !(vlan->flags & VLAN_FLAG_LOOSE_BINDING))
                return -ENETDOWN;
 
-       if (!ether_addr_equal(dev->dev_addr, real_dev->dev_addr)) {
+       if (!ether_addr_equal(dev->dev_addr, real_dev->dev_addr) &&
+           !vlan_dev_inherit_address(dev, real_dev)) {
                err = dev_uc_add(real_dev, dev->dev_addr);
                if (err < 0)
                        goto out;
@@ -560,8 +572,10 @@ static int vlan_dev_init(struct net_device *dev)
        /* ipv6 shared card related stuff */
        dev->dev_id = real_dev->dev_id;
 
-       if (is_zero_ether_addr(dev->dev_addr))
-               eth_hw_addr_inherit(dev, real_dev);
+       if (is_zero_ether_addr(dev->dev_addr)) {
+               ether_addr_copy(dev->dev_addr, real_dev->dev_addr);
+               dev->addr_assign_type = NET_ADDR_STOLEN;
+       }
        if (is_zero_ether_addr(dev->broadcast))
                memcpy(dev->broadcast, real_dev->broadcast, dev->addr_len);
 
index 4fd6af4..adb6e3d 100644 (file)
@@ -124,7 +124,7 @@ as_indicate_complete:
                break;
        case as_addparty:
        case as_dropparty:
-               sk->sk_err_soft = msg->reply;
+               sk->sk_err_soft = -msg->reply;
                                        /* < 0 failure, otherwise ep_ref */
                clear_bit(ATM_VF_WAITING, &vcc->flags);
                break;
index 3fa0a9e..878563a 100644 (file)
@@ -546,7 +546,7 @@ static int svc_addparty(struct socket *sock, struct sockaddr *sockaddr,
                schedule();
        }
        finish_wait(sk_sleep(sk), &wait);
-       error = xchg(&sk->sk_err_soft, 0);
+       error = -xchg(&sk->sk_err_soft, 0);
 out:
        release_sock(sk);
        return error;
@@ -573,7 +573,7 @@ static int svc_dropparty(struct socket *sock, int ep_ref)
                error = -EUNATCH;
                goto out;
        }
-       error = xchg(&sk->sk_err_soft, 0);
+       error = -xchg(&sk->sk_err_soft, 0);
 out:
        release_sock(sk);
        return error;
index dcea4f4..c18080a 100644 (file)
@@ -279,6 +279,8 @@ void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr)
         * change from under us.
         */
        list_for_each_entry(v, &vg->vlan_list, vlist) {
+               if (!br_vlan_should_use(v))
+                       continue;
                f = __br_fdb_get(br, br->dev->dev_addr, v->vid);
                if (f && f->is_local && !f->dst)
                        fdb_delete_local(br, NULL, f);
index 0160d7d..8946959 100644 (file)
@@ -1276,9 +1276,9 @@ static bool target_should_be_paused(struct ceph_osd_client *osdc,
                                    const struct ceph_osd_request_target *t,
                                    struct ceph_pg_pool_info *pi)
 {
-       bool pauserd = ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_PAUSERD);
-       bool pausewr = ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_PAUSEWR) ||
-                      ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_FULL) ||
+       bool pauserd = ceph_osdmap_flag(osdc, CEPH_OSDMAP_PAUSERD);
+       bool pausewr = ceph_osdmap_flag(osdc, CEPH_OSDMAP_PAUSEWR) ||
+                      ceph_osdmap_flag(osdc, CEPH_OSDMAP_FULL) ||
                       __pool_full(pi);
 
        WARN_ON(pi->id != t->base_oloc.pool);
@@ -1303,8 +1303,7 @@ static enum calc_target_result calc_target(struct ceph_osd_client *osdc,
        bool force_resend = false;
        bool need_check_tiering = false;
        bool need_resend = false;
-       bool sort_bitwise = ceph_osdmap_flag(osdc->osdmap,
-                                            CEPH_OSDMAP_SORTBITWISE);
+       bool sort_bitwise = ceph_osdmap_flag(osdc, CEPH_OSDMAP_SORTBITWISE);
        enum calc_target_result ct_res;
        int ret;
 
@@ -1540,9 +1539,9 @@ static void encode_request(struct ceph_osd_request *req, struct ceph_msg *msg)
         */
        msg->hdr.data_off = cpu_to_le16(req->r_data_offset);
 
-       dout("%s req %p oid %*pE oid_len %d front %zu data %u\n", __func__,
-            req, req->r_t.target_oid.name_len, req->r_t.target_oid.name,
-            req->r_t.target_oid.name_len, msg->front.iov_len, data_len);
+       dout("%s req %p oid %s oid_len %d front %zu data %u\n", __func__,
+            req, req->r_t.target_oid.name, req->r_t.target_oid.name_len,
+            msg->front.iov_len, data_len);
 }
 
 /*
@@ -1590,9 +1589,9 @@ static void maybe_request_map(struct ceph_osd_client *osdc)
        verify_osdc_locked(osdc);
        WARN_ON(!osdc->osdmap->epoch);
 
-       if (ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_FULL) ||
-           ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_PAUSERD) ||
-           ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_PAUSEWR)) {
+       if (ceph_osdmap_flag(osdc, CEPH_OSDMAP_FULL) ||
+           ceph_osdmap_flag(osdc, CEPH_OSDMAP_PAUSERD) ||
+           ceph_osdmap_flag(osdc, CEPH_OSDMAP_PAUSEWR)) {
                dout("%s osdc %p continuous\n", __func__, osdc);
                continuous = true;
        } else {
@@ -1629,19 +1628,19 @@ again:
        }
 
        if ((req->r_flags & CEPH_OSD_FLAG_WRITE) &&
-           ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_PAUSEWR)) {
+           ceph_osdmap_flag(osdc, CEPH_OSDMAP_PAUSEWR)) {
                dout("req %p pausewr\n", req);
                req->r_t.paused = true;
                maybe_request_map(osdc);
        } else if ((req->r_flags & CEPH_OSD_FLAG_READ) &&
-                  ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_PAUSERD)) {
+                  ceph_osdmap_flag(osdc, CEPH_OSDMAP_PAUSERD)) {
                dout("req %p pauserd\n", req);
                req->r_t.paused = true;
                maybe_request_map(osdc);
        } else if ((req->r_flags & CEPH_OSD_FLAG_WRITE) &&
                   !(req->r_flags & (CEPH_OSD_FLAG_FULL_TRY |
                                     CEPH_OSD_FLAG_FULL_FORCE)) &&
-                  (ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_FULL) ||
+                  (ceph_osdmap_flag(osdc, CEPH_OSDMAP_FULL) ||
                    pool_full(osdc, req->r_t.base_oloc.pool))) {
                dout("req %p full/pool_full\n", req);
                pr_warn_ratelimited("FULL or reached pool quota\n");
@@ -2280,7 +2279,7 @@ static void send_linger_ping(struct ceph_osd_linger_request *lreq)
        struct ceph_osd_request *req = lreq->ping_req;
        struct ceph_osd_req_op *op = &req->r_ops[0];
 
-       if (ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_PAUSERD)) {
+       if (ceph_osdmap_flag(osdc, CEPH_OSDMAP_PAUSERD)) {
                dout("%s PAUSERD\n", __func__);
                return;
        }
@@ -2893,6 +2892,9 @@ static void handle_reply(struct ceph_osd *osd, struct ceph_msg *msg)
                        dout("req %p tid %llu cb\n", req, req->r_tid);
                        __complete_request(req);
                }
+               if (m.flags & CEPH_OSD_FLAG_ONDISK)
+                       complete_all(&req->r_safe_completion);
+               ceph_osdc_put_request(req);
        } else {
                if (req->r_unsafe_callback) {
                        dout("req %p tid %llu unsafe-cb\n", req, req->r_tid);
@@ -2901,10 +2903,7 @@ static void handle_reply(struct ceph_osd *osd, struct ceph_msg *msg)
                        WARN_ON(1);
                }
        }
-       if (m.flags & CEPH_OSD_FLAG_ONDISK)
-               complete_all(&req->r_safe_completion);
 
-       ceph_osdc_put_request(req);
        return;
 
 fail_request:
@@ -3050,7 +3049,7 @@ static int handle_one_map(struct ceph_osd_client *osdc,
        bool skipped_map = false;
        bool was_full;
 
-       was_full = ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_FULL);
+       was_full = ceph_osdmap_flag(osdc, CEPH_OSDMAP_FULL);
        set_pool_was_full(osdc);
 
        if (incremental)
@@ -3088,7 +3087,7 @@ static int handle_one_map(struct ceph_osd_client *osdc,
                osdc->osdmap = newmap;
        }
 
-       was_full &= !ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_FULL);
+       was_full &= !ceph_osdmap_flag(osdc, CEPH_OSDMAP_FULL);
        scan_requests(&osdc->homeless_osd, skipped_map, was_full, true,
                      need_resend, need_resend_linger);
 
@@ -3174,9 +3173,9 @@ void ceph_osdc_handle_map(struct ceph_osd_client *osdc, struct ceph_msg *msg)
        if (ceph_check_fsid(osdc->client, &fsid) < 0)
                goto bad;
 
-       was_pauserd = ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_PAUSERD);
-       was_pausewr = ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_PAUSEWR) ||
-                     ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_FULL) ||
+       was_pauserd = ceph_osdmap_flag(osdc, CEPH_OSDMAP_PAUSERD);
+       was_pausewr = ceph_osdmap_flag(osdc, CEPH_OSDMAP_PAUSEWR) ||
+                     ceph_osdmap_flag(osdc, CEPH_OSDMAP_FULL) ||
                      have_pool_full(osdc);
 
        /* incremental maps */
@@ -3238,9 +3237,9 @@ done:
         * we find out when we are no longer full and stop returning
         * ENOSPC.
         */
-       pauserd = ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_PAUSERD);
-       pausewr = ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_PAUSEWR) ||
-                 ceph_osdmap_flag(osdc->osdmap, CEPH_OSDMAP_FULL) ||
+       pauserd = ceph_osdmap_flag(osdc, CEPH_OSDMAP_PAUSERD);
+       pausewr = ceph_osdmap_flag(osdc, CEPH_OSDMAP_PAUSEWR) ||
+                 ceph_osdmap_flag(osdc, CEPH_OSDMAP_FULL) ||
                  have_pool_full(osdc);
        if (was_pauserd || was_pausewr || pauserd || pausewr)
                maybe_request_map(osdc);
index cde52e9..03062bb 100644 (file)
@@ -1778,8 +1778,8 @@ int ceph_object_locator_to_pg(struct ceph_osdmap *osdmap,
        raw_pgid->seed = ceph_str_hash(pi->object_hash, oid->name,
                                       oid->name_len);
 
-       dout("%s %*pE -> raw_pgid %llu.%x\n", __func__, oid->name_len,
-            oid->name, raw_pgid->pool, raw_pgid->seed);
+       dout("%s %s -> raw_pgid %llu.%x\n", __func__, oid->name,
+            raw_pgid->pool, raw_pgid->seed);
        return 0;
 }
 EXPORT_SYMBOL(ceph_object_locator_to_pg);
index 5cfd26a..1cd2ec0 100644 (file)
@@ -309,8 +309,8 @@ void scm_detach_fds_compat(struct msghdr *kmsg, struct scm_cookie *scm)
        __scm_destroy(scm);
 }
 
-static int do_set_attach_filter(struct socket *sock, int level, int optname,
-                               char __user *optval, unsigned int optlen)
+/* allocate a 64-bit sock_fprog on the user stack for duration of syscall. */
+struct sock_fprog __user *get_compat_bpf_fprog(char __user *optval)
 {
        struct compat_sock_fprog __user *fprog32 = (struct compat_sock_fprog __user *)optval;
        struct sock_fprog __user *kfprog = compat_alloc_user_space(sizeof(struct sock_fprog));
@@ -323,6 +323,19 @@ static int do_set_attach_filter(struct socket *sock, int level, int optname,
            __get_user(ptr, &fprog32->filter) ||
            __put_user(len, &kfprog->len) ||
            __put_user(compat_ptr(ptr), &kfprog->filter))
+               return NULL;
+
+       return kfprog;
+}
+EXPORT_SYMBOL_GPL(get_compat_bpf_fprog);
+
+static int do_set_attach_filter(struct socket *sock, int level, int optname,
+                               char __user *optval, unsigned int optlen)
+{
+       struct sock_fprog __user *kfprog;
+
+       kfprog = get_compat_bpf_fprog(optval);
+       if (!kfprog)
                return -EFAULT;
 
        return sock_setsockopt(sock, level, optname, (char __user *)kfprog,
@@ -354,7 +367,8 @@ static int do_set_sock_timeout(struct socket *sock, int level,
 static int compat_sock_setsockopt(struct socket *sock, int level, int optname,
                                char __user *optval, unsigned int optlen)
 {
-       if (optname == SO_ATTACH_FILTER)
+       if (optname == SO_ATTACH_FILTER ||
+           optname == SO_ATTACH_REUSEPORT_CBPF)
                return do_set_attach_filter(sock, level, optname,
                                            optval, optlen);
        if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
index f96ee8b..be873e4 100644 (file)
@@ -47,6 +47,7 @@ nla_put_failure:
  * @xstats_type: TLV type for backward compatibility xstats TLV
  * @lock: statistics lock
  * @d: dumping handle
+ * @padattr: padding attribute
  *
  * Initializes the dumping handle, grabs the statistic lock and appends
  * an empty TLV header to the socket buffer for use a container for all
@@ -87,6 +88,7 @@ EXPORT_SYMBOL(gnet_stats_start_copy_compat);
  * @type: TLV type for top level statistic TLV
  * @lock: statistics lock
  * @d: dumping handle
+ * @padattr: padding attribute
  *
  * Initializes the dumping handle, grabs the statistic lock and appends
  * an empty TLV header to the socket buffer for use a container for all
index 941c284..2cab489 100644 (file)
@@ -55,18 +55,21 @@ int hwbm_pool_add(struct hwbm_pool *bm_pool, unsigned int buf_num, gfp_t gfp)
        spin_lock_irqsave(&bm_pool->lock, flags);
        if (bm_pool->buf_num == bm_pool->size) {
                pr_warn("pool already filled\n");
+               spin_unlock_irqrestore(&bm_pool->lock, flags);
                return bm_pool->buf_num;
        }
 
        if (buf_num + bm_pool->buf_num > bm_pool->size) {
                pr_warn("cannot allocate %d buffers for pool\n",
                        buf_num);
+               spin_unlock_irqrestore(&bm_pool->lock, flags);
                return 0;
        }
 
        if ((buf_num + bm_pool->buf_num) < bm_pool->buf_num) {
                pr_warn("Adding %d buffers to the %d current buffers will overflow\n",
                        buf_num,  bm_pool->buf_num);
+               spin_unlock_irqrestore(&bm_pool->lock, flags);
                return 0;
        }
 
index 2b3f76f..7a0b616 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/jiffies.h>
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
+#include <linux/of_net.h>
 
 #include "net-sysfs.h"
 
index 8604ae2..8b02df0 100644 (file)
@@ -2245,10 +2245,8 @@ static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until)
        hrtimer_set_expires(&t.timer, spin_until);
 
        remaining = ktime_to_ns(hrtimer_expires_remaining(&t.timer));
-       if (remaining <= 0) {
-               pkt_dev->next_tx = ktime_add_ns(spin_until, pkt_dev->delay);
-               return;
-       }
+       if (remaining <= 0)
+               goto out;
 
        start_time = ktime_get();
        if (remaining < 100000) {
@@ -2273,7 +2271,9 @@ static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until)
        }
 
        pkt_dev->idle_acc += ktime_to_ns(ktime_sub(end_time, start_time));
+out:
        pkt_dev->next_tx = ktime_add_ns(spin_until, pkt_dev->delay);
+       destroy_hrtimer_on_stack(&t.timer);
 }
 
 static inline void set_pkt_overhead(struct pktgen_dev *pkt_dev)
index ca207db..116187b 100644 (file)
@@ -1289,8 +1289,8 @@ ieee802154_llsec_parse_dev_addr(struct nlattr *nla,
                                     nl802154_dev_addr_policy))
                return -EINVAL;
 
-       if (!attrs[NL802154_DEV_ADDR_ATTR_PAN_ID] &&
-           !attrs[NL802154_DEV_ADDR_ATTR_MODE] &&
+       if (!attrs[NL802154_DEV_ADDR_ATTR_PAN_ID] ||
+           !attrs[NL802154_DEV_ADDR_ATTR_MODE] ||
            !(attrs[NL802154_DEV_ADDR_ATTR_SHORT] ||
              attrs[NL802154_DEV_ADDR_ATTR_EXTENDED]))
                return -EINVAL;
index 377424e..d39e9e4 100644 (file)
@@ -1681,6 +1681,14 @@ static __net_init int inet_init_net(struct net *net)
         */
        net->ipv4.ping_group_range.range[0] = make_kgid(&init_user_ns, 1);
        net->ipv4.ping_group_range.range[1] = make_kgid(&init_user_ns, 0);
+
+       /* Default values for sysctl-controlled parameters.
+        * We set them here, in case sysctl is not compiled.
+        */
+       net->ipv4.sysctl_ip_default_ttl = IPDEFTTL;
+       net->ipv4.sysctl_ip_dynaddr = 0;
+       net->ipv4.sysctl_ip_early_demux = 1;
+
        return 0;
 }
 
index bb04195..1cb67de 100644 (file)
@@ -999,10 +999,6 @@ static __net_init int ipv4_sysctl_init_net(struct net *net)
        if (!net->ipv4.sysctl_local_reserved_ports)
                goto err_ports;
 
-       net->ipv4.sysctl_ip_default_ttl = IPDEFTTL;
-       net->ipv4.sysctl_ip_dynaddr = 0;
-       net->ipv4.sysctl_ip_early_demux = 1;
-
        return 0;
 
 err_ports:
index d56c055..0ff31d9 100644 (file)
@@ -1618,12 +1618,12 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
                }
        }
 
-       if (rcu_access_pointer(sk->sk_filter)) {
-               if (udp_lib_checksum_complete(skb))
+       if (rcu_access_pointer(sk->sk_filter) &&
+           udp_lib_checksum_complete(skb))
                        goto csum_error;
-               if (sk_filter(sk, skb))
-                       goto drop;
-       }
+
+       if (sk_filter(sk, skb))
+               goto drop;
 
        udp_csum_pull_header(skb);
        if (sk_rcvqueues_full(sk, sk->sk_rcvbuf)) {
index 3f84113..2343e4f 100644 (file)
@@ -232,6 +232,15 @@ config IPV6_GRE
 
          Saying M here will produce a module called ip6_gre. If unsure, say N.
 
+config IPV6_FOU
+       tristate
+       default NET_FOU && IPV6
+
+config IPV6_FOU_TUNNEL
+       tristate
+       default NET_FOU_IP_TUNNELS && IPV6_FOU
+       select IPV6_TUNNEL
+
 config IPV6_MULTIPLE_TABLES
        bool "IPv6: Multiple Routing Tables"
        select FIB_RULES
index 7ec3129..6d8ea09 100644 (file)
@@ -42,7 +42,7 @@ obj-$(CONFIG_IPV6_VTI) += ip6_vti.o
 obj-$(CONFIG_IPV6_SIT) += sit.o
 obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o
 obj-$(CONFIG_IPV6_GRE) += ip6_gre.o
-obj-$(CONFIG_NET_FOU) += fou6.o
+obj-$(CONFIG_IPV6_FOU) += fou6.o
 
 obj-y += addrconf_core.o exthdrs_core.o ip6_checksum.o ip6_icmp.o
 obj-$(CONFIG_INET) += output_core.o protocol.o $(ipv6-offload)
index c972d0b..9ea249b 100644 (file)
@@ -69,7 +69,7 @@ int gue6_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
 }
 EXPORT_SYMBOL(gue6_build_header);
 
-#ifdef CONFIG_NET_FOU_IP_TUNNELS
+#if IS_ENABLED(CONFIG_IPV6_FOU_TUNNEL)
 
 static const struct ip6_tnl_encap_ops fou_ip6tun_ops = {
        .encap_hlen = fou_encap_hlen,
index af503f5..fdc9de2 100644 (file)
@@ -712,6 +712,7 @@ static void ip6gre_tnl_link_config(struct ip6_tnl *t, int set_mtu)
        fl6->daddr = p->raddr;
        fl6->flowi6_oif = p->link;
        fl6->flowlabel = 0;
+       fl6->flowi6_proto = IPPROTO_GRE;
 
        if (!(p->flags&IP6_TNL_F_USE_ORIG_TCLASS))
                fl6->flowlabel |= IPV6_TCLASS_MASK & p->flowinfo;
@@ -1027,6 +1028,8 @@ static int ip6gre_tunnel_init_common(struct net_device *dev)
 
        dev->hard_header_len = LL_MAX_HEADER + t_hlen;
        dev->mtu = ETH_DATA_LEN - t_hlen;
+       if (dev->type == ARPHRD_ETHER)
+               dev->mtu -= ETH_HLEN;
        if (!(tunnel->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
                dev->mtu -= 8;
 
@@ -1253,6 +1256,8 @@ static int ip6gre_tap_init(struct net_device *dev)
        if (ret)
                return ret;
 
+       dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
+
        tunnel = netdev_priv(dev);
 
        ip6gre_tnl_link_config(tunnel, 1);
@@ -1286,6 +1291,7 @@ static void ip6gre_tap_setup(struct net_device *dev)
 
        dev->features |= NETIF_F_NETNS_LOCAL;
        dev->priv_flags &= ~IFF_TX_SKB_SHARING;
+       dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
 }
 
 static bool ip6gre_netlink_encap_parms(struct nlattr *data[],
index cbf127a..635b8d3 100644 (file)
@@ -1071,17 +1071,12 @@ struct dst_entry *ip6_sk_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6,
                                         const struct in6_addr *final_dst)
 {
        struct dst_entry *dst = sk_dst_check(sk, inet6_sk(sk)->dst_cookie);
-       int err;
 
        dst = ip6_sk_dst_check(sk, dst, fl6);
+       if (!dst)
+               dst = ip6_dst_lookup_flow(sk, fl6, final_dst);
 
-       err = ip6_dst_lookup_tail(sock_net(sk), sk, &dst, fl6);
-       if (err)
-               return ERR_PTR(err);
-       if (final_dst)
-               fl6->daddr = *final_dst;
-
-       return xfrm_lookup_route(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0);
+       return dst;
 }
 EXPORT_SYMBOL_GPL(ip6_sk_dst_lookup_flow);
 
index 6989c70..4a84b5a 100644 (file)
@@ -33,6 +33,7 @@ static bool nf_dup_ipv6_route(struct net *net, struct sk_buff *skb,
        fl6.daddr = *gw;
        fl6.flowlabel = (__force __be32)(((iph->flow_lbl[0] & 0xF) << 16) |
                        (iph->flow_lbl[1] << 8) | iph->flow_lbl[2]);
+       fl6.flowi6_flags = FLOWI_FLAG_KNOWN_NH;
        dst = ip6_route_output(net, NULL, &fl6);
        if (dst->error) {
                dst_release(dst);
index 79e33e0..f36c2d0 100644 (file)
@@ -1721,7 +1721,9 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
        destp = ntohs(inet->inet_dport);
        srcp  = ntohs(inet->inet_sport);
 
-       if (icsk->icsk_pending == ICSK_TIME_RETRANS) {
+       if (icsk->icsk_pending == ICSK_TIME_RETRANS ||
+           icsk->icsk_pending == ICSK_TIME_EARLY_RETRANS ||
+           icsk->icsk_pending == ICSK_TIME_LOSS_PROBE) {
                timer_active    = 1;
                timer_expires   = icsk->icsk_timeout;
        } else if (icsk->icsk_pending == ICSK_TIME_PROBE0) {
index 2da1896..f421c9f 100644 (file)
@@ -653,12 +653,12 @@ int udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
                }
        }
 
-       if (rcu_access_pointer(sk->sk_filter)) {
-               if (udp_lib_checksum_complete(skb))
-                       goto csum_error;
-               if (sk_filter(sk, skb))
-                       goto drop;
-       }
+       if (rcu_access_pointer(sk->sk_filter) &&
+           udp_lib_checksum_complete(skb))
+               goto csum_error;
+
+       if (sk_filter(sk, skb))
+               goto drop;
 
        udp_csum_pull_header(skb);
        if (sk_rcvqueues_full(sk, sk->sk_rcvbuf)) {
index 6edfa99..1e40dac 100644 (file)
@@ -1581,7 +1581,7 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32
        /* Mark socket as an encapsulation socket. See net/ipv4/udp.c */
        tunnel->encap = encap;
        if (encap == L2TP_ENCAPTYPE_UDP) {
-               struct udp_tunnel_sock_cfg udp_cfg;
+               struct udp_tunnel_sock_cfg udp_cfg = { };
 
                udp_cfg.sk_user_data = tunnel;
                udp_cfg.encap_type = UDP_ENCAP_L2TPINUDP;
index c6f5df1..6c54e03 100644 (file)
@@ -128,6 +128,7 @@ static inline struct sock *l2tp_ip6_bind_lookup(struct net *net,
  */
 static int l2tp_ip6_recv(struct sk_buff *skb)
 {
+       struct net *net = dev_net(skb->dev);
        struct sock *sk;
        u32 session_id;
        u32 tunnel_id;
@@ -154,7 +155,7 @@ static int l2tp_ip6_recv(struct sk_buff *skb)
        }
 
        /* Ok, this is a data packet. Lookup the session. */
-       session = l2tp_session_find(&init_net, NULL, session_id);
+       session = l2tp_session_find(net, NULL, session_id);
        if (session == NULL)
                goto discard;
 
@@ -188,14 +189,14 @@ pass_up:
                goto discard;
 
        tunnel_id = ntohl(*(__be32 *) &skb->data[4]);
-       tunnel = l2tp_tunnel_find(&init_net, tunnel_id);
+       tunnel = l2tp_tunnel_find(net, tunnel_id);
        if (tunnel != NULL)
                sk = tunnel->sock;
        else {
                struct ipv6hdr *iph = ipv6_hdr(skb);
 
                read_lock_bh(&l2tp_ip6_lock);
-               sk = __l2tp_ip6_bind_lookup(&init_net, &iph->daddr,
+               sk = __l2tp_ip6_bind_lookup(net, &iph->daddr,
                                            0, tunnel_id);
                read_unlock_bh(&l2tp_ip6_lock);
        }
@@ -263,6 +264,7 @@ static int l2tp_ip6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        struct inet_sock *inet = inet_sk(sk);
        struct ipv6_pinfo *np = inet6_sk(sk);
        struct sockaddr_l2tpip6 *addr = (struct sockaddr_l2tpip6 *) uaddr;
+       struct net *net = sock_net(sk);
        __be32 v4addr = 0;
        int addr_type;
        int err;
@@ -286,7 +288,7 @@ static int l2tp_ip6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 
        err = -EADDRINUSE;
        read_lock_bh(&l2tp_ip6_lock);
-       if (__l2tp_ip6_bind_lookup(&init_net, &addr->l2tp_addr,
+       if (__l2tp_ip6_bind_lookup(net, &addr->l2tp_addr,
                                   sk->sk_bound_dev_if, addr->l2tp_conn_id))
                goto out_in_use;
        read_unlock_bh(&l2tp_ip6_lock);
@@ -456,7 +458,7 @@ static int l2tp_ip6_backlog_recv(struct sock *sk, struct sk_buff *skb)
        return 0;
 
 drop:
-       IP_INC_STATS(&init_net, IPSTATS_MIB_INDISCARDS);
+       IP_INC_STATS(sock_net(sk), IPSTATS_MIB_INDISCARDS);
        kfree_skb(skb);
        return -1;
 }
index 5dba899..1824708 100644 (file)
@@ -444,10 +444,9 @@ static void lapb_state3_machine(struct lapb_cb *lapb, struct sk_buff *skb,
                break;
 
        case LAPB_FRMR:
-               lapb_dbg(1, "(%p) S3 RX FRMR(%d) %02X %02X %02X %02X %02X\n",
+               lapb_dbg(1, "(%p) S3 RX FRMR(%d) %5ph\n",
                         lapb->dev, frame->pf,
-                        skb->data[0], skb->data[1], skb->data[2],
-                        skb->data[3], skb->data[4]);
+                        skb->data);
                lapb_establish_data_link(lapb);
                lapb_dbg(0, "(%p) S3 -> S1\n", lapb->dev);
                lapb_requeue_frames(lapb);
index ba4d015..482c94d 100644 (file)
@@ -148,9 +148,7 @@ void lapb_transmit_buffer(struct lapb_cb *lapb, struct sk_buff *skb, int type)
                }
        }
 
-       lapb_dbg(2, "(%p) S%d TX %02X %02X %02X\n",
-                lapb->dev, lapb->state,
-                skb->data[0], skb->data[1], skb->data[2]);
+       lapb_dbg(2, "(%p) S%d TX %3ph\n", lapb->dev, lapb->state, skb->data);
 
        if (!lapb_data_transmit(lapb, skb))
                kfree_skb(skb);
index 9d0a426..3c1914d 100644 (file)
@@ -113,9 +113,7 @@ int lapb_decode(struct lapb_cb *lapb, struct sk_buff *skb,
 {
        frame->type = LAPB_ILLEGAL;
 
-       lapb_dbg(2, "(%p) S%d RX %02X %02X %02X\n",
-                lapb->dev, lapb->state,
-                skb->data[0], skb->data[1], skb->data[2]);
+       lapb_dbg(2, "(%p) S%d RX %3ph\n", lapb->dev, lapb->state, skb->data);
 
        /* We always need to look at 2 bytes, sometimes we need
         * to look at 3 and those cases are handled below.
@@ -284,10 +282,9 @@ void lapb_transmit_frmr(struct lapb_cb *lapb)
                dptr++;
                *dptr++ = lapb->frmr_type;
 
-               lapb_dbg(1, "(%p) S%d TX FRMR %02X %02X %02X %02X %02X\n",
+               lapb_dbg(1, "(%p) S%d TX FRMR %5ph\n",
                         lapb->dev, lapb->state,
-                        skb->data[1], skb->data[2], skb->data[3],
-                        skb->data[4], skb->data[5]);
+                        &skb->data[1]);
        } else {
                dptr    = skb_put(skb, 4);
                *dptr++ = LAPB_FRMR;
@@ -299,9 +296,8 @@ void lapb_transmit_frmr(struct lapb_cb *lapb)
                dptr++;
                *dptr++ = lapb->frmr_type;
 
-               lapb_dbg(1, "(%p) S%d TX FRMR %02X %02X %02X\n",
-                        lapb->dev, lapb->state, skb->data[1],
-                        skb->data[2], skb->data[3]);
+               lapb_dbg(1, "(%p) S%d TX FRMR %3ph\n",
+                        lapb->dev, lapb->state, &skb->data[1]);
        }
 
        lapb_transmit_buffer(lapb, skb, LAPB_RESPONSE);
index 4c6404e..21b1fdf 100644 (file)
@@ -161,6 +161,10 @@ void mesh_sta_cleanup(struct sta_info *sta)
                del_timer_sync(&sta->mesh->plink_timer);
        }
 
+       /* make sure no readers can access nexthop sta from here on */
+       mesh_path_flush_by_nexthop(sta);
+       synchronize_net();
+
        if (changed)
                ieee80211_mbss_info_change_notify(sdata, changed);
 }
index c8b8ccc..78b0ef3 100644 (file)
@@ -280,7 +280,7 @@ struct ieee80211_fast_tx {
        u8 sa_offs, da_offs, pn_offs;
        u8 band;
        u8 hdr[30 + 2 + IEEE80211_FAST_XMIT_MAX_IV +
-              sizeof(rfc1042_header)];
+              sizeof(rfc1042_header)] __aligned(2);
 
        struct rcu_head rcu_head;
 };
index 2cb3c62..096a451 100644 (file)
@@ -762,7 +762,7 @@ static int expire_quiescent_template(struct netns_ipvs *ipvs,
  *     If available, return 1, otherwise invalidate this connection
  *     template and return 0.
  */
-int ip_vs_check_template(struct ip_vs_conn *ct)
+int ip_vs_check_template(struct ip_vs_conn *ct, struct ip_vs_dest *cdest)
 {
        struct ip_vs_dest *dest = ct->dest;
        struct netns_ipvs *ipvs = ct->ipvs;
@@ -772,7 +772,8 @@ int ip_vs_check_template(struct ip_vs_conn *ct)
         */
        if ((dest == NULL) ||
            !(dest->flags & IP_VS_DEST_F_AVAILABLE) ||
-           expire_quiescent_template(ipvs, dest)) {
+           expire_quiescent_template(ipvs, dest) ||
+           (cdest && (dest != cdest))) {
                IP_VS_DBG_BUF(9, "check_template: dest not available for "
                              "protocol %s s:%s:%d v:%s:%d "
                              "-> d:%s:%d\n",
index 1207f20..2c1b498 100644 (file)
@@ -321,7 +321,7 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
 
        /* Check if a template already exists */
        ct = ip_vs_ct_in_get(&param);
-       if (!ct || !ip_vs_check_template(ct)) {
+       if (!ct || !ip_vs_check_template(ct, NULL)) {
                struct ip_vs_scheduler *sched;
 
                /*
@@ -1154,7 +1154,8 @@ struct ip_vs_conn *ip_vs_new_conn_out(struct ip_vs_service *svc,
                                                  vport, &param) < 0)
                        return NULL;
                ct = ip_vs_ct_in_get(&param);
-               if (!ct) {
+               /* check if template exists and points to the same dest */
+               if (!ct || !ip_vs_check_template(ct, dest)) {
                        ct = ip_vs_conn_new(&param, dest->af, daddr, dport,
                                            IP_VS_CONN_F_TEMPLATE, dest, 0);
                        if (!ct) {
index 883c691..19efeba 100644 (file)
@@ -632,6 +632,7 @@ static int __init nf_conntrack_ftp_init(void)
                        if (ret) {
                                pr_err("failed to register helper for pf: %d port: %d\n",
                                       ftp[i][j].tuple.src.l3num, ports[i]);
+                               ports_c = i;
                                nf_conntrack_ftp_fini();
                                return ret;
                        }
index f703adb..196cb39 100644 (file)
@@ -361,9 +361,10 @@ EXPORT_SYMBOL_GPL(nf_ct_helper_log);
 
 int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
 {
-       int ret = 0;
-       struct nf_conntrack_helper *cur;
+       struct nf_conntrack_tuple_mask mask = { .src.u.all = htons(0xFFFF) };
        unsigned int h = helper_hash(&me->tuple);
+       struct nf_conntrack_helper *cur;
+       int ret = 0;
 
        BUG_ON(me->expect_policy == NULL);
        BUG_ON(me->expect_class_max >= NF_CT_MAX_EXPECT_CLASSES);
@@ -371,9 +372,7 @@ int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
 
        mutex_lock(&nf_ct_helper_mutex);
        hlist_for_each_entry(cur, &nf_ct_helper_hash[h], hnode) {
-               if (strncmp(cur->name, me->name, NF_CT_HELPER_NAME_LEN) == 0 &&
-                   cur->tuple.src.l3num == me->tuple.src.l3num &&
-                   cur->tuple.dst.protonum == me->tuple.dst.protonum) {
+               if (nf_ct_tuple_src_mask_cmp(&cur->tuple, &me->tuple, &mask)) {
                        ret = -EEXIST;
                        goto out;
                }
index 8b6da27..f97ac61 100644 (file)
@@ -271,6 +271,7 @@ static int __init nf_conntrack_irc_init(void)
                if (ret) {
                        pr_err("failed to register helper for pf: %u port: %u\n",
                               irc[i].tuple.src.l3num, ports[i]);
+                       ports_c = i;
                        nf_conntrack_irc_fini();
                        return ret;
                }
index 7523a57..3fcbaab 100644 (file)
@@ -223,6 +223,7 @@ static int __init nf_conntrack_sane_init(void)
                        if (ret) {
                                pr_err("failed to register helper for pf: %d port: %d\n",
                                       sane[i][j].tuple.src.l3num, ports[i]);
+                               ports_c = i;
                                nf_conntrack_sane_fini();
                                return ret;
                        }
index 3e06402..f72ba55 100644 (file)
@@ -1669,6 +1669,7 @@ static int __init nf_conntrack_sip_init(void)
                        if (ret) {
                                pr_err("failed to register helper for pf: %u port: %u\n",
                                       sip[i][j].tuple.src.l3num, ports[i]);
+                               ports_c = i;
                                nf_conntrack_sip_fini();
                                return ret;
                        }
index f87e84e..c026c47 100644 (file)
@@ -487,8 +487,6 @@ static struct ctl_table nf_ct_sysctl_table[] = {
        { }
 };
 
-#define NET_NF_CONNTRACK_MAX 2089
-
 static struct ctl_table nf_ct_netfilter_table[] = {
        {
                .procname       = "nf_conntrack_max",
index 36f9640..2e65b54 100644 (file)
@@ -142,6 +142,7 @@ static int __init nf_conntrack_tftp_init(void)
                        if (ret) {
                                pr_err("failed to register helper for pf: %u port: %u\n",
                                       tftp[i][j].tuple.src.l3num, ports[i]);
+                               ports_c = i;
                                nf_conntrack_tftp_fini();
                                return ret;
                        }
index 5baa8e2..b19ad20 100644 (file)
  * Once the queue is registered it must reinject all packets it
  * receives, no matter what.
  */
-static const struct nf_queue_handler __rcu *queue_handler __read_mostly;
 
 /* return EBUSY when somebody else is registered, return EEXIST if the
  * same handler is registered, return 0 in case of success. */
-void nf_register_queue_handler(const struct nf_queue_handler *qh)
+void nf_register_queue_handler(struct net *net, const struct nf_queue_handler *qh)
 {
        /* should never happen, we only have one queueing backend in kernel */
-       WARN_ON(rcu_access_pointer(queue_handler));
-       rcu_assign_pointer(queue_handler, qh);
+       WARN_ON(rcu_access_pointer(net->nf.queue_handler));
+       rcu_assign_pointer(net->nf.queue_handler, qh);
 }
 EXPORT_SYMBOL(nf_register_queue_handler);
 
 /* The caller must flush their queue before this */
-void nf_unregister_queue_handler(void)
+void nf_unregister_queue_handler(struct net *net)
 {
-       RCU_INIT_POINTER(queue_handler, NULL);
-       synchronize_rcu();
+       RCU_INIT_POINTER(net->nf.queue_handler, NULL);
 }
 EXPORT_SYMBOL(nf_unregister_queue_handler);
 
@@ -103,7 +101,7 @@ void nf_queue_nf_hook_drop(struct net *net, struct nf_hook_ops *ops)
        const struct nf_queue_handler *qh;
 
        rcu_read_lock();
-       qh = rcu_dereference(queue_handler);
+       qh = rcu_dereference(net->nf.queue_handler);
        if (qh)
                qh->nf_hook_drop(net, ops);
        rcu_read_unlock();
@@ -122,9 +120,10 @@ int nf_queue(struct sk_buff *skb,
        struct nf_queue_entry *entry = NULL;
        const struct nf_afinfo *afinfo;
        const struct nf_queue_handler *qh;
+       struct net *net = state->net;
 
        /* QUEUE == DROP if no one is waiting, to be safe. */
-       qh = rcu_dereference(queue_handler);
+       qh = rcu_dereference(net->nf.queue_handler);
        if (!qh) {
                status = -ESRCH;
                goto err;
index 4d292b9..7b7aa87 100644 (file)
@@ -2647,6 +2647,8 @@ static int nf_tables_getset(struct net *net, struct sock *nlsk,
        /* Only accept unspec with dump */
        if (nfmsg->nfgen_family == NFPROTO_UNSPEC)
                return -EAFNOSUPPORT;
+       if (!nla[NFTA_SET_TABLE])
+               return -EINVAL;
 
        set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME]);
        if (IS_ERR(set))
index aa93877..5d36a09 100644 (file)
@@ -557,7 +557,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
 
        if (entskb->tstamp.tv64) {
                struct nfqnl_msg_packet_timestamp ts;
-               struct timespec64 kts = ktime_to_timespec64(skb->tstamp);
+               struct timespec64 kts = ktime_to_timespec64(entskb->tstamp);
 
                ts.sec = cpu_to_be64(kts.tv_sec);
                ts.usec = cpu_to_be64(kts.tv_nsec / NSEC_PER_USEC);
@@ -1482,21 +1482,29 @@ static int __net_init nfnl_queue_net_init(struct net *net)
                         net->nf.proc_netfilter, &nfqnl_file_ops))
                return -ENOMEM;
 #endif
+       nf_register_queue_handler(net, &nfqh);
        return 0;
 }
 
 static void __net_exit nfnl_queue_net_exit(struct net *net)
 {
+       nf_unregister_queue_handler(net);
 #ifdef CONFIG_PROC_FS
        remove_proc_entry("nfnetlink_queue", net->nf.proc_netfilter);
 #endif
 }
 
+static void nfnl_queue_net_exit_batch(struct list_head *net_exit_list)
+{
+       synchronize_rcu();
+}
+
 static struct pernet_operations nfnl_queue_net_ops = {
-       .init   = nfnl_queue_net_init,
-       .exit   = nfnl_queue_net_exit,
-       .id     = &nfnl_queue_net_id,
-       .size   = sizeof(struct nfnl_queue_net),
+       .init           = nfnl_queue_net_init,
+       .exit           = nfnl_queue_net_exit,
+       .exit_batch     = nfnl_queue_net_exit_batch,
+       .id             = &nfnl_queue_net_id,
+       .size           = sizeof(struct nfnl_queue_net),
 };
 
 static int __init nfnetlink_queue_init(void)
@@ -1517,7 +1525,6 @@ static int __init nfnetlink_queue_init(void)
        }
 
        register_netdevice_notifier(&nfqnl_dev_notifier);
-       nf_register_queue_handler(&nfqh);
        return status;
 
 cleanup_netlink_notifier:
@@ -1529,7 +1536,6 @@ out:
 
 static void __exit nfnetlink_queue_fini(void)
 {
-       nf_unregister_queue_handler();
        unregister_netdevice_notifier(&nfqnl_dev_notifier);
        nfnetlink_subsys_unregister(&nfqnl_subsys);
        netlink_unregister_notifier(&nfqnl_rtnl_notifier);
index c69c892..2675d58 100644 (file)
@@ -612,7 +612,7 @@ int xt_compat_check_entry_offsets(const void *base, const char *elems,
                return -EINVAL;
 
        if (strcmp(t->u.user.name, XT_STANDARD_TARGET) == 0 &&
-           target_offset + sizeof(struct compat_xt_standard_target) != next_offset)
+           COMPAT_XT_ALIGN(target_offset + sizeof(struct compat_xt_standard_target)) != next_offset)
                return -EINVAL;
 
        /* compat_xt_entry match has less strict aligment requirements,
@@ -694,7 +694,7 @@ int xt_check_entry_offsets(const void *base,
                return -EINVAL;
 
        if (strcmp(t->u.user.name, XT_STANDARD_TARGET) == 0 &&
-           target_offset + sizeof(struct xt_standard_target) != next_offset)
+           XT_ALIGN(target_offset + sizeof(struct xt_standard_target)) != next_offset)
                return -EINVAL;
 
        return xt_check_entry_match(elems, base + target_offset,
index 879185f..9a3eb7a 100644 (file)
@@ -137,11 +137,23 @@ static bool is_flow_key_valid(const struct sw_flow_key *key)
        return !!key->eth.type;
 }
 
+static void update_ethertype(struct sk_buff *skb, struct ethhdr *hdr,
+                            __be16 ethertype)
+{
+       if (skb->ip_summed == CHECKSUM_COMPLETE) {
+               __be16 diff[] = { ~(hdr->h_proto), ethertype };
+
+               skb->csum = ~csum_partial((char *)diff, sizeof(diff),
+                                       ~skb->csum);
+       }
+
+       hdr->h_proto = ethertype;
+}
+
 static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key,
                     const struct ovs_action_push_mpls *mpls)
 {
        __be32 *new_mpls_lse;
-       struct ethhdr *hdr;
 
        /* Networking stack do not allow simultaneous Tunnel and MPLS GSO. */
        if (skb->encapsulation)
@@ -160,9 +172,7 @@ static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key,
 
        skb_postpush_rcsum(skb, new_mpls_lse, MPLS_HLEN);
 
-       hdr = eth_hdr(skb);
-       hdr->h_proto = mpls->mpls_ethertype;
-
+       update_ethertype(skb, eth_hdr(skb), mpls->mpls_ethertype);
        if (!skb->inner_protocol)
                skb_set_inner_protocol(skb, skb->protocol);
        skb->protocol = mpls->mpls_ethertype;
@@ -193,7 +203,7 @@ static int pop_mpls(struct sk_buff *skb, struct sw_flow_key *key,
         * field correctly in the presence of VLAN tags.
         */
        hdr = (struct ethhdr *)(skb_mpls_header(skb) - ETH_HLEN);
-       hdr->h_proto = ethertype;
+       update_ethertype(skb, hdr, ethertype);
        if (eth_p_mpls(skb->protocol))
                skb->protocol = ethertype;
 
index 4040eb9..9bff6ef 100644 (file)
@@ -93,6 +93,7 @@
 #include <net/inet_common.h>
 #endif
 #include <linux/bpf.h>
+#include <net/compat.h>
 
 #include "internal.h"
 
@@ -3940,6 +3941,27 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
 }
 
 
+#ifdef CONFIG_COMPAT
+static int compat_packet_setsockopt(struct socket *sock, int level, int optname,
+                                   char __user *optval, unsigned int optlen)
+{
+       struct packet_sock *po = pkt_sk(sock->sk);
+
+       if (level != SOL_PACKET)
+               return -ENOPROTOOPT;
+
+       if (optname == PACKET_FANOUT_DATA &&
+           po->fanout && po->fanout->type == PACKET_FANOUT_CBPF) {
+               optval = (char __user *)get_compat_bpf_fprog(optval);
+               if (!optval)
+                       return -EFAULT;
+               optlen = sizeof(struct sock_fprog);
+       }
+
+       return packet_setsockopt(sock, level, optname, optval, optlen);
+}
+#endif
+
 static int packet_notifier(struct notifier_block *this,
                           unsigned long msg, void *ptr)
 {
@@ -4416,6 +4438,9 @@ static const struct proto_ops packet_ops = {
        .shutdown =     sock_no_shutdown,
        .setsockopt =   packet_setsockopt,
        .getsockopt =   packet_getsockopt,
+#ifdef CONFIG_COMPAT
+       .compat_setsockopt = compat_packet_setsockopt,
+#endif
        .sendmsg =      packet_sendmsg,
        .recvmsg =      packet_recvmsg,
        .mmap =         packet_mmap,
index 80256b0..387df5f 100644 (file)
@@ -74,6 +74,7 @@ enum {
        RDS_CONN_CONNECTING,
        RDS_CONN_DISCONNECTING,
        RDS_CONN_UP,
+       RDS_CONN_RESETTING,
        RDS_CONN_ERROR,
 };
 
@@ -813,6 +814,7 @@ void rds_connect_worker(struct work_struct *);
 void rds_shutdown_worker(struct work_struct *);
 void rds_send_worker(struct work_struct *);
 void rds_recv_worker(struct work_struct *);
+void rds_connect_path_complete(struct rds_connection *conn, int curr);
 void rds_connect_complete(struct rds_connection *conn);
 
 /* transport.c */
index c0be1ec..8413f6c 100644 (file)
@@ -561,5 +561,7 @@ void rds_inc_info_copy(struct rds_incoming *inc,
                minfo.fport = inc->i_hdr.h_dport;
        }
 
+       minfo.flags = 0;
+
        rds_info_copy(iter, &minfo, sizeof(minfo));
 }
index c9cdb35..b1962f8 100644 (file)
@@ -99,6 +99,7 @@ void rds_send_reset(struct rds_connection *conn)
        list_splice_init(&conn->c_retrans, &conn->c_send_queue);
        spin_unlock_irqrestore(&conn->c_lock, flags);
 }
+EXPORT_SYMBOL_GPL(rds_send_reset);
 
 static int acquire_in_xmit(struct rds_connection *conn)
 {
index 86187da..74ee126 100644 (file)
@@ -126,9 +126,81 @@ void rds_tcp_restore_callbacks(struct socket *sock,
 }
 
 /*
- * This is the only path that sets tc->t_sock.  Send and receive trust that
- * it is set.  The RDS_CONN_UP bit protects those paths from being
- * called while it isn't set.
+ * rds_tcp_reset_callbacks() switches the to the new sock and
+ * returns the existing tc->t_sock.
+ *
+ * The only functions that set tc->t_sock are rds_tcp_set_callbacks
+ * and rds_tcp_reset_callbacks.  Send and receive trust that
+ * it is set.  The absence of RDS_CONN_UP bit protects those paths
+ * from being called while it isn't set.
+ */
+void rds_tcp_reset_callbacks(struct socket *sock,
+                            struct rds_connection *conn)
+{
+       struct rds_tcp_connection *tc = conn->c_transport_data;
+       struct socket *osock = tc->t_sock;
+
+       if (!osock)
+               goto newsock;
+
+       /* Need to resolve a duelling SYN between peers.
+        * We have an outstanding SYN to this peer, which may
+        * potentially have transitioned to the RDS_CONN_UP state,
+        * so we must quiesce any send threads before resetting
+        * c_transport_data. We quiesce these threads by setting
+        * c_state to something other than RDS_CONN_UP, and then
+        * waiting for any existing threads in rds_send_xmit to
+        * complete release_in_xmit(). (Subsequent threads entering
+        * rds_send_xmit() will bail on !rds_conn_up().
+        *
+        * However an incoming syn-ack at this point would end up
+        * marking the conn as RDS_CONN_UP, and would again permit
+        * rds_send_xmi() threads through, so ideally we would
+        * synchronize on RDS_CONN_UP after lock_sock(), but cannot
+        * do that: waiting on !RDS_IN_XMIT after lock_sock() may
+        * end up deadlocking with tcp_sendmsg(), and the RDS_IN_XMIT
+        * would not get set. As a result, we set c_state to
+        * RDS_CONN_RESETTTING, to ensure that rds_tcp_state_change
+        * cannot mark rds_conn_path_up() in the window before lock_sock()
+        */
+       atomic_set(&conn->c_state, RDS_CONN_RESETTING);
+       wait_event(conn->c_waitq, !test_bit(RDS_IN_XMIT, &conn->c_flags));
+       lock_sock(osock->sk);
+       /* reset receive side state for rds_tcp_data_recv() for osock  */
+       if (tc->t_tinc) {
+               rds_inc_put(&tc->t_tinc->ti_inc);
+               tc->t_tinc = NULL;
+       }
+       tc->t_tinc_hdr_rem = sizeof(struct rds_header);
+       tc->t_tinc_data_rem = 0;
+       tc->t_sock = NULL;
+
+       write_lock_bh(&osock->sk->sk_callback_lock);
+
+       osock->sk->sk_user_data = NULL;
+       osock->sk->sk_data_ready = tc->t_orig_data_ready;
+       osock->sk->sk_write_space = tc->t_orig_write_space;
+       osock->sk->sk_state_change = tc->t_orig_state_change;
+       write_unlock_bh(&osock->sk->sk_callback_lock);
+       release_sock(osock->sk);
+       sock_release(osock);
+newsock:
+       rds_send_reset(conn);
+       lock_sock(sock->sk);
+       write_lock_bh(&sock->sk->sk_callback_lock);
+       tc->t_sock = sock;
+       sock->sk->sk_user_data = conn;
+       sock->sk->sk_data_ready = rds_tcp_data_ready;
+       sock->sk->sk_write_space = rds_tcp_write_space;
+       sock->sk->sk_state_change = rds_tcp_state_change;
+
+       write_unlock_bh(&sock->sk->sk_callback_lock);
+       release_sock(sock->sk);
+}
+
+/* Add tc to rds_tcp_tc_list and set tc->t_sock. See comments
+ * above rds_tcp_reset_callbacks for notes about synchronization
+ * with data path
  */
 void rds_tcp_set_callbacks(struct socket *sock, struct rds_connection *conn)
 {
index 41c2283..ec0602b 100644 (file)
@@ -50,6 +50,7 @@ struct rds_tcp_statistics {
 void rds_tcp_tune(struct socket *sock);
 void rds_tcp_nonagle(struct socket *sock);
 void rds_tcp_set_callbacks(struct socket *sock, struct rds_connection *conn);
+void rds_tcp_reset_callbacks(struct socket *sock, struct rds_connection *conn);
 void rds_tcp_restore_callbacks(struct socket *sock,
                               struct rds_tcp_connection *tc);
 u32 rds_tcp_snd_nxt(struct rds_tcp_connection *tc);
index fb82e0a..fba13d0 100644 (file)
@@ -60,7 +60,7 @@ void rds_tcp_state_change(struct sock *sk)
                case TCP_SYN_RECV:
                        break;
                case TCP_ESTABLISHED:
-                       rds_connect_complete(conn);
+                       rds_connect_path_complete(conn, RDS_CONN_CONNECTING);
                        break;
                case TCP_CLOSE_WAIT:
                case TCP_CLOSE:
index 4bf4bef..686b1d0 100644 (file)
@@ -78,7 +78,6 @@ int rds_tcp_accept_one(struct socket *sock)
        struct inet_sock *inet;
        struct rds_tcp_connection *rs_tcp = NULL;
        int conn_state;
-       struct sock *nsk;
 
        if (!sock) /* module unload or netns delete in progress */
                return -ENETUNREACH;
@@ -136,26 +135,21 @@ int rds_tcp_accept_one(struct socket *sock)
                    !conn->c_outgoing) {
                        goto rst_nsk;
                } else {
-                       atomic_set(&conn->c_state, RDS_CONN_CONNECTING);
-                       wait_event(conn->c_waitq,
-                                  !test_bit(RDS_IN_XMIT, &conn->c_flags));
-                       rds_tcp_restore_callbacks(rs_tcp->t_sock, rs_tcp);
+                       rds_tcp_reset_callbacks(new_sock, conn);
                        conn->c_outgoing = 0;
+                       /* rds_connect_path_complete() marks RDS_CONN_UP */
+                       rds_connect_path_complete(conn, RDS_CONN_DISCONNECTING);
                }
+       } else {
+               rds_tcp_set_callbacks(new_sock, conn);
+               rds_connect_path_complete(conn, RDS_CONN_CONNECTING);
        }
-       rds_tcp_set_callbacks(new_sock, conn);
-       rds_connect_complete(conn); /* marks RDS_CONN_UP */
        new_sock = NULL;
        ret = 0;
        goto out;
 rst_nsk:
        /* reset the newly returned accept sock and bail */
-       nsk = new_sock->sk;
-       rds_tcp_stats_inc(s_tcp_listen_closed_stale);
-       nsk->sk_user_data = NULL;
-       nsk->sk_prot->disconnect(nsk, 0);
-       tcp_done(nsk);
-       new_sock = NULL;
+       kernel_sock_shutdown(new_sock, SHUT_RDWR);
        ret = 0;
 out:
        if (rs_tcp)
index 454aa6d..4a32304 100644 (file)
@@ -71,9 +71,9 @@
 struct workqueue_struct *rds_wq;
 EXPORT_SYMBOL_GPL(rds_wq);
 
-void rds_connect_complete(struct rds_connection *conn)
+void rds_connect_path_complete(struct rds_connection *conn, int curr)
 {
-       if (!rds_conn_transition(conn, RDS_CONN_CONNECTING, RDS_CONN_UP)) {
+       if (!rds_conn_transition(conn, curr, RDS_CONN_UP)) {
                printk(KERN_WARNING "%s: Cannot transition to state UP, "
                                "current state is %d\n",
                                __func__,
@@ -90,6 +90,12 @@ void rds_connect_complete(struct rds_connection *conn)
        queue_delayed_work(rds_wq, &conn->c_send_w, 0);
        queue_delayed_work(rds_wq, &conn->c_recv_w, 0);
 }
+EXPORT_SYMBOL_GPL(rds_connect_path_complete);
+
+void rds_connect_complete(struct rds_connection *conn)
+{
+       rds_connect_path_complete(conn, RDS_CONN_CONNECTING);
+}
 EXPORT_SYMBOL_GPL(rds_connect_complete);
 
 /*
index 6b726a0..bab56ed 100644 (file)
@@ -1162,9 +1162,7 @@ static int rxkad_init(void)
        /* pin the cipher we need so that the crypto layer doesn't invoke
         * keventd to go get it */
        rxkad_ci = crypto_alloc_skcipher("pcbc(fcrypt)", 0, CRYPTO_ALG_ASYNC);
-       if (IS_ERR(rxkad_ci))
-               return PTR_ERR(rxkad_ci);
-       return 0;
+       return PTR_ERR_OR_ZERO(rxkad_ci);
 }
 
 /*
index 330f14e..c557789 100644 (file)
@@ -38,7 +38,7 @@ struct tcf_police {
        bool                    peak_present;
 };
 #define to_police(pc)  \
-       container_of(pc, struct tcf_police, common)
+       container_of(pc->priv, struct tcf_police, common)
 
 #define POL_TAB_MASK     15
 
@@ -119,14 +119,12 @@ static int tcf_act_police_locate(struct net *net, struct nlattr *nla,
                                 struct nlattr *est, struct tc_action *a,
                                 int ovr, int bind)
 {
-       unsigned int h;
        int ret = 0, err;
        struct nlattr *tb[TCA_POLICE_MAX + 1];
        struct tc_police *parm;
        struct tcf_police *police;
        struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL;
        struct tc_action_net *tn = net_generic(net, police_net_id);
-       struct tcf_hashinfo *hinfo = tn->hinfo;
        int size;
 
        if (nla == NULL)
@@ -145,7 +143,7 @@ static int tcf_act_police_locate(struct net *net, struct nlattr *nla,
 
        if (parm->index) {
                if (tcf_hash_search(tn, a, parm->index)) {
-                       police = to_police(a->priv);
+                       police = to_police(a);
                        if (bind) {
                                police->tcf_bindcnt += 1;
                                police->tcf_refcnt += 1;
@@ -156,16 +154,15 @@ static int tcf_act_police_locate(struct net *net, struct nlattr *nla,
                        /* not replacing */
                        return -EEXIST;
                }
+       } else {
+               ret = tcf_hash_create(tn, parm->index, NULL, a,
+                                     sizeof(*police), bind, false);
+               if (ret)
+                       return ret;
+               ret = ACT_P_CREATED;
        }
 
-       police = kzalloc(sizeof(*police), GFP_KERNEL);
-       if (police == NULL)
-               return -ENOMEM;
-       ret = ACT_P_CREATED;
-       police->tcf_refcnt = 1;
-       spin_lock_init(&police->tcf_lock);
-       if (bind)
-               police->tcf_bindcnt = 1;
+       police = to_police(a);
 override:
        if (parm->rate.rate) {
                err = -ENOMEM;
@@ -237,14 +234,8 @@ override:
                return ret;
 
        police->tcfp_t_c = ktime_get_ns();
-       police->tcf_index = parm->index ? parm->index :
-               tcf_hash_new_index(tn);
-       h = tcf_hash(police->tcf_index, POL_TAB_MASK);
-       spin_lock_bh(&hinfo->lock);
-       hlist_add_head(&police->tcf_head, &hinfo->htab[h]);
-       spin_unlock_bh(&hinfo->lock);
+       tcf_hash_insert(tn, a);
 
-       a->priv = police;
        return ret;
 
 failure_unlock:
@@ -253,7 +244,7 @@ failure:
        qdisc_put_rtab(P_tab);
        qdisc_put_rtab(R_tab);
        if (ret == ACT_P_CREATED)
-               kfree(police);
+               tcf_hash_cleanup(a, est);
        return err;
 }
 
@@ -268,6 +259,7 @@ static int tcf_act_police(struct sk_buff *skb, const struct tc_action *a,
        spin_lock(&police->tcf_lock);
 
        bstats_update(&police->tcf_bstats, skb);
+       tcf_lastuse_update(&police->tcf_tm);
 
        if (police->tcfp_ewma_rate &&
            police->tcf_rate_est.bps >= police->tcfp_ewma_rate) {
@@ -327,6 +319,7 @@ tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
                .refcnt = police->tcf_refcnt - ref,
                .bindcnt = police->tcf_bindcnt - bind,
        };
+       struct tcf_t t;
 
        if (police->rate_present)
                psched_ratecfg_getrate(&opt.rate, &police->rate);
@@ -340,6 +333,13 @@ tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
        if (police->tcfp_ewma_rate &&
            nla_put_u32(skb, TCA_POLICE_AVRATE, police->tcfp_ewma_rate))
                goto nla_put_failure;
+
+       t.install = jiffies_to_clock_t(jiffies - police->tcf_tm.install);
+       t.lastuse = jiffies_to_clock_t(jiffies - police->tcf_tm.lastuse);
+       t.expires = jiffies_to_clock_t(police->tcf_tm.expires);
+       if (nla_put_64bit(skb, TCA_POLICE_TM, sizeof(t), &t, TCA_POLICE_PAD))
+               goto nla_put_failure;
+
        return skb->len;
 
 nla_put_failure:
index 730aaca..b3b7978 100644 (file)
@@ -171,7 +171,7 @@ static void fl_hw_destroy_filter(struct tcf_proto *tp, unsigned long cookie)
        struct tc_cls_flower_offload offload = {0};
        struct tc_to_netdev tc;
 
-       if (!tc_should_offload(dev, 0))
+       if (!tc_should_offload(dev, tp, 0))
                return;
 
        offload.command = TC_CLSFLOWER_DESTROY;
@@ -194,7 +194,7 @@ static void fl_hw_replace_filter(struct tcf_proto *tp,
        struct tc_cls_flower_offload offload = {0};
        struct tc_to_netdev tc;
 
-       if (!tc_should_offload(dev, flags))
+       if (!tc_should_offload(dev, tp, flags))
                return;
 
        offload.command = TC_CLSFLOWER_REPLACE;
@@ -216,7 +216,7 @@ static void fl_hw_update_stats(struct tcf_proto *tp, struct cls_fl_filter *f)
        struct tc_cls_flower_offload offload = {0};
        struct tc_to_netdev tc;
 
-       if (!tc_should_offload(dev, 0))
+       if (!tc_should_offload(dev, tp, 0))
                return;
 
        offload.command = TC_CLSFLOWER_STATS;
index 079b43b..ffe593e 100644 (file)
@@ -440,7 +440,7 @@ static void u32_remove_hw_knode(struct tcf_proto *tp, u32 handle)
        offload.type = TC_SETUP_CLSU32;
        offload.cls_u32 = &u32_offload;
 
-       if (tc_should_offload(dev, 0)) {
+       if (tc_should_offload(dev, tp, 0)) {
                offload.cls_u32->command = TC_CLSU32_DELETE_KNODE;
                offload.cls_u32->knode.handle = handle;
                dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle,
@@ -457,20 +457,21 @@ static int u32_replace_hw_hnode(struct tcf_proto *tp,
        struct tc_to_netdev offload;
        int err;
 
+       if (!tc_should_offload(dev, tp, flags))
+               return tc_skip_sw(flags) ? -EINVAL : 0;
+
        offload.type = TC_SETUP_CLSU32;
        offload.cls_u32 = &u32_offload;
 
-       if (tc_should_offload(dev, flags)) {
-               offload.cls_u32->command = TC_CLSU32_NEW_HNODE;
-               offload.cls_u32->hnode.divisor = h->divisor;
-               offload.cls_u32->hnode.handle = h->handle;
-               offload.cls_u32->hnode.prio = h->prio;
+       offload.cls_u32->command = TC_CLSU32_NEW_HNODE;
+       offload.cls_u32->hnode.divisor = h->divisor;
+       offload.cls_u32->hnode.handle = h->handle;
+       offload.cls_u32->hnode.prio = h->prio;
 
-               err = dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle,
-                                                   tp->protocol, &offload);
-               if (tc_skip_sw(flags))
-                       return err;
-       }
+       err = dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle,
+                                           tp->protocol, &offload);
+       if (tc_skip_sw(flags))
+               return err;
 
        return 0;
 }
@@ -484,7 +485,7 @@ static void u32_clear_hw_hnode(struct tcf_proto *tp, struct tc_u_hnode *h)
        offload.type = TC_SETUP_CLSU32;
        offload.cls_u32 = &u32_offload;
 
-       if (tc_should_offload(dev, 0)) {
+       if (tc_should_offload(dev, tp, 0)) {
                offload.cls_u32->command = TC_CLSU32_DELETE_HNODE;
                offload.cls_u32->hnode.divisor = h->divisor;
                offload.cls_u32->hnode.handle = h->handle;
@@ -507,27 +508,28 @@ static int u32_replace_hw_knode(struct tcf_proto *tp,
        offload.type = TC_SETUP_CLSU32;
        offload.cls_u32 = &u32_offload;
 
-       if (tc_should_offload(dev, flags)) {
-               offload.cls_u32->command = TC_CLSU32_REPLACE_KNODE;
-               offload.cls_u32->knode.handle = n->handle;
-               offload.cls_u32->knode.fshift = n->fshift;
+       if (!tc_should_offload(dev, tp, flags))
+               return tc_skip_sw(flags) ? -EINVAL : 0;
+
+       offload.cls_u32->command = TC_CLSU32_REPLACE_KNODE;
+       offload.cls_u32->knode.handle = n->handle;
+       offload.cls_u32->knode.fshift = n->fshift;
 #ifdef CONFIG_CLS_U32_MARK
-               offload.cls_u32->knode.val = n->val;
-               offload.cls_u32->knode.mask = n->mask;
+       offload.cls_u32->knode.val = n->val;
+       offload.cls_u32->knode.mask = n->mask;
 #else
-               offload.cls_u32->knode.val = 0;
-               offload.cls_u32->knode.mask = 0;
+       offload.cls_u32->knode.val = 0;
+       offload.cls_u32->knode.mask = 0;
 #endif
-               offload.cls_u32->knode.sel = &n->sel;
-               offload.cls_u32->knode.exts = &n->exts;
-               if (n->ht_down)
-                       offload.cls_u32->knode.link_handle = n->ht_down->handle;
-
-               err = dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle,
-                                                   tp->protocol, &offload);
-               if (tc_skip_sw(flags))
-                       return err;
-       }
+       offload.cls_u32->knode.sel = &n->sel;
+       offload.cls_u32->knode.exts = &n->exts;
+       if (n->ht_down)
+               offload.cls_u32->knode.link_handle = n->ht_down->handle;
+
+       err = dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle,
+                                           tp->protocol, &offload);
+       if (tc_skip_sw(flags))
+               return err;
 
        return 0;
 }
@@ -863,7 +865,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
        if (tb[TCA_U32_FLAGS]) {
                flags = nla_get_u32(tb[TCA_U32_FLAGS]);
                if (!tc_flags_valid(flags))
-                       return err;
+                       return -EINVAL;
        }
 
        n = (struct tc_u_knode *)*arg;
@@ -921,11 +923,17 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
                ht->divisor = divisor;
                ht->handle = handle;
                ht->prio = tp->prio;
+
+               err = u32_replace_hw_hnode(tp, ht, flags);
+               if (err) {
+                       kfree(ht);
+                       return err;
+               }
+
                RCU_INIT_POINTER(ht->next, tp_c->hlist);
                rcu_assign_pointer(tp_c->hlist, ht);
                *arg = (unsigned long)ht;
 
-               u32_replace_hw_hnode(tp, ht, flags);
                return 0;
        }
 
index 64f71a2..ddf047d 100644 (file)
@@ -607,6 +607,10 @@ void qdisc_watchdog_schedule_ns(struct qdisc_watchdog *wd, u64 expires, bool thr
        if (throttle)
                qdisc_throttled(wd->qdisc);
 
+       if (wd->last_expires == expires)
+               return;
+
+       wd->last_expires = expires;
        hrtimer_start(&wd->timer,
                      ns_to_ktime(expires),
                      HRTIMER_MODE_ABS_PINNED);
index a63e879..bf8af2c 100644 (file)
@@ -375,6 +375,7 @@ static int drr_enqueue(struct sk_buff *skb, struct Qdisc *sch)
                cl->deficit = cl->quantum;
        }
 
+       qdisc_qstats_backlog_inc(sch, skb);
        sch->q.qlen++;
        return err;
 }
@@ -407,6 +408,7 @@ static struct sk_buff *drr_dequeue(struct Qdisc *sch)
 
                        bstats_update(&cl->bstats, skb);
                        qdisc_bstats_update(sch, skb);
+                       qdisc_qstats_backlog_dec(sch, skb);
                        sch->q.qlen--;
                        return skb;
                }
@@ -428,6 +430,7 @@ static unsigned int drr_drop(struct Qdisc *sch)
                if (cl->qdisc->ops->drop) {
                        len = cl->qdisc->ops->drop(cl->qdisc);
                        if (len > 0) {
+                               sch->qstats.backlog -= len;
                                sch->q.qlen--;
                                if (cl->qdisc->q.qlen == 0)
                                        list_del(&cl->alist);
@@ -463,6 +466,7 @@ static void drr_reset_qdisc(struct Qdisc *sch)
                        qdisc_reset(cl->qdisc);
                }
        }
+       sch->qstats.backlog = 0;
        sch->q.qlen = 0;
 }
 
index 6883a89..da250b2 100644 (file)
@@ -199,6 +199,7 @@ static int fq_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        unsigned int idx, prev_backlog, prev_qlen;
        struct fq_codel_flow *flow;
        int uninitialized_var(ret);
+       unsigned int pkt_len;
        bool memory_limited;
 
        idx = fq_codel_classify(skb, sch, &ret);
@@ -230,6 +231,8 @@ static int fq_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        prev_backlog = sch->qstats.backlog;
        prev_qlen = sch->q.qlen;
 
+       /* save this packet length as it might be dropped by fq_codel_drop() */
+       pkt_len = qdisc_pkt_len(skb);
        /* fq_codel_drop() is quite expensive, as it performs a linear search
         * in q->backlogs[] to find a fat flow.
         * So instead of dropping a single packet, drop half of its backlog
@@ -237,14 +240,23 @@ static int fq_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch)
         */
        ret = fq_codel_drop(sch, q->drop_batch_size);
 
-       q->drop_overlimit += prev_qlen - sch->q.qlen;
+       prev_qlen -= sch->q.qlen;
+       prev_backlog -= sch->qstats.backlog;
+       q->drop_overlimit += prev_qlen;
        if (memory_limited)
-               q->drop_overmemory += prev_qlen - sch->q.qlen;
-       /* As we dropped packet(s), better let upper stack know this */
-       qdisc_tree_reduce_backlog(sch, prev_qlen - sch->q.qlen,
-                                 prev_backlog - sch->qstats.backlog);
+               q->drop_overmemory += prev_qlen;
 
-       return ret == idx ? NET_XMIT_CN : NET_XMIT_SUCCESS;
+       /* As we dropped packet(s), better let upper stack know this.
+        * If we dropped a packet for this flow, return NET_XMIT_CN,
+        * but in this case, our parents wont increase their backlogs.
+        */
+       if (ret == idx) {
+               qdisc_tree_reduce_backlog(sch, prev_qlen - 1,
+                                         prev_backlog - pkt_len);
+               return NET_XMIT_CN;
+       }
+       qdisc_tree_reduce_backlog(sch, prev_qlen, prev_backlog);
+       return NET_XMIT_SUCCESS;
 }
 
 /* This is the specific function called from codel_dequeue()
@@ -649,7 +661,7 @@ static int fq_codel_dump_class_stats(struct Qdisc *sch, unsigned long cl,
                qs.backlog = q->backlogs[idx];
                qs.drops = flow->dropped;
        }
-       if (gnet_stats_copy_queue(d, NULL, &qs, 0) < 0)
+       if (gnet_stats_copy_queue(d, NULL, &qs, qs.qlen) < 0)
                return -1;
        if (idx < q->flows_cnt)
                return gnet_stats_copy_app(d, &xstats, sizeof(xstats));
index 269dd71..f9e0e9c 100644 (file)
@@ -49,6 +49,7 @@ static inline int dev_requeue_skb(struct sk_buff *skb, struct Qdisc *q)
 {
        q->gso_skb = skb;
        q->qstats.requeues++;
+       qdisc_qstats_backlog_inc(q, skb);
        q->q.qlen++;    /* it's still part of the queue */
        __netif_schedule(q);
 
@@ -92,6 +93,7 @@ static struct sk_buff *dequeue_skb(struct Qdisc *q, bool *validate,
                txq = skb_get_tx_queue(txq->dev, skb);
                if (!netif_xmit_frozen_or_stopped(txq)) {
                        q->gso_skb = NULL;
+                       qdisc_qstats_backlog_dec(q, skb);
                        q->q.qlen--;
                } else
                        skb = NULL;
index d783d7c..1ac9f9f 100644 (file)
@@ -1529,6 +1529,7 @@ hfsc_reset_qdisc(struct Qdisc *sch)
        q->eligible = RB_ROOT;
        INIT_LIST_HEAD(&q->droplist);
        qdisc_watchdog_cancel(&q->watchdog);
+       sch->qstats.backlog = 0;
        sch->q.qlen = 0;
 }
 
@@ -1559,14 +1560,6 @@ hfsc_dump_qdisc(struct Qdisc *sch, struct sk_buff *skb)
        struct hfsc_sched *q = qdisc_priv(sch);
        unsigned char *b = skb_tail_pointer(skb);
        struct tc_hfsc_qopt qopt;
-       struct hfsc_class *cl;
-       unsigned int i;
-
-       sch->qstats.backlog = 0;
-       for (i = 0; i < q->clhash.hashsize; i++) {
-               hlist_for_each_entry(cl, &q->clhash.hash[i], cl_common.hnode)
-                       sch->qstats.backlog += cl->qdisc->qstats.backlog;
-       }
 
        qopt.defcls = q->defcls;
        if (nla_put(skb, TCA_OPTIONS, sizeof(qopt), &qopt))
@@ -1604,6 +1597,7 @@ hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        if (cl->qdisc->q.qlen == 1)
                set_active(cl, qdisc_pkt_len(skb));
 
+       qdisc_qstats_backlog_inc(sch, skb);
        sch->q.qlen++;
 
        return NET_XMIT_SUCCESS;
@@ -1672,6 +1666,7 @@ hfsc_dequeue(struct Qdisc *sch)
 
        qdisc_unthrottled(sch);
        qdisc_bstats_update(sch, skb);
+       qdisc_qstats_backlog_dec(sch, skb);
        sch->q.qlen--;
 
        return skb;
@@ -1695,6 +1690,7 @@ hfsc_drop(struct Qdisc *sch)
                        }
                        cl->qstats.drops++;
                        qdisc_qstats_drop(sch);
+                       sch->qstats.backlog -= len;
                        sch->q.qlen--;
                        return len;
                }
index f6bf581..d4b4218 100644 (file)
@@ -928,17 +928,10 @@ ok:
                }
        }
        qdisc_qstats_overlimit(sch);
-       if (likely(next_event > q->now)) {
-               if (!test_bit(__QDISC_STATE_DEACTIVATED,
-                             &qdisc_root_sleeping(q->watchdog.qdisc)->state)) {
-                       ktime_t time = ns_to_ktime(next_event);
-                       qdisc_throttled(q->watchdog.qdisc);
-                       hrtimer_start(&q->watchdog.timer, time,
-                                     HRTIMER_MODE_ABS_PINNED);
-               }
-       } else {
+       if (likely(next_event > q->now))
+               qdisc_watchdog_schedule_ns(&q->watchdog, next_event, true);
+       else
                schedule_work(&q->work);
-       }
 fin:
        return skb;
 }
index 10adbc6..8fe6999 100644 (file)
@@ -27,6 +27,11 @@ static unsigned long ingress_get(struct Qdisc *sch, u32 classid)
        return TC_H_MIN(classid) + 1;
 }
 
+static bool ingress_cl_offload(u32 classid)
+{
+       return true;
+}
+
 static unsigned long ingress_bind_filter(struct Qdisc *sch,
                                         unsigned long parent, u32 classid)
 {
@@ -86,6 +91,7 @@ static const struct Qdisc_class_ops ingress_class_ops = {
        .put            =       ingress_put,
        .walk           =       ingress_walk,
        .tcf_chain      =       ingress_find_tcf,
+       .tcf_cl_offload =       ingress_cl_offload,
        .bind_tcf       =       ingress_bind_filter,
        .unbind_tcf     =       ingress_put,
 };
@@ -110,6 +116,11 @@ static unsigned long clsact_get(struct Qdisc *sch, u32 classid)
        }
 }
 
+static bool clsact_cl_offload(u32 classid)
+{
+       return TC_H_MIN(classid) == TC_H_MIN(TC_H_MIN_INGRESS);
+}
+
 static unsigned long clsact_bind_filter(struct Qdisc *sch,
                                        unsigned long parent, u32 classid)
 {
@@ -158,6 +169,7 @@ static const struct Qdisc_class_ops clsact_class_ops = {
        .put            =       ingress_put,
        .walk           =       ingress_walk,
        .tcf_chain      =       clsact_find_tcf,
+       .tcf_cl_offload =       clsact_cl_offload,
        .bind_tcf       =       clsact_bind_filter,
        .unbind_tcf     =       ingress_put,
 };
index fee1b15..4b0a821 100644 (file)
@@ -85,6 +85,7 @@ prio_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 
        ret = qdisc_enqueue(skb, qdisc);
        if (ret == NET_XMIT_SUCCESS) {
+               qdisc_qstats_backlog_inc(sch, skb);
                sch->q.qlen++;
                return NET_XMIT_SUCCESS;
        }
@@ -117,6 +118,7 @@ static struct sk_buff *prio_dequeue(struct Qdisc *sch)
                struct sk_buff *skb = qdisc_dequeue_peeked(qdisc);
                if (skb) {
                        qdisc_bstats_update(sch, skb);
+                       qdisc_qstats_backlog_dec(sch, skb);
                        sch->q.qlen--;
                        return skb;
                }
@@ -135,6 +137,7 @@ static unsigned int prio_drop(struct Qdisc *sch)
        for (prio = q->bands-1; prio >= 0; prio--) {
                qdisc = q->queues[prio];
                if (qdisc->ops->drop && (len = qdisc->ops->drop(qdisc)) != 0) {
+                       sch->qstats.backlog -= len;
                        sch->q.qlen--;
                        return len;
                }
@@ -151,6 +154,7 @@ prio_reset(struct Qdisc *sch)
 
        for (prio = 0; prio < q->bands; prio++)
                qdisc_reset(q->queues[prio]);
+       sch->qstats.backlog = 0;
        sch->q.qlen = 0;
 }
 
index 8d2d8d9..f18857f 100644 (file)
@@ -1235,8 +1235,10 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
                         cl->agg->lmax, qdisc_pkt_len(skb), cl->common.classid);
                err = qfq_change_agg(sch, cl, cl->agg->class_weight,
                                     qdisc_pkt_len(skb));
-               if (err)
-                       return err;
+               if (err) {
+                       cl->qstats.drops++;
+                       return qdisc_drop(skb, sch);
+               }
        }
 
        err = qdisc_enqueue(skb, cl->qdisc);
index 8c0508c..91578bd 100644 (file)
@@ -97,6 +97,7 @@ static int red_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 
        ret = qdisc_enqueue(skb, child);
        if (likely(ret == NET_XMIT_SUCCESS)) {
+               qdisc_qstats_backlog_inc(sch, skb);
                sch->q.qlen++;
        } else if (net_xmit_drop_count(ret)) {
                q->stats.pdrop++;
@@ -118,6 +119,7 @@ static struct sk_buff *red_dequeue(struct Qdisc *sch)
        skb = child->dequeue(child);
        if (skb) {
                qdisc_bstats_update(sch, skb);
+               qdisc_qstats_backlog_dec(sch, skb);
                sch->q.qlen--;
        } else {
                if (!red_is_idling(&q->vars))
@@ -143,6 +145,7 @@ static unsigned int red_drop(struct Qdisc *sch)
        if (child->ops->drop && (len = child->ops->drop(child)) > 0) {
                q->stats.other++;
                qdisc_qstats_drop(sch);
+               sch->qstats.backlog -= len;
                sch->q.qlen--;
                return len;
        }
@@ -158,6 +161,7 @@ static void red_reset(struct Qdisc *sch)
        struct red_sched_data *q = qdisc_priv(sch);
 
        qdisc_reset(q->qdisc);
+       sch->qstats.backlog = 0;
        sch->q.qlen = 0;
        red_restart(&q->vars);
 }
index 83b90b5..3161e49 100644 (file)
@@ -207,6 +207,7 @@ static int tbf_enqueue(struct sk_buff *skb, struct Qdisc *sch)
                return ret;
        }
 
+       qdisc_qstats_backlog_inc(sch, skb);
        sch->q.qlen++;
        return NET_XMIT_SUCCESS;
 }
@@ -217,6 +218,7 @@ static unsigned int tbf_drop(struct Qdisc *sch)
        unsigned int len = 0;
 
        if (q->qdisc->ops->drop && (len = q->qdisc->ops->drop(q->qdisc)) != 0) {
+               sch->qstats.backlog -= len;
                sch->q.qlen--;
                qdisc_qstats_drop(sch);
        }
@@ -263,6 +265,7 @@ static struct sk_buff *tbf_dequeue(struct Qdisc *sch)
                        q->t_c = now;
                        q->tokens = toks;
                        q->ptokens = ptoks;
+                       qdisc_qstats_backlog_dec(sch, skb);
                        sch->q.qlen--;
                        qdisc_unthrottled(sch);
                        qdisc_bstats_update(sch, skb);
@@ -294,6 +297,7 @@ static void tbf_reset(struct Qdisc *sch)
        struct tbf_sched_data *q = qdisc_priv(sch);
 
        qdisc_reset(q->qdisc);
+       sch->qstats.backlog = 0;
        sch->q.qlen = 0;
        q->t_c = ktime_get_ns();
        q->tokens = q->buffer;
index 8e3e769..1ce724b 100644 (file)
@@ -356,6 +356,9 @@ static int sctp_ep_dump(struct sctp_endpoint *ep, void *p)
        if (cb->args[4] < cb->args[1])
                goto next;
 
+       if ((r->idiag_states & ~TCPF_LISTEN) && !list_empty(&ep->asocs))
+               goto next;
+
        if (r->sdiag_family != AF_UNSPEC &&
            sk->sk_family != r->sdiag_family)
                goto next;
index 777d032..67154b8 100644 (file)
@@ -4220,6 +4220,7 @@ int sctp_get_sctp_info(struct sock *sk, struct sctp_association *asoc,
                info->sctpi_s_disable_fragments = sp->disable_fragments;
                info->sctpi_s_v4mapped = sp->v4mapped;
                info->sctpi_s_frag_interleave = sp->frag_interleave;
+               info->sctpi_s_type = sp->type;
 
                return 0;
        }
index 06b4df9..2808d55 100644 (file)
@@ -446,16 +446,27 @@ out_no_rpciod:
        return ERR_PTR(err);
 }
 
-struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args,
+static struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args,
                                        struct rpc_xprt *xprt)
 {
        struct rpc_clnt *clnt = NULL;
        struct rpc_xprt_switch *xps;
 
-       xps = xprt_switch_alloc(xprt, GFP_KERNEL);
-       if (xps == NULL)
-               return ERR_PTR(-ENOMEM);
-
+       if (args->bc_xprt && args->bc_xprt->xpt_bc_xps) {
+               WARN_ON(args->protocol != XPRT_TRANSPORT_BC_TCP);
+               xps = args->bc_xprt->xpt_bc_xps;
+               xprt_switch_get(xps);
+       } else {
+               xps = xprt_switch_alloc(xprt, GFP_KERNEL);
+               if (xps == NULL) {
+                       xprt_put(xprt);
+                       return ERR_PTR(-ENOMEM);
+               }
+               if (xprt->bc_xprt) {
+                       xprt_switch_get(xps);
+                       xprt->bc_xprt->xpt_bc_xps = xps;
+               }
+       }
        clnt = rpc_new_client(args, xps, xprt, NULL);
        if (IS_ERR(clnt))
                return clnt;
@@ -483,7 +494,6 @@ struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args,
 
        return clnt;
 }
-EXPORT_SYMBOL_GPL(rpc_create_xprt);
 
 /**
  * rpc_create - create an RPC client and transport with one call
@@ -509,6 +519,15 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
        };
        char servername[48];
 
+       if (args->bc_xprt) {
+               WARN_ON(args->protocol != XPRT_TRANSPORT_BC_TCP);
+               xprt = args->bc_xprt->xpt_bc_xprt;
+               if (xprt) {
+                       xprt_get(xprt);
+                       return rpc_create_xprt(args, xprt);
+               }
+       }
+
        if (args->flags & RPC_CLNT_CREATE_INFINITE_SLOTS)
                xprtargs.flags |= XPRT_CREATE_INFINITE_SLOTS;
        if (args->flags & RPC_CLNT_CREATE_NO_IDLE_TIMEOUT)
index f5572e3..4f01f63 100644 (file)
@@ -136,6 +136,8 @@ static void svc_xprt_free(struct kref *kref)
        /* See comment on corresponding get in xs_setup_bc_tcp(): */
        if (xprt->xpt_bc_xprt)
                xprt_put(xprt->xpt_bc_xprt);
+       if (xprt->xpt_bc_xps)
+               xprt_switch_put(xprt->xpt_bc_xps);
        xprt->xpt_ops->xpo_free(xprt);
        module_put(owner);
 }
index 2d3e0c4..7e2b2fa 100644 (file)
@@ -3057,6 +3057,7 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args)
                return xprt;
 
        args->bc_xprt->xpt_bc_xprt = NULL;
+       args->bc_xprt->xpt_bc_xps = NULL;
        xprt_put(xprt);
        ret = ERR_PTR(-EINVAL);
 out_err:
index 4dfc5c1..3ad9fab 100644 (file)
@@ -346,9 +346,15 @@ static int tipc_nl_compat_bearer_dump(struct tipc_nl_compat_msg *msg,
                                      struct nlattr **attrs)
 {
        struct nlattr *bearer[TIPC_NLA_BEARER_MAX + 1];
+       int err;
+
+       if (!attrs[TIPC_NLA_BEARER])
+               return -EINVAL;
 
-       nla_parse_nested(bearer, TIPC_NLA_BEARER_MAX, attrs[TIPC_NLA_BEARER],
-                        NULL);
+       err = nla_parse_nested(bearer, TIPC_NLA_BEARER_MAX,
+                              attrs[TIPC_NLA_BEARER], NULL);
+       if (err)
+               return err;
 
        return tipc_add_tlv(msg->rep, TIPC_TLV_BEARER_NAME,
                            nla_data(bearer[TIPC_NLA_BEARER_NAME]),
@@ -460,14 +466,31 @@ static int tipc_nl_compat_link_stat_dump(struct tipc_nl_compat_msg *msg,
        struct nlattr *link[TIPC_NLA_LINK_MAX + 1];
        struct nlattr *prop[TIPC_NLA_PROP_MAX + 1];
        struct nlattr *stats[TIPC_NLA_STATS_MAX + 1];
+       int err;
 
-       nla_parse_nested(link, TIPC_NLA_LINK_MAX, attrs[TIPC_NLA_LINK], NULL);
+       if (!attrs[TIPC_NLA_LINK])
+               return -EINVAL;
 
-       nla_parse_nested(prop, TIPC_NLA_PROP_MAX, link[TIPC_NLA_LINK_PROP],
-                        NULL);
+       err = nla_parse_nested(link, TIPC_NLA_LINK_MAX, attrs[TIPC_NLA_LINK],
+                              NULL);
+       if (err)
+               return err;
+
+       if (!link[TIPC_NLA_LINK_PROP])
+               return -EINVAL;
 
-       nla_parse_nested(stats, TIPC_NLA_STATS_MAX, link[TIPC_NLA_LINK_STATS],
-                        NULL);
+       err = nla_parse_nested(prop, TIPC_NLA_PROP_MAX,
+                              link[TIPC_NLA_LINK_PROP], NULL);
+       if (err)
+               return err;
+
+       if (!link[TIPC_NLA_LINK_STATS])
+               return -EINVAL;
+
+       err = nla_parse_nested(stats, TIPC_NLA_STATS_MAX,
+                              link[TIPC_NLA_LINK_STATS], NULL);
+       if (err)
+               return err;
 
        name = (char *)TLV_DATA(msg->req);
        if (strcmp(name, nla_data(link[TIPC_NLA_LINK_NAME])) != 0)
@@ -569,12 +592,20 @@ static int tipc_nl_compat_link_dump(struct tipc_nl_compat_msg *msg,
 {
        struct nlattr *link[TIPC_NLA_LINK_MAX + 1];
        struct tipc_link_info link_info;
+       int err;
 
-       nla_parse_nested(link, TIPC_NLA_LINK_MAX, attrs[TIPC_NLA_LINK], NULL);
+       if (!attrs[TIPC_NLA_LINK])
+               return -EINVAL;
+
+       err = nla_parse_nested(link, TIPC_NLA_LINK_MAX, attrs[TIPC_NLA_LINK],
+                              NULL);
+       if (err)
+               return err;
 
        link_info.dest = nla_get_flag(link[TIPC_NLA_LINK_DEST]);
        link_info.up = htonl(nla_get_flag(link[TIPC_NLA_LINK_UP]));
-       strcpy(link_info.str, nla_data(link[TIPC_NLA_LINK_NAME]));
+       nla_strlcpy(link_info.str, nla_data(link[TIPC_NLA_LINK_NAME]),
+                   TIPC_MAX_LINK_NAME);
 
        return tipc_add_tlv(msg->rep, TIPC_TLV_LINK_INFO,
                            &link_info, sizeof(link_info));
@@ -758,12 +789,23 @@ static int tipc_nl_compat_name_table_dump(struct tipc_nl_compat_msg *msg,
        u32 node, depth, type, lowbound, upbound;
        static const char * const scope_str[] = {"", " zone", " cluster",
                                                 " node"};
+       int err;
 
-       nla_parse_nested(nt, TIPC_NLA_NAME_TABLE_MAX,
-                        attrs[TIPC_NLA_NAME_TABLE], NULL);
+       if (!attrs[TIPC_NLA_NAME_TABLE])
+               return -EINVAL;
 
-       nla_parse_nested(publ, TIPC_NLA_PUBL_MAX, nt[TIPC_NLA_NAME_TABLE_PUBL],
-                        NULL);
+       err = nla_parse_nested(nt, TIPC_NLA_NAME_TABLE_MAX,
+                              attrs[TIPC_NLA_NAME_TABLE], NULL);
+       if (err)
+               return err;
+
+       if (!nt[TIPC_NLA_NAME_TABLE_PUBL])
+               return -EINVAL;
+
+       err = nla_parse_nested(publ, TIPC_NLA_PUBL_MAX,
+                              nt[TIPC_NLA_NAME_TABLE_PUBL], NULL);
+       if (err)
+               return err;
 
        ntq = (struct tipc_name_table_query *)TLV_DATA(msg->req);
 
@@ -815,8 +857,15 @@ static int __tipc_nl_compat_publ_dump(struct tipc_nl_compat_msg *msg,
 {
        u32 type, lower, upper;
        struct nlattr *publ[TIPC_NLA_PUBL_MAX + 1];
+       int err;
 
-       nla_parse_nested(publ, TIPC_NLA_PUBL_MAX, attrs[TIPC_NLA_PUBL], NULL);
+       if (!attrs[TIPC_NLA_PUBL])
+               return -EINVAL;
+
+       err = nla_parse_nested(publ, TIPC_NLA_PUBL_MAX, attrs[TIPC_NLA_PUBL],
+                              NULL);
+       if (err)
+               return err;
 
        type = nla_get_u32(publ[TIPC_NLA_PUBL_TYPE]);
        lower = nla_get_u32(publ[TIPC_NLA_PUBL_LOWER]);
@@ -876,7 +925,13 @@ static int tipc_nl_compat_sk_dump(struct tipc_nl_compat_msg *msg,
        u32 sock_ref;
        struct nlattr *sock[TIPC_NLA_SOCK_MAX + 1];
 
-       nla_parse_nested(sock, TIPC_NLA_SOCK_MAX, attrs[TIPC_NLA_SOCK], NULL);
+       if (!attrs[TIPC_NLA_SOCK])
+               return -EINVAL;
+
+       err = nla_parse_nested(sock, TIPC_NLA_SOCK_MAX, attrs[TIPC_NLA_SOCK],
+                              NULL);
+       if (err)
+               return err;
 
        sock_ref = nla_get_u32(sock[TIPC_NLA_SOCK_REF]);
        tipc_tlv_sprintf(msg->rep, "%u:", sock_ref);
@@ -917,9 +972,15 @@ static int tipc_nl_compat_media_dump(struct tipc_nl_compat_msg *msg,
                                     struct nlattr **attrs)
 {
        struct nlattr *media[TIPC_NLA_MEDIA_MAX + 1];
+       int err;
+
+       if (!attrs[TIPC_NLA_MEDIA])
+               return -EINVAL;
 
-       nla_parse_nested(media, TIPC_NLA_MEDIA_MAX, attrs[TIPC_NLA_MEDIA],
-                        NULL);
+       err = nla_parse_nested(media, TIPC_NLA_MEDIA_MAX, attrs[TIPC_NLA_MEDIA],
+                              NULL);
+       if (err)
+               return err;
 
        return tipc_add_tlv(msg->rep, TIPC_TLV_MEDIA_NAME,
                            nla_data(media[TIPC_NLA_MEDIA_NAME]),
@@ -931,8 +992,15 @@ static int tipc_nl_compat_node_dump(struct tipc_nl_compat_msg *msg,
 {
        struct tipc_node_info node_info;
        struct nlattr *node[TIPC_NLA_NODE_MAX + 1];
+       int err;
 
-       nla_parse_nested(node, TIPC_NLA_NODE_MAX, attrs[TIPC_NLA_NODE], NULL);
+       if (!attrs[TIPC_NLA_NODE])
+               return -EINVAL;
+
+       err = nla_parse_nested(node, TIPC_NLA_NODE_MAX, attrs[TIPC_NLA_NODE],
+                              NULL);
+       if (err)
+               return err;
 
        node_info.addr = htonl(nla_get_u32(node[TIPC_NLA_NODE_ADDR]));
        node_info.up = htonl(nla_get_flag(node[TIPC_NLA_NODE_UP]));
@@ -971,8 +1039,16 @@ static int tipc_nl_compat_net_dump(struct tipc_nl_compat_msg *msg,
 {
        __be32 id;
        struct nlattr *net[TIPC_NLA_NET_MAX + 1];
+       int err;
+
+       if (!attrs[TIPC_NLA_NET])
+               return -EINVAL;
+
+       err = nla_parse_nested(net, TIPC_NLA_NET_MAX, attrs[TIPC_NLA_NET],
+                              NULL);
+       if (err)
+               return err;
 
-       nla_parse_nested(net, TIPC_NLA_NET_MAX, attrs[TIPC_NLA_NET], NULL);
        id = htonl(nla_get_u32(net[TIPC_NLA_NET_ID]));
 
        return tipc_add_tlv(msg->rep, TIPC_TLV_UNSIGNED, &id, sizeof(id));
index 80aa6a3..735362c 100644 (file)
@@ -315,7 +315,7 @@ static struct sock *unix_find_socket_byinode(struct inode *i)
                    &unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]) {
                struct dentry *dentry = unix_sk(s)->path.dentry;
 
-               if (dentry && d_backing_inode(dentry) == i) {
+               if (dentry && d_real_inode(dentry) == i) {
                        sock_hold(s);
                        goto found;
                }
@@ -911,7 +911,7 @@ static struct sock *unix_find_other(struct net *net,
                err = kern_path(sunname->sun_path, LOOKUP_FOLLOW, &path);
                if (err)
                        goto fail;
-               inode = d_backing_inode(path.dentry);
+               inode = d_real_inode(path.dentry);
                err = inode_permission(inode, MAY_WRITE);
                if (err)
                        goto put_fail;
@@ -1048,7 +1048,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
                        goto out_up;
                }
                addr->hash = UNIX_HASH_SIZE;
-               hash = d_backing_inode(dentry)->i_ino & (UNIX_HASH_SIZE - 1);
+               hash = d_real_inode(dentry)->i_ino & (UNIX_HASH_SIZE - 1);
                spin_lock(&unix_table_lock);
                u->path = u_path;
                list = &unix_socket_table[hash];
index d25c82b..ecca389 100644 (file)
@@ -363,8 +363,6 @@ struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv,
        WARN_ON(ops->remain_on_channel && !ops->cancel_remain_on_channel);
        WARN_ON(ops->tdls_channel_switch && !ops->tdls_cancel_channel_switch);
        WARN_ON(ops->add_tx_ts && !ops->del_tx_ts);
-       WARN_ON(ops->set_tx_power && !ops->get_tx_power);
-       WARN_ON(ops->set_antenna && !ops->get_antenna);
 
        alloc_size = sizeof(*rdev) + sizeof_priv;
 
index 6250b1c..dbb2738 100644 (file)
@@ -958,8 +958,29 @@ static int wireless_process_ioctl(struct net *net, struct ifreq *ifr,
                        return private(dev, iwr, cmd, info, handler);
        }
        /* Old driver API : call driver ioctl handler */
-       if (dev->netdev_ops->ndo_do_ioctl)
-               return dev->netdev_ops->ndo_do_ioctl(dev, ifr, cmd);
+       if (dev->netdev_ops->ndo_do_ioctl) {
+#ifdef CONFIG_COMPAT
+               if (info->flags & IW_REQUEST_FLAG_COMPAT) {
+                       int ret = 0;
+                       struct iwreq iwr_lcl;
+                       struct compat_iw_point *iwp_compat = (void *) &iwr->u.data;
+
+                       memcpy(&iwr_lcl, iwr, sizeof(struct iwreq));
+                       iwr_lcl.u.data.pointer = compat_ptr(iwp_compat->pointer);
+                       iwr_lcl.u.data.length = iwp_compat->length;
+                       iwr_lcl.u.data.flags = iwp_compat->flags;
+
+                       ret = dev->netdev_ops->ndo_do_ioctl(dev, (void *) &iwr_lcl, cmd);
+
+                       iwp_compat->pointer = ptr_to_compat(iwr_lcl.u.data.pointer);
+                       iwp_compat->length = iwr_lcl.u.data.length;
+                       iwp_compat->flags = iwr_lcl.u.data.flags;
+
+                       return ret;
+               } else
+#endif
+                       return dev->netdev_ops->ndo_do_ioctl(dev, ifr, cmd);
+       }
        return -EOPNOTSUPP;
 }
 
index 6750595..4904ced 100755 (executable)
@@ -2454,6 +2454,7 @@ sub process {
 
 # Check for git id commit length and improperly formed commit descriptions
                if ($in_commit_log && !$commit_log_possible_stack_dump &&
+                   $line !~ /^\s*(?:Link|Patchwork|http|BugLink):/i &&
                    ($line =~ /\bcommit\s+[0-9a-f]{5,}\b/i ||
                     ($line =~ /\b[0-9a-f]{12,40}\b/i &&
                      $line !~ /[\<\[][0-9a-f]{12,40}[\>\]]/i &&
index a915507..fec7578 100644 (file)
@@ -384,7 +384,7 @@ static void do_of_entry_multi(void *symval, struct module *mod)
        len = sprintf(alias, "of:N%sT%s", (*name)[0] ? *name : "*",
                      (*type)[0] ? *type : "*");
 
-       if (compatible[0])
+       if ((*compatible)[0])
                sprintf(&alias[len], "%sC%s", (*type)[0] ? "*" : "",
                        *compatible);
 
index c8783b3..36c80bf 100644 (file)
@@ -134,7 +134,7 @@ COMPAT_SYSCALL_DEFINE5(keyctl, u32, option,
 
        case KEYCTL_DH_COMPUTE:
                return keyctl_dh_compute(compat_ptr(arg2), compat_ptr(arg3),
-                                        arg4);
+                                        arg4, compat_ptr(arg5));
 
        default:
                return -EOPNOTSUPP;
index 880505a..531ed2e 100644 (file)
@@ -78,7 +78,8 @@ error:
 }
 
 long keyctl_dh_compute(struct keyctl_dh_params __user *params,
-                      char __user *buffer, size_t buflen)
+                      char __user *buffer, size_t buflen,
+                      void __user *reserved)
 {
        long ret;
        MPI base, private, prime, result;
@@ -97,6 +98,11 @@ long keyctl_dh_compute(struct keyctl_dh_params __user *params,
                goto out;
        }
 
+       if (reserved) {
+               ret = -EINVAL;
+               goto out;
+       }
+
        keylen = mpi_from_key(pcopy.prime, buflen, &prime);
        if (keylen < 0 || !prime) {
                /* buflen == 0 may be used to query the required buffer size,
index 8ec7a52..a705a7d 100644 (file)
@@ -260,10 +260,11 @@ static inline long keyctl_get_persistent(uid_t uid, key_serial_t destring)
 
 #ifdef CONFIG_KEY_DH_OPERATIONS
 extern long keyctl_dh_compute(struct keyctl_dh_params __user *, char __user *,
-                             size_t);
+                             size_t, void __user *);
 #else
 static inline long keyctl_dh_compute(struct keyctl_dh_params __user *params,
-                                    char __user *buffer, size_t buflen)
+                                    char __user *buffer, size_t buflen,
+                                    void __user *reserved)
 {
        return -EOPNOTSUPP;
 }
index bd5a272..346fbf2 100644 (file)
@@ -597,7 +597,7 @@ int key_reject_and_link(struct key *key,
 
        mutex_unlock(&key_construction_mutex);
 
-       if (keyring)
+       if (keyring && link_ret == 0)
                __key_link_end(keyring, &key->index_key, edit);
 
        /* wake up anyone waiting for a key to be constructed */
index 3b135a0..d580ad0 100644 (file)
@@ -1688,8 +1688,8 @@ SYSCALL_DEFINE5(keyctl, int, option, unsigned long, arg2, unsigned long, arg3,
 
        case KEYCTL_DH_COMPUTE:
                return keyctl_dh_compute((struct keyctl_dh_params __user *) arg2,
-                                        (char __user *) arg3,
-                                        (size_t) arg4);
+                                        (char __user *) arg3, (size_t) arg4,
+                                        (void __user *) arg5);
 
        default:
                return -EOPNOTSUPP;
index c0f8f61..172dacd 100644 (file)
@@ -420,6 +420,7 @@ static int dummy_hrtimer_stop(struct snd_pcm_substream *substream)
 
 static inline void dummy_hrtimer_sync(struct dummy_hrtimer_pcm *dpcm)
 {
+       hrtimer_cancel(&dpcm->timer);
        tasklet_kill(&dpcm->tasklet);
 }
 
index 87041dd..47a358f 100644 (file)
@@ -444,7 +444,7 @@ int snd_hdac_regmap_write_raw(struct hdac_device *codec, unsigned int reg,
        err = reg_raw_write(codec, reg, val);
        if (err == -EAGAIN) {
                err = snd_hdac_power_up_pm(codec);
-               if (!err)
+               if (err >= 0)
                        err = reg_raw_write(codec, reg, val);
                snd_hdac_power_down_pm(codec);
        }
@@ -470,7 +470,7 @@ static int __snd_hdac_regmap_read_raw(struct hdac_device *codec,
        err = reg_raw_read(codec, reg, val, uncached);
        if (err == -EAGAIN) {
                err = snd_hdac_power_up_pm(codec);
-               if (!err)
+               if (err >= 0)
                        err = reg_raw_read(codec, reg, val, uncached);
                snd_hdac_power_down_pm(codec);
        }
index 9a0d144..94089fc 100644 (file)
@@ -365,8 +365,11 @@ enum {
 
 #define IS_SKL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa170)
 #define IS_SKL_LP(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9d70)
+#define IS_KBL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa171)
+#define IS_KBL_LP(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9d71)
 #define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98)
-#define IS_SKL_PLUS(pci) (IS_SKL(pci) || IS_SKL_LP(pci) || IS_BXT(pci))
+#define IS_SKL_PLUS(pci) (IS_SKL(pci) || IS_SKL_LP(pci) || IS_BXT(pci)) || \
+                       IS_KBL(pci) || IS_KBL_LP(pci)
 
 static char *driver_short_names[] = {
        [AZX_DRIVER_ICH] = "HDA Intel",
@@ -2181,6 +2184,12 @@ static const struct pci_device_id azx_ids[] = {
        /* Sunrise Point-LP */
        { PCI_DEVICE(0x8086, 0x9d70),
          .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE },
+       /* Kabylake */
+       { PCI_DEVICE(0x8086, 0xa171),
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE },
+       /* Kabylake-LP */
+       { PCI_DEVICE(0x8086, 0x9d71),
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE },
        /* Broxton-P(Apollolake) */
        { PCI_DEVICE(0x8086, 0x5a98),
          .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_BROXTON },
index 17fd817..0621920 100644 (file)
@@ -115,20 +115,20 @@ static int substream_free_pages(struct azx *chip,
 /*
  * Register access ops. Tegra HDA register access is DWORD only.
  */
-static void hda_tegra_writel(u32 value, u32 *addr)
+static void hda_tegra_writel(u32 value, u32 __iomem *addr)
 {
        writel(value, addr);
 }
 
-static u32 hda_tegra_readl(u32 *addr)
+static u32 hda_tegra_readl(u32 __iomem *addr)
 {
        return readl(addr);
 }
 
-static void hda_tegra_writew(u16 value, u16 *addr)
+static void hda_tegra_writew(u16 value, u16 __iomem  *addr)
 {
        unsigned int shift = ((unsigned long)(addr) & 0x3) << 3;
-       void *dword_addr = (void *)((unsigned long)(addr) & ~0x3);
+       void __iomem *dword_addr = (void __iomem *)((unsigned long)(addr) & ~0x3);
        u32 v;
 
        v = readl(dword_addr);
@@ -137,20 +137,20 @@ static void hda_tegra_writew(u16 value, u16 *addr)
        writel(v, dword_addr);
 }
 
-static u16 hda_tegra_readw(u16 *addr)
+static u16 hda_tegra_readw(u16 __iomem *addr)
 {
        unsigned int shift = ((unsigned long)(addr) & 0x3) << 3;
-       void *dword_addr = (void *)((unsigned long)(addr) & ~0x3);
+       void __iomem *dword_addr = (void __iomem *)((unsigned long)(addr) & ~0x3);
        u32 v;
 
        v = readl(dword_addr);
        return (v >> shift) & 0xffff;
 }
 
-static void hda_tegra_writeb(u8 value, u8 *addr)
+static void hda_tegra_writeb(u8 value, u8 __iomem *addr)
 {
        unsigned int shift = ((unsigned long)(addr) & 0x3) << 3;
-       void *dword_addr = (void *)((unsigned long)(addr) & ~0x3);
+       void __iomem *dword_addr = (void __iomem *)((unsigned long)(addr) & ~0x3);
        u32 v;
 
        v = readl(dword_addr);
@@ -159,10 +159,10 @@ static void hda_tegra_writeb(u8 value, u8 *addr)
        writel(v, dword_addr);
 }
 
-static u8 hda_tegra_readb(u8 *addr)
+static u8 hda_tegra_readb(u8 __iomem *addr)
 {
        unsigned int shift = ((unsigned long)(addr) & 0x3) << 3;
-       void *dword_addr = (void *)((unsigned long)(addr) & ~0x3);
+       void __iomem *dword_addr = (void __iomem *)((unsigned long)(addr) & ~0x3);
        u32 v;
 
        v = readl(dword_addr);
index d53c25e..900bfbc 100644 (file)
@@ -346,6 +346,9 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
        case 0x10ec0234:
        case 0x10ec0274:
        case 0x10ec0294:
+       case 0x10ec0700:
+       case 0x10ec0701:
+       case 0x10ec0703:
                alc_update_coef_idx(codec, 0x10, 1<<15, 0);
                break;
        case 0x10ec0662:
@@ -2655,6 +2658,7 @@ enum {
        ALC269_TYPE_ALC256,
        ALC269_TYPE_ALC225,
        ALC269_TYPE_ALC294,
+       ALC269_TYPE_ALC700,
 };
 
 /*
@@ -2686,6 +2690,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
        case ALC269_TYPE_ALC256:
        case ALC269_TYPE_ALC225:
        case ALC269_TYPE_ALC294:
+       case ALC269_TYPE_ALC700:
                ssids = alc269_ssids;
                break;
        default:
@@ -3618,13 +3623,20 @@ static void alc269_fixup_hp_line1_mic1_led(struct hda_codec *codec,
 static void alc_headset_mode_unplugged(struct hda_codec *codec)
 {
        static struct coef_fw coef0255[] = {
-               WRITE_COEF(0x1b, 0x0c0b), /* LDO and MISC control */
                WRITE_COEF(0x45, 0xd089), /* UAJ function set to menual mode */
                UPDATE_COEFEX(0x57, 0x05, 1<<14, 0), /* Direct Drive HP Amp control(Set to verb control)*/
                WRITE_COEF(0x06, 0x6104), /* Set MIC2 Vref gate with HP */
                WRITE_COEFEX(0x57, 0x03, 0x8aa6), /* Direct Drive HP Amp control */
                {}
        };
+       static struct coef_fw coef0255_1[] = {
+               WRITE_COEF(0x1b, 0x0c0b), /* LDO and MISC control */
+               {}
+       };
+       static struct coef_fw coef0256[] = {
+               WRITE_COEF(0x1b, 0x0c4b), /* LDO and MISC control */
+               {}
+       };
        static struct coef_fw coef0233[] = {
                WRITE_COEF(0x1b, 0x0c0b),
                WRITE_COEF(0x45, 0xc429),
@@ -3677,7 +3689,11 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec)
 
        switch (codec->core.vendor_id) {
        case 0x10ec0255:
+               alc_process_coef_fw(codec, coef0255_1);
+               alc_process_coef_fw(codec, coef0255);
+               break;
        case 0x10ec0256:
+               alc_process_coef_fw(codec, coef0256);
                alc_process_coef_fw(codec, coef0255);
                break;
        case 0x10ec0233:
@@ -3896,6 +3912,12 @@ static void alc_headset_mode_ctia(struct hda_codec *codec)
                WRITE_COEFEX(0x57, 0x03, 0x8ea6),
                {}
        };
+       static struct coef_fw coef0256[] = {
+               WRITE_COEF(0x45, 0xd489), /* Set to CTIA type */
+               WRITE_COEF(0x1b, 0x0c6b),
+               WRITE_COEFEX(0x57, 0x03, 0x8ea6),
+               {}
+       };
        static struct coef_fw coef0233[] = {
                WRITE_COEF(0x45, 0xd429),
                WRITE_COEF(0x1b, 0x0c2b),
@@ -3936,9 +3958,11 @@ static void alc_headset_mode_ctia(struct hda_codec *codec)
 
        switch (codec->core.vendor_id) {
        case 0x10ec0255:
-       case 0x10ec0256:
                alc_process_coef_fw(codec, coef0255);
                break;
+       case 0x10ec0256:
+               alc_process_coef_fw(codec, coef0256);
+               break;
        case 0x10ec0233:
        case 0x10ec0283:
                alc_process_coef_fw(codec, coef0233);
@@ -3978,6 +4002,12 @@ static void alc_headset_mode_omtp(struct hda_codec *codec)
                WRITE_COEFEX(0x57, 0x03, 0x8ea6),
                {}
        };
+       static struct coef_fw coef0256[] = {
+               WRITE_COEF(0x45, 0xe489), /* Set to OMTP Type */
+               WRITE_COEF(0x1b, 0x0c6b),
+               WRITE_COEFEX(0x57, 0x03, 0x8ea6),
+               {}
+       };
        static struct coef_fw coef0233[] = {
                WRITE_COEF(0x45, 0xe429),
                WRITE_COEF(0x1b, 0x0c2b),
@@ -4018,9 +4048,11 @@ static void alc_headset_mode_omtp(struct hda_codec *codec)
 
        switch (codec->core.vendor_id) {
        case 0x10ec0255:
-       case 0x10ec0256:
                alc_process_coef_fw(codec, coef0255);
                break;
+       case 0x10ec0256:
+               alc_process_coef_fw(codec, coef0256);
+               break;
        case 0x10ec0233:
        case 0x10ec0283:
                alc_process_coef_fw(codec, coef0233);
@@ -4266,7 +4298,7 @@ static void alc_fixup_headset_mode_no_hp_mic(struct hda_codec *codec,
 static void alc255_set_default_jack_type(struct hda_codec *codec)
 {
        /* Set to iphone type */
-       static struct coef_fw fw[] = {
+       static struct coef_fw alc255fw[] = {
                WRITE_COEF(0x1b, 0x880b),
                WRITE_COEF(0x45, 0xd089),
                WRITE_COEF(0x1b, 0x080b),
@@ -4274,7 +4306,22 @@ static void alc255_set_default_jack_type(struct hda_codec *codec)
                WRITE_COEF(0x1b, 0x0c0b),
                {}
        };
-       alc_process_coef_fw(codec, fw);
+       static struct coef_fw alc256fw[] = {
+               WRITE_COEF(0x1b, 0x884b),
+               WRITE_COEF(0x45, 0xd089),
+               WRITE_COEF(0x1b, 0x084b),
+               WRITE_COEF(0x46, 0x0004),
+               WRITE_COEF(0x1b, 0x0c4b),
+               {}
+       };
+       switch (codec->core.vendor_id) {
+       case 0x10ec0255:
+               alc_process_coef_fw(codec, alc255fw);
+               break;
+       case 0x10ec0256:
+               alc_process_coef_fw(codec, alc256fw);
+               break;
+       }
        msleep(30);
 }
 
@@ -5587,6 +5634,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x2218, "Thinkpad X1 Carbon 2nd", ALC292_FIXUP_TPT440_DOCK),
        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, 0x2231, "Thinkpad T560", ALC292_FIXUP_TPT460),
        SND_PCI_QUIRK(0x17aa, 0x2233, "Thinkpad", ALC292_FIXUP_TPT460),
        SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
        SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
@@ -5602,6 +5650,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x503c, "Thinkpad L450", ALC292_FIXUP_TPT440_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x504a, "ThinkPad X260", ALC292_FIXUP_TPT440_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x504b, "Thinkpad", ALC293_FIXUP_LENOVO_SPK_NOISE),
+       SND_PCI_QUIRK(0x17aa, 0x5050, "Thinkpad T560p", ALC292_FIXUP_TPT460),
+       SND_PCI_QUIRK(0x17aa, 0x5053, "Thinkpad T460", ALC292_FIXUP_TPT460),
        SND_PCI_QUIRK(0x17aa, 0x5109, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
        SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
        SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
@@ -5775,10 +5825,18 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
                {0x12, 0x90a60180},
                {0x14, 0x90170130},
                {0x21, 0x02211040}),
+       SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell Inspiron 5565", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+               {0x12, 0x90a60180},
+               {0x14, 0x90170120},
+               {0x21, 0x02211030}),
        SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
                {0x12, 0x90a60160},
                {0x14, 0x90170120},
                {0x21, 0x02211030}),
+       SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+               {0x12, 0x90a60170},
+               {0x14, 0x90170120},
+               {0x21, 0x02211030}),
        SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
                ALC256_STANDARD_PINS),
        SND_HDA_PIN_QUIRK(0x10ec0280, 0x103c, "HP", ALC280_FIXUP_HP_GPIO4,
@@ -6053,6 +6111,14 @@ static int patch_alc269(struct hda_codec *codec)
        case 0x10ec0294:
                spec->codec_variant = ALC269_TYPE_ALC294;
                break;
+       case 0x10ec0700:
+       case 0x10ec0701:
+       case 0x10ec0703:
+               spec->codec_variant = ALC269_TYPE_ALC700;
+               spec->gen.mixer_nid = 0; /* ALC700 does not have any loopback mixer path */
+               alc_update_coef_idx(codec, 0x4a, 0, 1 << 15); /* Combo jack auto trigger control */
+               break;
+
        }
 
        if (snd_hda_codec_read(codec, 0x51, 0, AC_VERB_PARAMETERS, 0) == 0x10ec5505) {
@@ -7008,6 +7074,9 @@ static const struct hda_device_id snd_hda_id_realtek[] = {
        HDA_CODEC_ENTRY(0x10ec0670, "ALC670", patch_alc662),
        HDA_CODEC_ENTRY(0x10ec0671, "ALC671", patch_alc662),
        HDA_CODEC_ENTRY(0x10ec0680, "ALC680", patch_alc680),
+       HDA_CODEC_ENTRY(0x10ec0700, "ALC700", patch_alc269),
+       HDA_CODEC_ENTRY(0x10ec0701, "ALC701", patch_alc269),
+       HDA_CODEC_ENTRY(0x10ec0703, "ALC703", patch_alc269),
        HDA_CODEC_ENTRY(0x10ec0867, "ALC891", patch_alc882),
        HDA_CODEC_ENTRY(0x10ec0880, "ALC880", patch_alc880),
        HDA_CODEC_ENTRY(0x10ec0882, "ALC882", patch_alc882),
index bbf69d2..9f53020 100644 (file)
@@ -204,6 +204,44 @@ static unsigned long long adjust_signedness(unsigned long long value_int, int si
        return (value_int & value_mask) | ~value_mask;
 }
 
+static int string_set_value(struct bt_ctf_field *field, const char *string)
+{
+       char *buffer = NULL;
+       size_t len = strlen(string), i, p;
+       int err;
+
+       for (i = p = 0; i < len; i++, p++) {
+               if (isprint(string[i])) {
+                       if (!buffer)
+                               continue;
+                       buffer[p] = string[i];
+               } else {
+                       char numstr[5];
+
+                       snprintf(numstr, sizeof(numstr), "\\x%02x",
+                                (unsigned int)(string[i]) & 0xff);
+
+                       if (!buffer) {
+                               buffer = zalloc(i + (len - i) * 4 + 2);
+                               if (!buffer) {
+                                       pr_err("failed to set unprintable string '%s'\n", string);
+                                       return bt_ctf_field_string_set_value(field, "UNPRINTABLE-STRING");
+                               }
+                               if (i > 0)
+                                       strncpy(buffer, string, i);
+                       }
+                       strncat(buffer + p, numstr, 4);
+                       p += 3;
+               }
+       }
+
+       if (!buffer)
+               return bt_ctf_field_string_set_value(field, string);
+       err = bt_ctf_field_string_set_value(field, buffer);
+       free(buffer);
+       return err;
+}
+
 static int add_tracepoint_field_value(struct ctf_writer *cw,
                                      struct bt_ctf_event_class *event_class,
                                      struct bt_ctf_event *event,
@@ -270,8 +308,7 @@ static int add_tracepoint_field_value(struct ctf_writer *cw,
                }
 
                if (flags & FIELD_IS_STRING)
-                       ret = bt_ctf_field_string_set_value(field,
-                                       data + offset + i * len);
+                       ret = string_set_value(field, data + offset + i * len);
                else {
                        unsigned long long value_int;
 
index f6fcc68..9b141f1 100644 (file)
@@ -673,6 +673,8 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
        int err;
        union perf_event *event;
 
+       if (symbol_conf.kptr_restrict)
+               return -1;
        if (map == NULL)
                return -1;
 
index 20f9cb3..54c4ff2 100644 (file)
@@ -1933,17 +1933,17 @@ int setup_intlist(struct intlist **list, const char *list_str,
 static bool symbol__read_kptr_restrict(void)
 {
        bool value = false;
+       FILE *fp = fopen("/proc/sys/kernel/kptr_restrict", "r");
 
-       if (geteuid() != 0) {
-               FILE *fp = fopen("/proc/sys/kernel/kptr_restrict", "r");
-               if (fp != NULL) {
-                       char line[8];
+       if (fp != NULL) {
+               char line[8];
 
-                       if (fgets(line, sizeof(line), fp) != NULL)
-                               value = atoi(line) != 0;
+               if (fgets(line, sizeof(line), fp) != NULL)
+                       value = (geteuid() != 0) ?
+                                       (atoi(line) != 0) :
+                                       (atoi(line) == 2);
 
-                       fclose(fp);
-               }
+               fclose(fp);
        }
 
        return value;
index c2b61c4..0bf5085 100644 (file)
@@ -23,15 +23,14 @@ if [ ! -f events/sched/sched_process_fork/trigger ]; then
     exit_unsupported
 fi
 
-reset_tracer
-do_reset
-
-FEATURE=`grep hist events/sched/sched_process_fork/trigger`
-if [ -z "$FEATURE" ]; then
+if [ ! -f events/sched/sched_process_fork/hist ]; then
     echo "hist trigger is not supported"
     exit_unsupported
 fi
 
+reset_tracer
+do_reset
+
 echo "Test histogram with execname modifier"
 
 echo 'hist:keys=common_pid.execname' > events/sched/sched_process_fork/trigger
index b2902d4..a00184c 100644 (file)
@@ -23,15 +23,14 @@ if [ ! -f events/sched/sched_process_fork/trigger ]; then
     exit_unsupported
 fi
 
-reset_tracer
-do_reset
-
-FEATURE=`grep hist events/sched/sched_process_fork/trigger`
-if [ -z "$FEATURE" ]; then
+if [ ! -f events/sched/sched_process_fork/hist ]; then
     echo "hist trigger is not supported"
     exit_unsupported
 fi
 
+reset_tracer
+do_reset
+
 echo "Test histogram basic tigger"
 
 echo 'hist:keys=parent_pid:vals=child_pid' > events/sched/sched_process_fork/trigger
index 03c4a46..3478b00 100644 (file)
@@ -23,15 +23,14 @@ if [ ! -f events/sched/sched_process_fork/trigger ]; then
     exit_unsupported
 fi
 
-reset_tracer
-do_reset
-
-FEATURE=`grep hist events/sched/sched_process_fork/trigger`
-if [ -z "$FEATURE" ]; then
+if [ ! -f events/sched/sched_process_fork/hist ]; then
     echo "hist trigger is not supported"
     exit_unsupported
 fi
 
+reset_tracer
+do_reset
+
 reset_trigger
 
 echo "Test histogram multiple tiggers"
index 96ba386..4a82174 100644 (file)
@@ -111,9 +111,9 @@ static void attach_ebpf(int fd, uint16_t mod)
        memset(&attr, 0, sizeof(attr));
        attr.prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
        attr.insn_cnt = ARRAY_SIZE(prog);
-       attr.insns = (uint64_t)prog;
-       attr.license = (uint64_t)bpf_license;
-       attr.log_buf = (uint64_t)bpf_log_buf;
+       attr.insns = (unsigned long) &prog;
+       attr.license = (unsigned long) &bpf_license;
+       attr.log_buf = (unsigned long) &bpf_log_buf;
        attr.log_size = sizeof(bpf_log_buf);
        attr.log_level = 1;
        attr.kern_version = 0;
@@ -351,8 +351,8 @@ static void test_filter_no_reuseport(const struct test_params p)
        memset(&eprog, 0, sizeof(eprog));
        eprog.prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
        eprog.insn_cnt = ARRAY_SIZE(ecode);
-       eprog.insns = (uint64_t)ecode;
-       eprog.license = (uint64_t)bpf_license;
+       eprog.insns = (unsigned long) &ecode;
+       eprog.license = (unsigned long) &bpf_license;
        eprog.kern_version = 0;
 
        memset(&cprog, 0, sizeof(cprog));
index 932ff57..00c4f65 100644 (file)
@@ -136,7 +136,7 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size)
        printf("No of huge pages allocated = %d\n",
               (atoi(nr_hugepages)));
 
-       if (write(fd, initial_nr_hugepages, sizeof(initial_nr_hugepages))
+       if (write(fd, initial_nr_hugepages, strlen(initial_nr_hugepages))
            != strlen(initial_nr_hugepages)) {
                perror("Failed to write to /proc/sys/vm/nr_hugepages\n");
                goto close_fd;
index 6ba7455..6173ada 100644 (file)
@@ -1,6 +1,6 @@
 all:
 
-all: ring virtio_ring_0_9 virtio_ring_poll virtio_ring_inorder
+all: ring virtio_ring_0_9 virtio_ring_poll virtio_ring_inorder noring
 
 CFLAGS += -Wall
 CFLAGS += -pthread -O2 -ggdb
@@ -15,11 +15,13 @@ ring: ring.o main.o
 virtio_ring_0_9: virtio_ring_0_9.o main.o
 virtio_ring_poll: virtio_ring_poll.o main.o
 virtio_ring_inorder: virtio_ring_inorder.o main.o
+noring: noring.o main.o
 clean:
        -rm main.o
        -rm ring.o ring
        -rm virtio_ring_0_9.o virtio_ring_0_9
        -rm virtio_ring_poll.o virtio_ring_poll
        -rm virtio_ring_inorder.o virtio_ring_inorder
+       -rm noring.o noring
 
 .PHONY: all clean
index 34e94c4..d83707a 100644 (file)
@@ -1,2 +1,6 @@
 Partial implementation of various ring layouts, useful to tune virtio design.
 Uses shared memory heavily.
+
+Typical use:
+
+# sh run-on-all.sh perf stat -r 10 --log-fd 1 -- ./ring
diff --git a/tools/virtio/ringtest/noring.c b/tools/virtio/ringtest/noring.c
new file mode 100644 (file)
index 0000000..eda2f48
--- /dev/null
@@ -0,0 +1,69 @@
+#define _GNU_SOURCE
+#include "main.h"
+#include <assert.h>
+
+/* stub implementation: useful for measuring overhead */
+void alloc_ring(void)
+{
+}
+
+/* guest side */
+int add_inbuf(unsigned len, void *buf, void *datap)
+{
+       return 0;
+}
+
+/*
+ * skb_array API provides no way for producer to find out whether a given
+ * buffer was consumed.  Our tests merely require that a successful get_buf
+ * implies that add_inbuf succeed in the past, and that add_inbuf will succeed,
+ * fake it accordingly.
+ */
+void *get_buf(unsigned *lenp, void **bufp)
+{
+       return "Buffer";
+}
+
+void poll_used(void)
+{
+}
+
+void disable_call()
+{
+       assert(0);
+}
+
+bool enable_call()
+{
+       assert(0);
+}
+
+void kick_available(void)
+{
+       assert(0);
+}
+
+/* host side */
+void disable_kick()
+{
+       assert(0);
+}
+
+bool enable_kick()
+{
+       assert(0);
+}
+
+void poll_avail(void)
+{
+}
+
+bool use_buf(unsigned *lenp, void **bufp)
+{
+       return true;
+}
+
+void call_used(void)
+{
+       assert(0);
+}
index 52b0f71..2e69ca8 100755 (executable)
@@ -3,10 +3,10 @@
 #use last CPU for host. Why not the first?
 #many devices tend to use cpu0 by default so
 #it tends to be busier
-HOST_AFFINITY=$(cd /dev/cpu; ls|grep -v '[a-z]'|sort -n|tail -1)
+HOST_AFFINITY=$(lscpu -p=cpu | tail -1)
 
 #run command on all cpus
-for cpu in $(cd /dev/cpu; ls|grep -v '[a-z]'|sort -n);
+for cpu in $(seq 0 $HOST_AFFINITY)
 do
        #Don't run guest and host on same CPU
        #It actually works ok if using signalling
index 1889163..7cf6e17 100644 (file)
@@ -492,7 +492,7 @@ static void slab_stats(struct slabinfo *s)
                        s->deactivate_to_head + s->deactivate_to_tail + s->deactivate_bypass;
 
        if (total) {
-               printf("\nSlab Deactivation             Ocurrences  %%\n");
+               printf("\nSlab Deactivation             Occurrences %%\n");
                printf("-------------------------------------------------\n");
                printf("Slab full                     %7lu  %3lu%%\n",
                        s->deactivate_full, (s->deactivate_full * 100) / total);
index a3f12b3..3a3a699 100644 (file)
@@ -100,12 +100,11 @@ static void __hyp_text save_lrs(struct kvm_vcpu *vcpu, void __iomem *base)
                if (!(vcpu->arch.vgic_cpu.live_lrs & (1UL << i)))
                        continue;
 
-               if (cpu_if->vgic_elrsr & (1UL << i)) {
+               if (cpu_if->vgic_elrsr & (1UL << i))
                        cpu_if->vgic_lr[i] &= ~GICH_LR_STATE;
-                       continue;
-               }
+               else
+                       cpu_if->vgic_lr[i] = readl_relaxed(base + GICH_LR0 + (i * 4));
 
-               cpu_if->vgic_lr[i] = readl_relaxed(base + GICH_LR0 + (i * 4));
                writel_relaxed(0, base + GICH_LR0 + (i * 4));
        }
 }
index 059595e..9f6fab7 100644 (file)
@@ -191,10 +191,8 @@ static void vgic_mmio_change_active(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
         * other thread sync back the IRQ.
         */
        while (irq->vcpu && /* IRQ may have state in an LR somewhere */
-              irq->vcpu->cpu != -1) { /* VCPU thread is running */
-               BUG_ON(irq->intid < VGIC_NR_PRIVATE_IRQS);
+              irq->vcpu->cpu != -1) /* VCPU thread is running */
                cond_resched_lock(&irq->irq_lock);
-       }
 
        irq->active = new_active_state;
        if (new_active_state)
index 8ad42c2..e31405e 100644 (file)
@@ -112,11 +112,15 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
                        }
                }
 
-               /* Clear soft pending state when level IRQs have been acked */
-               if (irq->config == VGIC_CONFIG_LEVEL &&
-                   !(val & GICH_LR_PENDING_BIT)) {
-                       irq->soft_pending = false;
-                       irq->pending = irq->line_level;
+               /*
+                * Clear soft pending state when level irqs have been acked.
+                * Always regenerate the pending state.
+                */
+               if (irq->config == VGIC_CONFIG_LEVEL) {
+                       if (!(val & GICH_LR_PENDING_BIT))
+                               irq->soft_pending = false;
+
+                       irq->pending = irq->line_level || irq->soft_pending;
                }
 
                spin_unlock(&irq->irq_lock);
index 336a461..346b4ad 100644 (file)
@@ -101,11 +101,15 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
                        }
                }
 
-               /* Clear soft pending state when level irqs have been acked */
-               if (irq->config == VGIC_CONFIG_LEVEL &&
-                   !(val & ICH_LR_PENDING_BIT)) {
-                       irq->soft_pending = false;
-                       irq->pending = irq->line_level;
+               /*
+                * Clear soft pending state when level irqs have been acked.
+                * Always regenerate the pending state.
+                */
+               if (irq->config == VGIC_CONFIG_LEVEL) {
+                       if (!(val & ICH_LR_PENDING_BIT))
+                               irq->soft_pending = false;
+
+                       irq->pending = irq->line_level || irq->soft_pending;
                }
 
                spin_unlock(&irq->irq_lock);
index fe84e1a..8db197b 100644 (file)
@@ -40,7 +40,7 @@ int kvm_irq_map_gsi(struct kvm *kvm,
 
        irq_rt = srcu_dereference_check(kvm->irq_routing, &kvm->irq_srcu,
                                        lockdep_is_held(&kvm->irq_lock));
-       if (gsi < irq_rt->nr_rt_entries) {
+       if (irq_rt && gsi < irq_rt->nr_rt_entries) {
                hlist_for_each_entry(e, &irq_rt->map[gsi], link) {
                        entries[n] = *e;
                        ++n;
index 37af230..48bd520 100644 (file)
@@ -2935,25 +2935,27 @@ static long kvm_vm_ioctl(struct file *filp,
        case KVM_SET_GSI_ROUTING: {
                struct kvm_irq_routing routing;
                struct kvm_irq_routing __user *urouting;
-               struct kvm_irq_routing_entry *entries;
+               struct kvm_irq_routing_entry *entries = NULL;
 
                r = -EFAULT;
                if (copy_from_user(&routing, argp, sizeof(routing)))
                        goto out;
                r = -EINVAL;
-               if (routing.nr >= KVM_MAX_IRQ_ROUTES)
+               if (routing.nr > KVM_MAX_IRQ_ROUTES)
                        goto out;
                if (routing.flags)
                        goto out;
-               r = -ENOMEM;
-               entries = vmalloc(routing.nr * sizeof(*entries));
-               if (!entries)
-                       goto out;
-               r = -EFAULT;
-               urouting = argp;
-               if (copy_from_user(entries, urouting->entries,
-                                  routing.nr * sizeof(*entries)))
-                       goto out_free_irq_routing;
+               if (routing.nr) {
+                       r = -ENOMEM;
+                       entries = vmalloc(routing.nr * sizeof(*entries));
+                       if (!entries)
+                               goto out;
+                       r = -EFAULT;
+                       urouting = argp;
+                       if (copy_from_user(entries, urouting->entries,
+                                          routing.nr * sizeof(*entries)))
+                               goto out_free_irq_routing;
+               }
                r = kvm_set_irq_routing(kvm, entries, routing.nr,
                                        routing.flags);
 out_free_irq_routing: